抓取微博数据:使用HtmlUnitDriver实现模拟登陆


前言

作为小白的我而言,对于各种网络数据抓取也不少了,但是在抓取过程之中坑点也不少的,这里就分享一下对于需要登陆的网页的处理,我们整体思路是这样的,我们通过对该网站的登录之后拿到该网站的Cookie,然后拿着获取到的Cookie再去我们想要爬取的地址进行数据爬取.


Selenium简介

Selenium是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera等。

而我用到的HtmlUnitDriverSelenium众多工具中一个基于HtmlUnit的无界面实现,即使用HtmlUnit时并不会打开真实的浏览器,而是在内存中执行代码,因此运行速度很快,但是对JavaScript的支持不够好,当页面上有复杂的JavaScript元素时,经常捕捉不到。

当我们需要Selenium的时候,我们可以添加Maven依赖.如下所示.

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>3.4.0</version>
</dependency>


HtmlUnitDriver的鼠标和键盘事件

我们平常在普通一个网站登录的时候都会使用到我们的键盘和鼠标来进行一系列的用户交互操作.那么我们在HtmlUnitDriver该如何实现键盘的输入和鼠标的点击呢?在其实现的接口类WebDeriver中有一个专门的类来负责实现这些测试场景,那就是 Actions 类,在使用该类的过程中会配合使用到 Keys 枚举以及 Mouse、 Keyboard、CompositeAction 等类。下面我就分别简单介绍鼠标事件和键盘事件的实现.


鼠标事件

  • 鼠标左键点击
Actions action = new Actions(driver);
action.click();// 鼠标左键在当前停留的位置做单击操作 
action.click(driver.findElement(By.name(element)))// 鼠标左键点击指定的元素
  • 鼠标右键点击
Actions action = new Actions(driver); 
action.contextClick();// 鼠标右键在当前停留的位置做单击操作 
action.contextClick(driver.findElement(By.name(element)))// 鼠标右键点击指定的元素
  • 鼠标双击操作
Actions action = new Actions(driver); 
action.doubleClick();// 鼠标在当前停留的位置做双击操作 
action.doubleClick(driver.findElement(By.name(element)))// 鼠标双击指定的元素
  • 鼠标拖拽动作
Actions action = new Actions(driver); 
// 鼠标拖拽动作,将 source 元素拖放到 target 元素的位置。
action.dragAndDrop(source,target);
// 鼠标拖拽动作,将 source 元素拖放到 (xOffset, yOffset) 位置,其中 xOffset 为横坐标,yOffset 为纵坐标。
action.dragAndDrop(source,xOffset,yOffset);
  • 释放鼠标
Actions action = new Actions(driver); 
action.release();// 释放鼠标


键盘事件

对于键盘的模拟操作,Actions 类中有提供 keyUp(theKey)、keyDown(theKey)、sendKeys(keysToSend) 等方法来实现。键盘的操作有普通键盘和修饰键盘(Modifier Keys, 下面的章节将讲到修饰键的概念)两种 :

  • 普通键盘模拟 sendKeys(keysToSend)
Actions action = new Actions(driver); 
action.sendKeys(Keys.TAB);// 模拟按下并释放 TAB 键
action.sendKeys(Keys.SPACE);// 模拟按下并释放空格键
/***
针对某个元素发出某个键盘的按键操作,或者是输入操作,
比如在 input 框中输入某个字符也可以使用这个方法。这个方法也可以拆分成:
action.click(element).sendKeys(keysToSend)。
*/
action.sendKeys(element,keysToSend);
  • 对于修饰键(Modifier keys),一般都是跟普通键组合使用的。比如 Ctrl+a、Alt+F4、 Shift+Ctrl+F 等等。
Actions action = new Actions(driver); 
action.keyDown(Keys.CONTROL);// 按下 Ctrl 键
action.keyDown(Keys.SHIFT);// 按下 Shift 键
action.keyDown(Key.ALT);// 按下 Alt 键
action.keyUp(Keys.CONTROL);// 释放 Ctrl 键
action.keyUp(Keys.SHIFT);// 释放 Shift 键
action.keyUp(Keys.ALT);// 释放 Alt 键

示例:通过 Alt+F4 来关闭当前的活动窗口,可以通过下面语句来实现.

action.keyDown(Keys.ALT).keyDown(Keys.F4).keyUp(Keys.ALT).perform();`


使用 HtmlUnitDriver 模拟登录微博账号(基于Selenium:3.4.0实现)

上面我们对HtmlUnitDriver的使用有了初步的了解,下面我们就要模拟登录微博账号.由于数据抓取是通过www.weibo.cn而不是www.weibo.com.所以我们要通过https://passport.weibo.cn/signin/login这个登录地址来登录.我们首先要打开这个网站地址,分析这个网站有什么是我们需要.网站上的元素很少.我们需要账号输入框密码输入框登录按钮的点击事件.

然后我们通过控制台来获取这个三个元素.如下所示.(因为我先前登陆过,所以Cookie里面会有我的信息)

好了,准备工作已经做完了,那么接下来我们就需要搞我们的代码了.代码比较简单,这里就不过多解释了.

            //初始化一个HtmlUnitDriver对象
            HtmlUnitDriver driver = new HtmlUnitDriver(BrowserVersion.FIREFOX_52);
            driver.setJavascriptEnabled(true);//允许JS操作
            driver.get("https://passport.weibo.cn/signin/login");
            driver.executeScript("document.getElementById('loginWrapper').style.display = 'block'");//隐藏新浪微博登录的验证码
            //找到账号输入框,输入用户账号
            WebElement mobile = driver.findElementByCssSelector("input#loginName");
            mobile.sendKeys(username);
            //找到密码输入框,输入用户密码
            WebElement pass = driver.findElementByCssSelector("input#loginPassword");
            pass.sendKeys(password);
            //输入完成之后,点击登录按钮
            WebElement submit = driver.findElementByCssSelector("a#loginAction");
            submit.click();
            driver.close();//关闭浏览器

那么我们该如何拿到Cookie字符串呢?这里登录完成之后,HtmlUnitDriver就存储了Cookie信息,我们直接拿出来就行,代码如下所示.

            Set<Cookie> cookieSet = driver.manage().getCookies();
            StringBuilder sb = new StringBuilder();
            for (Cookie cookie : cookieSet) {
                sb.append(cookie.getName() + "=" + cookie.getValue() + ";");
            }
            String result = sb.toString();//拼接好的Cookie信息

整体代码如下所示.

     public static String getSinaCookie(String username, String password) throws Exception {
            //初始化一个HtmlUnitDriver对象
            HtmlUnitDriver driver = new HtmlUnitDriver(BrowserVersion.FIREFOX_52);
            driver.setJavascriptEnabled(true);//允许JS操作
            driver.get("https://passport.weibo.cn/signin/login");
            driver.executeScript("document.getElementById('loginWrapper').style.display = 'block'");//隐藏新浪微博登录的验证码
            //找到账号输入框,输入用户账号
            WebElement mobile = driver.findElementByCssSelector("input#loginName");
            mobile.sendKeys(username);
            //找到密码输入框,输入用户密码
            WebElement pass = driver.findElementByCssSelector("input#loginPassword");
            pass.sendKeys(password);
            //输入完成之后,点击登录按钮
            WebElement submit = driver.findElementByCssSelector("a#loginAction");
            submit.click();
            String result = concatCookie(driver);
            System.out.println("Get Cookie: " + result);
            driver.close();//关闭浏览器

            if (result.contains("SUB")) {
                return result;
            } else {
                throw new Exception("weibo login failed");
            }
        }

        public static String concatCookie(HtmlUnitDriver driver) {
            Set<Cookie> cookieSet = driver.manage().getCookies();
            StringBuilder sb = new StringBuilder();
            for (Cookie cookie : cookieSet) {
                sb.append(cookie.getName() + "=" + cookie.getValue() + ";");
            }
            String result = sb.toString();
            return result;
        }

通过控制台的打印,我们就能获得我们所需要的Cookie字符串了.如下所示.


总结

这篇博客写到这就到了尾声了,有一点要注意,那就是使用HtmlUnitDriver时候,可能会链接失败,现在未找到原因,希望有知道的大佬能提点下.文章很多点都可能模糊不清,所以如果有错误,欢迎指导批评,非常感谢各位大佬.

本文参考文章:
Selenium WebDriver 中鼠标和键盘事件分析及扩展
Java开源爬虫框架WebCollector教程——爬取新浪微博



最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,951评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,606评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,601评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,478评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,565评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,587评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,590评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,337评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,785评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,096评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,273评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,935评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,578评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,199评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,440评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,163评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,133评论 2 352

推荐阅读更多精彩内容