最近需要解析javascript动态生成的内容,Jsoup不能够完成这个功能,就使用HtmlUnit,可以说到目前为止HtmlUnit很好的完成了任务。
但是有时候会出现莫名其妙的问题,现在将处理js请求内容中遇到的问题和解决方法列举如下。等手头这个项目做完了会把htmlunit的使用系统的做出总结。
第一类,通过源码就能够看到js请求,并且模拟请求获取内容
比如这个网站:http://fashion.qq.com/a/20140403/011113.htm ; //吴莫愁
要获取所有图片,必须依次单击下一页,通过源码看不到内容,但是通过审查元素可以发现其下一页的内容是通过这几行代码获得:
于是在代码里可以这样写:
rootPage.executeJavaScript("myGallery.changeImage("+ i +")") ;
rootPage.executeJavaScript("javascript:void(0)") ;
rootPage对象是htmlunit的webclient.getPage(url)返回的对象
再下一步通过:
rootPage.asXml() ;
就可以看到结果,这时候rootPage对象的内容已经发生了改变。
第二类,没有onclick方法 比如这个网页:
http://fashion.qq.com/a/20140402/005443.htm //平胸美女
通过审查元素查看:
通过模拟this.blur() 和 javascript:void(0) 都不能获取下一页的内容。
要么就一步一步查看他的js调用,通过查看js源码。要么就是观察其浏览器地址改变。通过观察可以发现每一次请求下一页他的浏览器地址就改变:
http://fashion.qq.com/a/20140402/005443.htm#p=1
http://fashion.qq.com/a/20140402/005443.htm#p=2
http://fashion.qq.com/a/20140402/005443.htm#p=3 ...
所以可以通过手动拼凑他的URL地址的方法来获取下一页的内容。
这个方法不是正统的解决方法,但是目前可以解决问题。回头会继续研究。
第三种,就是有onclick方法,但是href方法不能使用,并且浏览器地址跳转也无规律。
比如这个: http://korea.yule.sohu.com/s2009/koreanews/index.shtml //韩娱新闻
要想请求他的下一页内容,通过审查元素查看:
他的href属性指向的地址始终是第一页,所以如果再调用
rootPage.executeJavaScript("javascript:go(2)") ;
rootPage.executeJavaScript("#") ;
始终会返回第一页,实际上我试了很多方法,都解决不了。
后来发现htmlUnit有一个page对象,而page对象可以返回其url,这样的话就可以得到他的请求后的新的url。然后再重新请求url就可以得到下一页内容。
代码如下:
ScriptResult sr = rootPage.executeJavaScript("javascript:go(x)") ;
Page page2 = sr.getNewPage() ;
System.out.println(page2.getUrl().toString());
x变量表示第几页
还有一种方法,因为每次executeJavaScript方法执行后都建立了一次请求了,所以如果只拿到url再次进行请求比较浪费资源,可以使用这种办法:
ScriptResult sr = rootPage.executeJavaScript("javascript:go("+ i +")") ;
Page page2 = sr.getNewPage() ;
WebResponse wr = page2.getWebResponse() ;
String content = wr.getContentAsString() ;
这个时候content对象里面是页面经过执行js之后的完全代码,只要把这些内容放进html的txt文件里就可以使用了。
下一步可以使用jsouop的parse方法,以content为参数,获取jsoup的document对象,就更容易操作了。
如果只想要看到执行js之后生成的代码,比如这个网站:
http://beauty.rayli.com.cn/makeup/master/index.shtml
他的下一页的内容整个标签和内容都是由js生成的。如图
这个时候没有onclick方法来获取下一页内容,就只能模拟js代码获取他生成的下一页的地址。所以使用这几行代码生成:
ScriptResult sr = rootPage.executeJavaScript("pagelist["+i+"]") ;
Object o = sr.getJavaScriptResult() ; //执行过后的结果
System.out.println(o.toString());
输出结果为:makeup/master/list_1.shtml
makeup/master/list_2.shtml
makeup/master/list_3.shtml
注意这里的结果是相对地址,不是绝对地址。要获的绝对地址也可以,通过java的URL对象。代码如下:
URL u = new URL(url) ;
String baseURL = "http://" + u.getHost() ;
String absURL = baseURL + o.toString() ;
这里的absURL就是绝对地址,放进浏览器里可以直接获取下一页的内容。
再遇到更复杂的情况再做说明
OVER