网页爬虫抓取js动态渲染数据

时间:2021-11-07 08:26:37

先从一堆故事背景讲起吧——

在非计算机专业的世界里,如果一个人是学计算机相关专业的,那么这个人肯定会修电脑,会做外挂,会盗号……

因为我是学计算机,有一天,表哥找了我,说请人做的一个用excel处理网站动态数据的程序不会跑了,然后他第一感觉就是找我(囧囧囧)。好吧,亲戚一场,就look一下。

第一次,我知道excel有个web查询,居然可以查询网站的动态数据。好吧,是我奥特了。摆弄了好一会,才知道操作方式。的确,查询无数据。

怎么说毕业后也搞了一年多的web开发。于是,我打开了chrome浏览器的调试功能~~

经过排查,我终于知道了原因,原因是网站优化了代码,以前是将查询结果生成静态页面。现在改成使用ajax动态获取数据然后再使用javascript进行网页渲染。于是,excel这头蠢驴拿到的是查询前的空数据、、、

说到这里,可能有些人马上就会想到,看下浏览器调试器的network视图,然后也发同样的http请求不就好了。

遗憾的是,这个网站也不是省油的灯。它在服务端作了安全限制,只有网页自己发出的请求才能通过安全验证。

这下,心好累,一点思路都没有。

突然,我想到一个傻b的思路,直接等浏览器渲染后页面后,来个另存为,显然也能工作。

但程序员天生是很懒的,我可不允许做这种事。

凭着第七感,我知道需要能够模拟浏览器自己执行脚本发请求再渲染。问了一下有爬虫工作经验的大学同学。同学说,要分析请求的参数和cookie等等,还说每一个网页都要单独处理。这明显不科学啊。还说如果要通用的话,可以用phantomJS、或者Selenium之类的东西。原谅我听都没听过。

最后,我决定用java的方法。说实在的,java的世界真的很强大,只要你想得到,肯定有大牛已经帮你实现了。

于是,我发现了一个神器——htmlunit

说白了,这个框架就是一个没有界面的浏览器。可以模拟浏览器的各种行为,拿到页面元素,模拟点击事件等等。

种种牛逼功能还得自己慢慢发掘,其官网地址为(htmlunit官网

推荐使用maven下载相关依赖,否则要手工下载一堆jar包。maven这东西,用过的人都说它好。哈哈~~

代码比较简单,直接看就可以了,需要注意的是,由于浏览器查询需要时间,在查询的过程中,应该让主线程休眠一段时间,才能保证htmlunit浏览器已经查询完毕。

import java.util.concurrent.TimeUnit;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlTable;
import com.gargoylesoftware.htmlunit.html.HtmlTableBody;

public class Entrance {

public static void main (String[] args ) throws Exception
{
String webUrl = "http://www.xy2046.com/xypk10.aspx?T=234&day=2016-05-29";
HtmlPage page = getHtmlPage(webUrl);
final HtmlTable div = (HtmlTable) page.getElementById("mytable");
HtmlTableBody tbody = (HtmlTableBody) div.getBodies().get(0);
printTable(tbody);
System.err.println("查询数据成功");
}

private static HtmlPage getHtmlPage(String url) throws Exception{
final WebClient webClient=new WebClient(BrowserVersion.CHROME);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setMaxInMemory(500);
final HtmlPage page = webClient.getPage(url);
System.err.println("查询中,请稍候");
TimeUnit.SECONDS.sleep(5); //web请求数据需要时间,必须让主线程休眠片刻
webClient.close();

return page;
}

private static void printTable(HtmlTableBody tbody) throws Exception{
DomNodeList<HtmlElement> trs = tbody.getElementsByTagName("tr");
for(int i=0;i<trs.size();i++){
HtmlElement node = trs.get(i);
DomNodeList<HtmlElement> tds = node.getElementsByTagName("td");
for(int j=0;j<tds.size();j++){
HtmlElement td = tds.get(j);
System.err.print(td.asText()+"\t");
}
System.err.println();
}
}
}
代码运行结果如下:

网页爬虫抓取js动态渲染数据