文档章节

ajax动态网页爬取总结

_liucui_
 _liucui_
发布于 2015/07/07 16:04
字数 1813
阅读 238
收藏 1

这几天对JS动态网页的爬取做了一下研究,主要涉及到的对象有HtmlUnitHttpUnitSelenium WebDriverCasperJsHttpClient模拟等操作。我们可以通过对天猫商品的促销价爬取来对他们进行下对比。

测试网页如下:

http://detail.tmall.com/item.htm?spm=0.0.0.0.HkxFxe&id=520129049356

促销价在天猫的网站上是动态生成的,在源码中是看不到的。

1 HtmlUnit

HtmlUnit是一款开源的Java 页面分析工具,读取页面后,可以有效的使用HtmlUnit分析页面上的内容。项目可以模拟浏览器运行,被誉为java浏览器的开源实现。它对于动态生成的数据提供了支持,使我们能够得到ajax执行后的源代码。而且它操作简单只需将相关的jar包引入便可使用。

测试代码:

public class HtmlUnitTest {

String url = "http://detail.tmall.com/item.htm?spm=0.0.0.0.HkxFxe&id=520129049356";

static WebClient webClient;

 

@BeforeClass

public static void init() {

// 指定浏览器,并指定浏览器模拟的版本;

webClient = new WebClient(BrowserVersion.CHROME);

// webclient参数载体

WebClientOptions clientOptions = webClient.getOptions();

ProxyConfig proxyConfig = new ProxyConfig();

proxyConfig.setProxyHost("proxy.asiainfo.com");

proxyConfig.setProxyPort(8080);

// 设置webClient的相关参数

clientOptions.setJavaScriptEnabled(true);

clientOptions.setCssEnabled(false);

clientOptions.setTimeout(10000);

clientOptions.setThrowExceptionOnScriptError(false);

clientOptions.setProxyConfig(proxyConfig);

webClient.setAjaxController(new NicelyResynchronizingAjaxController());

}

 

@Test

public void test() {

long start = System.currentTimeMillis();

// 模拟浏览器打开一个目标网址

HtmlPage rootPage;

try {

rootPage = webClient.getPage(url);

     HtmlElement htmlElement = rootPage.getBody();

     String xmlContent = htmlElement.asXml();

long end = System.currentTimeMillis();

System.out.println("time:" + (end - start));

System.out.println(xmlContent);

// 测试js生成的部分是否加载成功

Document doc = Jsoup.parse(xmlContent);

Elements select = doc.select("#J_PromoPrice .tm-price");

if (select != null && select.size() > 0) {

String text = select.get(0).text();

System.out.println(text);

}

catch (FailingHttpStatusCodeException e) {

e.printStackTrace();

catch (MalformedURLException e) {

e.printStackTrace();

catch (IOException e) {

e.printStackTrace();

}

}

}

执行结果:

通过代码及测试我们会发现,它简单易用,但是在抓取时间上耗时还是很多的。

2 HttpUnit

上面谈到HtmlUnit我们还要提一下这个HttpUnit,名字相似、功能相似,如果不注意往往会混淆。网上搜索HttpUnit的官方文档,你会发现它的版本已经有好几年没有更新了,而且对ajax动态数据的解析不支持,无法解决我们现有的问题,放弃。

3 Selenium WebDriver

现在的网络访问不了官方网站,只能从其他地方收集一些资料,它包含了多种Driver,如下图所示:

1HtmlUnitDriver

从这些子类中我们可以看出Selenium包含了HtmlUnitDriver,通过查看源码以及使用发现它实际上就是调用的HtmlUnit的部分方法,不过与HtmlUnit不同的是它并没有提供Ajax支持,因此对于天猫这类的网页它是解析不了促销价格的。

2)各种浏览器Driver

我们在使用时,不同的浏览器需要配置不同的参数来指定浏览器的安装路径。每次初始化操作都会打开一个浏览器。下面让我们以火狐浏览器为例:

测试代码:

public class SelenimuWebDriverTest {

WebDriver webDriver;

String url = "http://detail.tmall.com/item.htm?spm=0.0.0.0.HkxFxe&id=520129049356";

 

@Before

public void setUp() {

DesiredCapabilities capability = DesiredCapabilities.firefox();

capability.setCapability("firefox_binary""E:\\Program Files\\Mozilla Firefox\\firefox.exe");

webDriver = new FirefoxDriver(capability);// 初始化一个火狐浏览器

webDriver.manage().window().maximize(); // 最大化浏览器

}

 

@Test

public void test1() throws Exception {

long start = System.currentTimeMillis();

webDriver.get(url);

String pageSource = webDriver.getPageSource();

long end = System.currentTimeMillis();

System.out.println("time:" + (end - start));

Document doc = Jsoup.parse(pageSource);

Elements select = doc.select("#J_PromoPrice .tm-price");

if (select != null && select.size() > 0) {

String result = select.get(0).text();

System.out.println(result);

else {

System.out.println("no result");

}

webDriver.close();

}

}

执行结果:

 

从网页的抓取时间上来说,它的效率还是可以的,初始化浏览器的过程我们需要注意防止浏览器打开过多,以免耗时且耗资源。并且这个在使用的时候有时候打开浏览器的时候会提示导入向导,这种还需要调整浏览器的配置参数。

3PhantomJSDriver

PhantomJSDriver的使用非常简单、接近真实浏览器且不需要打开浏览器,因此,直接创建一个PhantomJSDriver对象就可以用了。前提是需要安装phantomjs并且配置好环境变量,不过这一步是非常简单的。

测试代码:

@Before

public void setUp() {

webDriver = new PhantomJSDriver();

}

//其他同上

结果:

这个用起来还是很方便的,不知道是否是网络的原因,测试过程中抓取时间的变化在2s-7s范围波动,从抓取来看时间也不是最慢的,简单易用。

4 CasperJs

由于最先研究的是这个东西,在此还是要先简单说一下吧。

CasperJS[1] 是一个开源的导航脚本处理和测试工具,基于PhantomJS(前端自动化测试工具)编写。CasperJS简化了完整的导航场景的过程定义,提供了用于完成常见任务的实用的高级函数、方法和语法。它的写法与JSJquery的方法类似,我们可以在他的脚本中使用js或者Jquery的函数。

由于官方文档写的不是很详细,因此对于初学者来说也是有一定难度的。且它的抓取效率也是秒级的。由于它不是Java编写的,因此我们需要通过相关的方法来调用脚本。它是基于PhantomJS的,因此我们也需要安装PhantomJS,配置相关的环境变量。

官方地址http://docs.casperjs.org/en/latest/installation.html

调用CasperJs的脚本,来得到页面源代码,示例代码如下:

public static void useSperjs() {

String url = "http://detail.tmall.com/item.htm?spm=a220m.1000858.1000725.1.MbFIev&id=45844061725&skuId=93180315832&areaId=110000&cat_id=52810004&rn=21d1496d974e4f9984611fad013f1696&user_id=728628560&is_b=1";

long start = System.currentTimeMillis();

try {

Process exec = Runtime.getRuntime().exec("casperjs D:/jade/casperjs/jadeFile/test.js --url=" + url);

InputStream in = exec.getInputStream();

InputStreamReader isr = new InputStreamReader(in"gbk");

BufferedReader br = new BufferedReader(isr);

String line = null;

StringBuilder sb = new StringBuilder();

while ((line = br.readLine()) != null) {

sb.append(line + "\n\r");

}

System.out.println(sb.toString());

catch (IOException e) {

e.printStackTrace();

}

long end = System.currentTimeMillis();

System.out.println("casperjs time:" + (end - start) / 1000);

}

示例脚本如下:

//test.js

var casper = require('casper').create({

verbose: false,

logLevel: 'debug',

waitTimeout: 10000,

pageSettings:{

loadImages: false, // The WebPage instance used by Casper will

loadPlugins: false // use these settings

}

});

phantom.outputEncoding = "gbk";//解决乱码问题

phantom.cookiesEnabled = true;

var url =casper.cli.get('url');

 

casper.start(url, function() {

this.scrollToBottom();

casper.GetDetailUrl(url);

});

 

casper.GetDetailUrl = function(detailUrl) {

  casper.thenOpen(detailUrl, function() {

   console.log(this.getCurrentUrl());

});

};

 

casper.then(function getPic() {

return this.echo(this.getHTML());

});

casper.run();

 

我们可以通过上述的方式来得到AJax加载后的源代码,然后通过流的方式取得页面的源码,不过这个需要我们掌握CasperJs脚本的编写规则。在性能方面也是秒级的。

5 HttpClient模拟请求

这种情况相对于前面所有的方法来说就比较复杂了,因为它需要我们对网页进行分析,由于不同的网站结构不一样,因此采用这种方式需要我们对网页请求进行分析。一般都需要借助一些专业的工具如httpwatch等。

比如我们要提取价格,我们需要找到价格对应的请求链接,然后再去请求数据,这种情况在提取多个属性信息的时候也是不方便的,因为涉及到多次请求,而且一般不具有通用性。好处是httpclient抓取性能较高,抓取效率是毫秒级的。

总结

从简单的测试结果来看,我认为HtmlUnitSelenium WebDriverPhantomJSDriver都是不错的选择,模拟浏览器简单易用且都能满足我们目前的需求。

以上是我这几天的调查结果,有很多的不足之处,对于本人粗陋的总结,对于后期的工作就当是抛砖引玉吧。


© 著作权归作者所有

_liucui_
粉丝 16
博文 134
码字总数 53455
作品 0
秦皇岛
私信 提问
爬取动态网页之python+selenium+webdriver

静态页面的爬取相对来说比较容易,通过请求获取到静态页面资源进行解析就可以拿到我们想要的,但很多网站通常会用到Ajax和动态HTML技术,因而只是使用基于静态页面爬取的方法是行不通的。 对...

激情的狼王
2018/10/26
0
0
python+selenium+PhantomJS抓取动态内容

本人使用的是python3.6.1+selenium3.4.3+PhantomJS2.1.1来做一个小爬虫,爬取网页:http://t.10jqka.com.cn/guba/1...中动态加载的内容( ) 静态网页会爬取,不知道哪位大神可以帮忙写下这个...

LeoGQ
2017/07/03
103
0
scrapy爬取淘宝商品页的问题

之前用scrapy官方的模板稍加该变就可以成功的爬取一些网页,博客什么的,用sel.XPath()爬取指定问题也可以成功. 但是在爬取淘宝商品页的内容时出现了问题。一开始以为是Xpath 出错 但是退出的...

果子面包
2015/12/08
1K
1
用Node.js爬取动态网页,这可能是最简洁的方式

现在网页大多是动态网页,如果只是单纯地通过爬取网页HTML文件,根本爬取不到需要后续加载的商品价格或图片等重要信息,更别谈那些丧心病狂的登录限制,对于小爬虫来说,去分析那些复杂的脚本...

Nothlu
06/15
0
0
动态网页内容如何爬取

动态网页内容一般如何爬取?我需要爬的网页中的内容需要登录才会显示,而且都是由javascript生成的。有开源项目吗?或者实现的思路。之前了解到的爬虫都是用来爬静态页面。

taohe
2014/06/15
1K
5

没有更多内容

加载失败,请刷新页面

加载更多

CentOS 7系统增加swap

转载请注明文章出处:CentOS 7系统增加swap swap是位于磁盘上的特殊文件(或分区),属于“虚拟内存”的一部分。通俗点就是内存的备胎,内存充足的情况下,基本上没swap什么事(和设置有关)...

tlanyan
23分钟前
2
0
基于Prometheus和Grafana的监控平台 - 环境搭建

相关概念 微服务中的监控分根据作用领域分为三大类,Logging,Tracing,Metrics。 Logging - 用于记录离散的事件。例如,应用程序的调试信息或错误信息。它是我们诊断问题的依据。比如我们说...

JAVA日知录
今天
5
0
PHP运行时全局构造体

struct _php_core_globals { zend_bool magic_quotes_gpc; // 是否对输入的GET/POST/Cookie数据使用自动字符串转义。 zend_bool magic_quotes_runtime; //是否对运行时从外部资源产生的数据使...

冻结not
今天
4
0
webpack插件html-webpack-plugin

本文转载于:专业的前端网站→webpack插件html-webpack-plugin 1、插件安装 npm install html-webpack-plugin --save-dev 2、插件使用 webpack.config.js配置文件为: var htmlWebpackPlugin=...

前端老手
今天
6
0
数据挖掘

zhengchen1996
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部