动态网页爬取例子(WebCollector+selenium+phantomjs)
目标:动态网页爬取
说明:这里的动态网页指几种可能:1)需要用户交互,如常见的登录操作;2)网页通过JS /
AJAX动态生成,如一个html里有<div id="test"></div>,通过JS生成<div
id="test"><span>aaa</span></div>。
这里用了WebCollector 2进行爬虫,这东东也方便,不过要支持动态关键还是要靠另外一个API -- selenium 2(集成htmlunit 和 phantomjs).
1)需要登录后的爬取,如新浪微博
- import java.util.Set;
- import cn.edu.hfut.dmic.webcollector.crawler.DeepCrawler;
- import cn.edu.hfut.dmic.webcollector.model.Links;
- import cn.edu.hfut.dmic.webcollector.model.Page;
- import cn.edu.hfut.dmic.webcollector.net.HttpRequesterImpl;
- import org.openqa.selenium.Cookie;
- import org.openqa.selenium.WebElement;
- import org.openqa.selenium.htmlunit.HtmlUnitDriver;
- import org.jsoup.nodes.Element;
- import org.jsoup.select.Elements;
- /*
- * 登录后爬取
- * Refer: http://nutcher.org/topics/33
- * https://github.com/CrawlScript/WebCollector/blob/master/README.zh-cn.md
- * Lib required: webcollector-2.07-bin, selenium-java-2.44.0 & its lib
- */
- public class WebCollector1 extends DeepCrawler {
- public WebCollector1(String crawlPath) {
- super(crawlPath);
- /*获取新浪微博的cookie,账号密码以明文形式传输,请使用小号*/
- try {
- String cookie=WebCollector1.WeiboCN.getSinaCookie("yourAccount", "yourPwd");
- HttpRequesterImpl myRequester=(HttpRequesterImpl) this.getHttpRequester();
- myRequester.setCookie(cookie);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- @Override
- public Links visitAndGetNextLinks(Page page) {
- /*抽取微博*/
- Elements weibos=page.getDoc().select("div.c");
- for(Element weibo:weibos){
- System.out.println(weibo.text());
- }
- /*如果要爬取评论,这里可以抽取评论页面的URL,返回*/
- return null;
- }
- public static void main(String[] args) {
- WebCollector1 crawler=new WebCollector1("/home/hu/data/weibo");
- crawler.setThreads(3);
- /*对某人微博前5页进行爬取*/
- for(int i=0;i<5;i++){
- crawler.addSeed("http://weibo.cn/zhouhongyi?vt=4&page="+i);
- }
- try {
- crawler.start(1);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public static class WeiboCN {
- /**
- * 获取新浪微博的cookie,这个方法针对weibo.cn有效,对weibo.com无效
- * weibo.cn以明文形式传输数据,请使用小号
- * @param username 新浪微博用户名
- * @param password 新浪微博密码
- * @return
- * @throws Exception
- */
- public static String getSinaCookie(String username, String password) throws Exception{
- StringBuilder sb = new StringBuilder();
- HtmlUnitDriver driver = new HtmlUnitDriver();
- driver.setJavascriptEnabled(true);
- driver.get("http://login.weibo.cn/login/");
- WebElement mobile = driver.findElementByCssSelector("input[name=mobile]");
- mobile.sendKeys(username);
- WebElement pass = driver.findElementByCssSelector("input[name^=password]");
- pass.sendKeys(password);
- WebElement rem = driver.findElementByCssSelector("input[name=remember]");
- rem.click();
- WebElement submit = driver.findElementByCssSelector("input[name=submit]");
- submit.click();
- Set<Cookie> cookieSet = driver.manage().getCookies();
- driver.close();
- for (Cookie cookie : cookieSet) {
- sb.append(cookie.getName()+"="+cookie.getValue()+";");
- }
- String result=sb.toString();
- if(result.contains("gsid_CTandWM")){
- return result;
- }else{
- throw new Exception("weibo login failed");
- }
- }
- }
- }
* 这里有个自定义路径/home/hu/data/weibo(WebCollector1 crawler=new WebCollector1("/home/hu/data/weibo");),是用来保存到嵌入式数据库Berkeley DB。
* 总体上来自Webcollector 作者的sample。
2)JS动态生成HTML元素的爬取
- import java.util.List;
- import org.openqa.selenium.By;
- import org.openqa.selenium.WebDriver;
- import org.openqa.selenium.WebElement;
- import cn.edu.hfut.dmic.webcollector.crawler.DeepCrawler;
- import cn.edu.hfut.dmic.webcollector.model.Links;
- import cn.edu.hfut.dmic.webcollector.model.Page;
- /*
- * JS爬取
- * Refer: http://blog.csdn.net/smilings/article/details/7395509
- */
- public class WebCollector3 extends DeepCrawler {
- public WebCollector3(String crawlPath) {
- super(crawlPath);
- // TODO Auto-generated constructor stub
- }
- @Override
- public Links visitAndGetNextLinks(Page page) {
- /*HtmlUnitDriver可以抽取JS生成的数据*/
- // HtmlUnitDriver driver=PageUtils.getDriver(page,BrowserVersion.CHROME);
- // String content = PageUtils.getPhantomJSDriver(page);
- WebDriver driver = PageUtils.getWebDriver(page);
- // List<WebElement> divInfos=driver.findElementsByCssSelector("#feed_content");
- List<WebElement> divInfos=driver.findElements(By.cssSelector("#feed_content span"));
- for(WebElement divInfo:divInfos){
- System.out.println("Text是:" + divInfo.getText());
- }
- return null;
- }
- public static void main(String[] args) {
- WebCollector3 crawler=new WebCollector3("/home/hu/data/wb");
- for(int page=1;page<=5;page++)
- // crawler.addSeed("http://www.sogou.com/web?query="+URLEncoder.encode("编程")+"&page="+page);
- crawler.addSeed("http://cq.qq.com/baoliao/detail.htm?294064");
- try {
- crawler.start(1);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
PageUtils.java
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import org.openqa.selenium.JavascriptExecutor;
- import org.openqa.selenium.WebDriver;
- import org.openqa.selenium.chrome.ChromeDriver;
- import org.openqa.selenium.htmlunit.HtmlUnitDriver;
- import org.openqa.selenium.ie.InternetExplorerDriver;
- import org.openqa.selenium.phantomjs.PhantomJSDriver;
- import com.gargoylesoftware.htmlunit.BrowserVersion;
- import cn.edu.hfut.dmic.webcollector.model.Page;
- public class PageUtils {
- public static HtmlUnitDriver getDriver(Page page) {
- HtmlUnitDriver driver = new HtmlUnitDriver();
- driver.setJavascriptEnabled(true);
- driver.get(page.getUrl());
- return driver;
- }
- public static HtmlUnitDriver getDriver(Page page, BrowserVersion browserVersion) {
- HtmlUnitDriver driver = new HtmlUnitDriver(browserVersion);
- driver.setJavascriptEnabled(true);
- driver.get(page.getUrl());
- return driver;
- }
- public static WebDriver getWebDriver(Page page) {
- // WebDriver driver = new HtmlUnitDriver(true);
- // System.setProperty("webdriver.chrome.driver", "D:\\Installs\\Develop\\crawling\\chromedriver.exe");
- // WebDriver driver = new ChromeDriver();
- System.setProperty("phantomjs.binary.path", "D:\\Installs\\Develop\\crawling\\phantomjs-2.0.0-windows\\bin\\phantomjs.exe");
- WebDriver driver = new PhantomJSDriver();
- driver.get(page.getUrl());
- // JavascriptExecutor js = (JavascriptExecutor) driver;
- // js.executeScript("function(){}");
- return driver;
- }
- public static String getPhantomJSDriver(Page page) {
- Runtime rt = Runtime.getRuntime();
- Process process = null;
- try {
- process = rt.exec("D:\\Installs\\Develop\\crawling\\phantomjs-2.0.0-windows\\bin\\phantomjs.exe " +
- "D:\\workspace\\crawlTest1\\src\\crawlTest1\\parser.js " +
- page.getUrl().trim());
- InputStream in = process.getInputStream();
- InputStreamReader reader = new InputStreamReader(
- in, "UTF-8");
- BufferedReader br = new BufferedReader(reader);
- StringBuffer sbf = new StringBuffer();
- String tmp = "";
- while((tmp = br.readLine())!=null){
- sbf.append(tmp);
- }
- return sbf.toString();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return null;
- }
- }
2.1)HtmlUnitDriver getDriver是selenium 1.x的作法,已经outdate了,现在用WebDriver getWebDriver
2.2)这里用了几种方法:HtmlUnitDriver, ChromeDriver, PhantomJSDriver,
PhantomJS,参考 http://blog.csdn.net/five3/article/details/19085303,各自之间的优缺
点如下:
| driver类型 | 优点 | 缺点 | 应用 |
| 真实浏览器driver | 真实模拟用户行为 | 效率、稳定性低 | 兼容性测试 |
| HtmlUnit | 速度快 | js引擎不是主流的浏览器支持的 | 包含少量js的页面测试 |
| PhantomJS | 速度中等、模拟行为接近真实 | 不能模拟不同/特定浏览器的行为 | 非GUI的功能性测试 |
* 真实浏览器driver 包括 Firefox, Chrome, IE
2.3)用PhantomJSDriver的时候,遇上错
误:ClassNotFoundException: org.openqa.selenium.browserlaunchers.Proxies,原
因竟然是selenium 2.44 的bug,后来通过maven找到phantomjsdriver-1.2.1.jar 才解决了。
2.4)另外,我还试了PhantomJS 原生调用(也就是不用selenium,直接调用PhantomJS,见上面的方法),原生要调用JS,这里的parser.js代码如下:
- system = require('system')
- address = system.args[1];//获得命令行第二个参数 接下来会用到
- //console.log('Loading a web page');
- var page = require('webpage').create();
- var url = address;
- //console.log(url);
- page.open(url, function (status) {
- //Page is loaded!
- if (status !== 'success') {
- console.log('Unable to post!');
- } else {
- //此处的打印,是将结果一流的形式output到java中,java通过InputStream可以获取该输出内容
- console.log(page.content);
- }
- phantom.exit();
- });
3)后话
3.1)HtmlUnitDriver + PhantomJSDriver是当前最可靠的动态抓取方案。
3.2)这过程中用到很多包、exe,遇到很多的墙~,有需要的朋友可以找我要。
Reference
http://www.ibm.com/developerworks/cn/web/1309_fengyq_seleniumvswebdriver/
http://blog.csdn.net/smilings/article/details/7395509
http://phantomjs.org/download.html
http://blog.csdn.net/five3/article/details/19085303
http://phantomjs.org/quick-start.html
动态网页爬取例子(WebCollector+selenium+phantomjs)的更多相关文章
- Node.js 动态网页爬取 PhantomJS 使用入门(转)
Node.js 动态网页爬取 PhantomJS 使用入门 原创NeverSettle101 发布于2017-03-24 09:34:45 阅读数 8309 收藏 展开 版权声明:本文为 winte ...
- python动态网页爬取——四六级成绩批量爬取
需求: 四六级成绩查询网站我所知道的有两个:学信网(http://www.chsi.com.cn/cet/)和99宿舍(http://cet.99sushe.com/),这两个网站采用的都是动态网页. ...
- 爬虫入门(三)——动态网页爬取:爬取pexel上的图片
Pexel上有大量精美的图片,没事总想看看有什么好看的自己保存到电脑里可能会很有用 但是一个一个保存当然太麻烦了 所以不如我们写个爬虫吧(๑•̀ㅂ•́)و✧ 一开始学习爬虫的时候希望爬取pexel上的 ...
- 动态网页爬取样例(WebCollector+selenium+phantomjs)
目标:动态网页爬取 说明:这里的动态网页指几种可能:1)须要用户交互,如常见的登录操作:2)网页通过JS / AJAX动态生成.如一个html里有<div id="test" ...
- Python开发爬虫之动态网页抓取篇:爬取博客评论数据——通过Selenium模拟浏览器抓取
区别于上篇动态网页抓取,这里介绍另一种方法,即使用浏览器渲染引擎.直接用浏览器在显示网页时解析 HTML.应用 CSS 样式并执行 JavaScript 的语句. 这个方法在爬虫过程中会打开一个浏览器 ...
- 【图文详解】scrapy爬虫与动态页面——爬取拉勾网职位信息(2)
上次挖了一个坑,今天终于填上了,还记得之前我们做的拉勾爬虫吗?那时我们实现了一页的爬取,今天让我们再接再厉,实现多页爬取,顺便实现职位和公司的关键词搜索功能. 之前的内容就不再介绍了,不熟悉的请一定要 ...
- 爬虫系列5:scrapy动态页面爬取的另一种思路
前面有篇文章给出了爬取动态页面的一种思路,即应用Selenium+Firefox(参考<scrapy动态页面爬取>).但是selenium需要运行本地浏览器,比较耗时,不太适合大规模网页抓 ...
- python网络爬虫-动态网页抓取(五)
动态抓取的实例 在开始爬虫之前,我们需要了解一下Ajax(异步请求).它的价值在于在与后台进行少量的数据交换就可以使网页实现异步更新. 如果使用Ajax加载的动态网页抓取,有两种方法: 通过浏览器审查 ...
- 使用urllib进行网页爬取
# coding=gbk # 抓取开奖号码 # url:http://datachart.500.com/dlt/zoushi/jbzs_foreback.shtml ''' 对网页逐行迭代,找到目标 ...
随机推荐
- 转换GridView的内容到Excel里面 ---带有格式
http://www.aspsnippets.com/Articles/Export-GridView-to-Excel-in-ASPNet-with-Formatting-using-C-and-V ...
- Android中的一些基础知识(三)
最近在回顾Android的基础知识,就把一些常见的知识点整理一下,以后忘了也可以翻出来看一看. 在TextView中显示图像(使用< img>标签) 在TextView中显示图片的方法有许 ...
- LeetCode 链表的插入排序
Sort a linked list using insertion sort 创建一个新的链表,将旧链表的节点插入到正确的位置 package cn.edu.algorithm.huawei; pu ...
- Null指针
C++ Null 指针 C++ 指针 C++ 指针 在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯.赋为 NULL 值的指针被称为空指针. NULL ...
- Java学习03
Java学习03 1.java面试一些问题 一.什么是变量 变量是指在程序执行期间可变的数据.类中的变量是用来表示累的属性的,在编程过程中,可以对变量的值进行修改.变量通常是可变的,即值是变化的 二. ...
- mac下 配置 Apache Php Mysql
参考 http://www.guomii.com/posts/30136 参考 http://forums.mysql.com/read.php?11,600754,600754 MacOS 10.8 ...
- ASP.NET MVC3中的路由系统 Routes
MVC中,用户访问的地址并不映射到服务器中对应的文件,而是映射到对应Control里对应的ActionMethod,由ActionMethod来决定返回用户什么样的信息.而把用户访问的地址对应到对应的 ...
- 用SQL实现统计报表中的"小计"与"合计"的方法详解
本篇文章是对使用SQL实现统计报表中的"小计"与"合计"的方法进行了详细的分析介绍,需要的朋友参考下 客户提出需求,针对某一列分组加上小计,合计汇总.网上找 ...
- 转:FileReader详解与实例---读取并显示图像文件
~~~针对需要读取本地图像,并立即显示在浏览器的情况,由于chrome firefox出于安全限制,input file并不返回文件的真实路径,经测试IE6/7/8都会返回真实路径,所以chrome, ...
- IT第六天 - eclipse快捷操作、万年历项目的编写、菱形的打印输出、代码简化
IT第六天 上午 小项目 1.程序提前结束的退出标志 2.登录用户的模拟,给出适当的提示信息 3.根据要求,寻找规律,然后编写程序 Eclipse的使用 1.快捷键的使用 下午 中小项目 1.九九乘法 ...