最近在用Jsoup抓取某网站数据,可有些页面是ajax请求动态生成的,去群里问了一下,大神说模拟ajax请求即可。去网上搜索了一下,发现了这篇文章,拿过来先用着试试。

   转帖如下:

网上关于网络爬虫实现方式有很多种,但是很多都不支持Ajax,李兄说:模拟才是王道。确实,如果能够模拟一个没有界面的浏览器,还有什么不能做到的呢? 关于解析Ajax网站的框架也有不少,我选择了HtmlUnit,官方网站:http://htmlunit.sourceforge.net /,htmlunit可以说是一个Java版本的无界面浏览器,几乎无所不能,而且很多东西都封装得特别完美。这是这几天来积累下来的心血,记录一下。


package com.lanyotech.www.wordbank;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.util.List;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.ScriptResult;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlOption;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlSelect; public class WorldBankCrawl { private static String TARGET_URL = "http://databank.worldbank.org/ddp/home.do"; public static void main(String[] args) throws FailingHttpStatusCodeException, MalformedURLException, IOException {
//模拟一个浏览器
WebClient webClient = new WebClient();
//设置webClient的相关参数
webClient.setJavaScriptEnabled(true);
webClient.setCssEnabled(false);
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
webClient.setTimeout(35000);
webClient.setThrowExceptionOnScriptError(false);
//模拟浏览器打开一个目标网址
HtmlPage rootPage= webClient.getPage(TARGET_URL);
//获取第一个数据库
HtmlSelect hs = (HtmlSelect) rootPage.getElementById("lstCubes");
//按要求选择第一个数据库
hs.getOption(0).setSelected(true);
//模拟点击Next按钮,跳转到第二个页面
System.out.println("正在跳转…");
//执行按钮出发的js事件
ScriptResult sr = rootPage.executeJavaScript("javascript:setCubeData(2,-1,4,'/ddp');"); //跳转到第二个页面,选择国家
HtmlPage countrySelect = (HtmlPage) sr.getNewPage();
//获得包含全部国家信息的选择框页面
HtmlPage framePage=(HtmlPage)countrySelect.getFrameByName("frmTree1″).getEnclosedPage();
//获得selectAll按钮,触发js事件
framePage.executeJavaScript("javascript:TransferListAll(‘countrylst','countrylstselected','no');SetSelectedCount(‘countrylstselected','tdcount');");
//获取Next按钮,触发js事件
ScriptResult electricityScriptResult = framePage.executeJavaScript("javascript:wrapperSetCube('/ddp')"); System.out.println("正在跳转…");
//跳转到下一个页面electricitySelect
HtmlPage electricitySelect = (HtmlPage) electricityScriptResult.getNewPage();
//获得electricity选择的iframe
HtmlPage electricityFrame = (HtmlPage) electricitySelect.getFrameByName("frmTree1″).getEnclosedPage();
//获得选择框
HtmlSelect seriesSelect = (HtmlSelect) electricityFrame.getElementById("countrylst");
//获得所有的选择框内容
List optionList = seriesSelect.getOptions();
//将指定的选项选中
optionList.get(1).setSelected(true);
//模拟点击select按钮 electricityFrame.executeJavaScript("javascript:TransferList('countrylst','countrylstselected','no');SetSelectedCount('countrylstselected','tdcount');");
//获取选中后,下面的选择框
HtmlSelect electricitySelected = (HtmlSelect) electricityFrame.getElementById("countrylstselected");
List list = electricitySelected.getOptions();
//模拟点击Next按钮,跳转到选择时间的页面
ScriptResult timeScriptResult = electricityFrame.executeJavaScript("javascript:wrapperSetCube('/ddp')"); System.out.println("正在跳转…");
HtmlPage timeSelectPage = (HtmlPage) timeScriptResult.getNewPage();
//获取选中时间的选择框
timeSelectPage = (HtmlPage) timeSelectPage.getFrameByName("frmTree1″).getEnclosedPage();
//选中所有的时间 timeSelectPage.executeJavaScript("javascript:TransferListAll('countrylst','countrylstselected','no');SetSelectedCount('countrylstselected','tdcount');");
//点击Next按钮
ScriptResult exportResult = timeSelectPage.executeJavaScript("javascript:wrapperSetCube('/ddp')"); System.out.println("正在跳转…");
//转到export页面
HtmlPage exportPage = (HtmlPage) exportResult.getNewPage();
//点击页面上的Export按钮,进入下载页面
ScriptResult downResult = exportPage.executeJavaScript("javascript:exportData('/ddp' ,'EXT_BULK' ,'WDI_Time=51||WDI_Series=1||WDI_Ctry=244||' );"); System.out.println("正在跳转…");
HtmlPage downLoadPage = (HtmlPage) downResult.getNewPage();
//点击Excel图标,开始下载
ScriptResult downLoadResult = downLoadPage.executeJavaScript("javascript:exportData('/ddp','BULKEXCEL');");
//下载Excel文件
InputStream is = downLoadResult.getNewPage().getWebResponse().getContentAsStream(); OutputStream fos = new FileOutputStream("d://test.xls");
byte[] buffer=new byte[1024*30];
int len=-1;
while((len=is.read(buffer))>0){
fos.write(buffer, 0, len);
}
fos.close();
fos.close();
System.out.println("Success!");
}
}

 

注释:

  /**HtmlUnit请求web页面*/
WebClient wc = new WebClient();
wc.getOptions().setJavaScriptEnabled(true); //启用JS解释器,默认为true
wc.getOptions().setCssEnabled(false); //禁用css支持
wc.getOptions().setThrowExceptionOnScriptError(false); //js运行错误时,是否抛出异常
wc.getOptions().setTimeout(10000); //设置连接超时时间 ,这里是10S。如果为0,则无限期等待
HtmlPage page = wc.getPage("http://cq.qq.com/baoliao/detail.htm?294064");
String pageXml = page.asXml(); //以xml的形式获取响应文本

模拟ajax实现网络爬虫——HtmlUnit的更多相关文章

  1. java假设模拟请求重新启动路由器(网络爬虫经常使用),还有java怎样下载图片

    我们假设在公司或家里使用网络爬虫去抓取自己索要的一些数据的时候,经常对方的站点有defence机制,会给你的http请求返回500错误,仅仅要是同样IP就请求不到数据,这时候我们仅仅能去重新启动路由器 ...

  2. HtmlUnit 开发网络爬虫

    网络爬虫第一个要面临的问题,就是如何抓取网页,抓取其实很容易,没你想的那么复杂,一个开源HtmlUnit包,几行代码就OK啦! 通常在一个页面中会包含别的Url,在别的Url当中又会包含更多的Url. ...

  3. Java开发、网络爬虫、自然语言处理、数据挖掘简介

    一.java开发 (1) 应用开发,即Java SE开发,不属于java的优势所在,所以市场占有率很低,前途也不被看好. (2) web开发,即Java Web开发,主要是基于自有或第三方成熟框架的系 ...

  4. java之网络爬虫介绍

    文章大纲 一.网络爬虫基本介绍二.java常见爬虫框架介绍三.WebCollector实战四.项目源码下载五.参考文章   一.网络爬虫基本介绍 1. 什么是网络爬虫   网络爬虫(又被称为网页蜘蛛, ...

  5. 学 Java 网络爬虫,需要哪些基础知识?

    说起网络爬虫,大家想起的估计都是 Python ,诚然爬虫已经是 Python 的代名词之一,相比 Java 来说就要逊色不少.有不少人都不知道 Java 可以做网络爬虫,其实 Java 也能做网络爬 ...

  6. 开源的49款Java 网络爬虫软件

    参考地址 搜索引擎 Nutch Nutch 是一个开源Java 实现的搜索引擎.它提供了我们运行自己的搜索引擎所需的全部工具.包括全文搜索和Web爬虫. Nutch的创始人是Doug Cutting, ...

  7. 【转】44款Java 网络爬虫开源软件

    原帖地址 http://www.oschina.net/project/lang/19?tag=64&sort=time 极简网络爬虫组件 WebFetch WebFetch 是无依赖极简网页 ...

  8. 网络爬虫框架Scrapy简介

    作者: 黄进(QQ:7149101) 一. 网络爬虫 网络爬虫(又被称为网页蜘蛛,网络机器人),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本:它是一个自动提取网页的程序,它为搜索引擎从万维 ...

  9. Python网络爬虫精要

    目的 学习如何从互联网上获取数据.数据科学必须掌握的技能之一. 本文所用到的第三方库如下: requests, parsel, selenium requests负责向网页发送HTTP请求并得到响应, ...

随机推荐

  1. [nginx]location语法

    location语法 location语法格式 location [=|~|~*|^~] uri { .... } location [=|~|~*|^~] uri {....} 指令 匹配标识 匹配 ...

  2. 深入理解Linux内核-进程调度

    1.什么时候进行进程切换 调度策略目标:1.进程响应尽量快:2.后台作业吞吐量尽量高:3.尽可能避免进程饥饿:4.低优先级和高优先级进程需要尽量调和. 调度策略:决定什么时候选择什么进程运行的规则.基 ...

  3. Rocket MQ 源码解析

    http://rocketmq.apache.org/rocketmq/the-design-of-transactional-message/ http://www.iocoder.cn/Rocke ...

  4. Silverlight-MEF-DEMO

    “托管扩展性框架(Managed Extensibility Framework,简称MEF),是微软.NET框架下为提高应用和组件复用程度而推出的,用于使组件能够最大化的重用.使用MEF能够使静态编 ...

  5. 【Linux技术】linux库文件编写·入门

    一.为什么要使用库文件 我们在实际编程中肯定会遇到这种情况:有几个项目里有一些函数模块的功能相同,实现代码也相同,也是我们所说的重复代码.比如,很多项目里都有一个用户验证的功能. 代码段如下: //U ...

  6. 【驱动】linux设备驱动·字符设备驱动开发

    Preface 前面对linux设备驱动的相应知识点进行了总结,现在进入实践阶段! <linux设备驱动入门篇>:http://infohacker.blog.51cto.com/6751 ...

  7. Lintcode: Majority Number 解题报告

    Majority Number 原题链接:http://lintcode.com/en/problem/majority-number/# Given an array of integers, th ...

  8. zoj 3761(并查集+搜索)

    题意:在一个平面上,有若干个球,给出球的坐标,每次可以将一个球朝另一个球打过去(只有上下左右),碰到下一个球之后原先的球停下来,然后被撞的球朝这个方向移动,直到有一个球再也撞不到下一个球后,这个球飞出 ...

  9. 网络构建入门技术(2)——IP子网划分

    说明(2017-5-10 10:54:31): 1. 为什么要子网划分? 子网划分就是,网络位变长,主机位变短的过程.实际上就是将一个大网络,划分成多个小网络的过程. 目的就是为了解决IP地址不够用的 ...

  10. [转]Mustache 使用心得总结

    原文地址:https://blog.csdn.net/xuemoyao/article/details/17896203 前言: 之前的一个项目里面就有用到这个前台的渲染模版,当时挺忙的也没时间抽空总 ...