更新,这就尴尬了,这篇文章博客阅读文章最多,但是被踩得也最多。
爬取思路:
所谓动态,就是通过请求后台,可以动态的改变相应的html页面,页面并不是一开始就全部展现出来的。
大部分操作都是通过请求完成的,一次请求,一次返回。而在大多数网页中请求往往都被开发者隐藏在了js代码中。
所以爬取动态网页的思路就转化为找出相应的js代码,并且执行相应的js代码,从而能够通过java代码动态的改变页面。
而当页面能够正确显示出来,我们也就可以类似于爬取静态网页般去爬取数据啦!
首先,可以利用htmlunit来模拟鼠标点击事件,这个容易实现:
/**
* 通过htmlunit来获得一些搜狗的网址。
* 通过模拟鼠标点击事件来实现
* @param key
* @return
* @throws Exception
*/
public String getNextUrl(String key){
String page = new String();
try {
WebClient webClient = new WebClient();
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(false);
//去拿网页
HtmlPage htmlPage = webClient.getPage("http://pic.sogou.com/");
//得到表单
HtmlForm form = htmlPage.getFormByName("searchForm");
//得到提交按钮
HtmlSubmitInput button = form.getInputByValue("搜狗搜索");
//得到输入框
HtmlTextInput textField = form.getInputByName("query");
//输入内容
textField.setValueAttribute(key);
//点一下按钮
HtmlPage nextPage = button.click();
String str = nextPage.toString();
page = cutString(str);
webClient.close();
} catch (Exception e) {
e.printStackTrace();
}
return page;
}
如上图所示,我就是通过java代码,向搜索矿中填入关键字,然后在通过getInputByValue方法获得button控件,最后直接button.click(),
即可以模拟点击,并且把点击后的返回的http请求解析到htmlpage中。
接下来就是利用强大的htmlunit来执行js代码的过程了。
首先写一个简单的jsp页面:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
Insert title here
由上可知,jsp页面很简单,就一个函数change,用于给htmlUnit调用。
再下来就是一个使用htmlunit的类。该类通过支持JavaScript解释器,
然后在页面中嵌入自己写的JavaScript代码从而执行,并且获得执行后的返回结果以及返回页面。
package com.blog.anla;
import com.gargoylesoftware.htmlunit.ScriptResult;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
public class TestMyOwnPage {
private void action() {
WebClient webClient = new WebClient();
try {
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(true); // 设置支持JavaScript。
// 去拿网页
HtmlPage htmlPage = webClient
.getPage("http://localhost:8989/testHtmlScrop/index.jsp");
String s = "更改后的数字";
ScriptResult t = htmlPage.executeJavaScript("change(\"" + s
+ "\");", "injected script", 500);
// 这里是在500行插入这一小行JavaScript代码段,因为如果在默认的1行,那不会有结果
// 因为js是顺序执行的,当你执行第一行js代码时,可能还没有渲染body里面的标签。
HtmlPage myPage = (HtmlPage) t.getNewPage();
String nextPage = myPage.asXml().toString();
String nextPage2 = myPage.asText().toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
webClient.close();
}
}
public static void main(String[] args) {
TestMyOwnPage tmop = new TestMyOwnPage();
tmop.action();
}
}
newPage_:执行该段代码后返回的整个页面。
结果如图:
最终这段代码执行的结果如下:
asXml():将整个页面的html代码返回给我们:
而asText()则仅仅返回页面上能显示的值,即head和label标签:
这样的执行思路也就能够去动态的执行相应的js代码,从而爬取到需要的数据了。
----------------------------------------------------------------------------------------2017年7月更新--------------------------------------------------------------------------------------------------------
这两天在做一个有关于网络爬虫的系统
但是呢,一开始爬的时候就发现问题,js的动态页面的爬不下来
网上找了好多方法,google也问了,主要还是提到htmlunit,以下是核心代码,
使用htmlunit主要就是为了模拟浏览器操作,因为有些链接点击无法直接通过src来获得url,而通常使用JavaScript
进行简单拼接后的网址,所以这样一来,使用htmlunit直接来模拟浏览器点击,相比来说就更加的简单了。
WebClient webClient = new WebClient();
webClient.getOptions().setJavaScriptEnabled(true); //启用JS解释器,默认为true
webClient.getOptions().setCssEnabled(false); //禁用css支持
webClient.getOptions().setThrowExceptionOnScriptError(false); //js运行错误时,是否抛出异常
webClient.getOptions().setTimeout(20000);
HtmlPage page = wc.getPage("http://www.hao123.com");
//我认为这个最重要
String pageXml = page.asXml(); //以xml的形式获取响应文本
/**jsoup解析文档*/
Document doc = Jsoup.parse(pageXml, "http://cq.qq.com");
这个时候,就可以得到jsoup中的document对象了,接下来就好写了,就像爬普通静态网页一样了。
不过,webclient解析是还是会出现一些问题,js的问题,
主要是由于目标url的js写的有些问题,但在实际的浏览器中却会忽略,eclipse中会报异常。
今天一看,好多人踩啊哈,可能当时并没有认真的写博客吧,如果大家想找一个java爬虫的项目,可以去我的专栏
图片搜索 包括使用jsoup来爬图,以及lire来建立索引以及搜索图片。
赠人玫瑰手留余香,有问题的大家可以多多讨论呀!