使用htmlunit抓取网页中ajax或者js动态生成的内容

Life is short , play more!
本文来自lihao's Blog,转载请注明。

为什么要抓取ajax的内容?

1)并不一定必须要进行ajax的内容, 首先要确认你抓取的数据页面webpage是否包含了ajax或者js动态数据。   如果有动态的,则必须使用支持js解析的html 框架(其实就是类似浏览器)进行。

2. 如果纯粹的html数据解析,则直接用http client即可。

首先先列出用于测试的html页面。

test1.html 测试页面。  js代码直接写dom。

<html>
<head><title>Test Page</title></head>
<body>

<script>
document.write("<div>content generated by javascript!</div>");
</script>

</body>


</html>

test2.html  异步请求数据

<html>
<head><title>Test Page</title></head>
<body>

<script>
function get()
{
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
     document.write(this.responseText);
    }
  };
  xhttp.open("GET", "testcontent", true);
  xhttp.send();
}

get();

</script>

</body>


</html>

 

异步请求数据,模拟异步请求有较长时间的延时。

<html>
<head><title>Test Page</title></head>
<body>

<script>
function get()
{
  var xhttp = new XMLHttpRequest();
  console.log("start xhr request");
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
     //document.write(this.responseText);
document.getElementById("demo").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "testcontent", true);
  xhttp.send();
}

setTimeout(function(){ get(); }, 4000);

console.log("set timed out !");

</script>

<div id="demo"></div>

</body>


</html>

 

使用httpclient 直接读取html

String url = "http://qa.heika.com/dashboard/test2.html";		
String returnJson = Request.Get(url).execute().returnContent().asString();
System.out.println(returnJson);

使用htmlunit 读取html(支持js解析)

		  final WebClient webClient = new WebClient();
	      final HtmlPage page = webClient.getPage("http://qa.heika.com/dashboard/test2.html");
	       // Assert.assertEquals("HtmlUnit - Welcome to HtmlUnit", page.getTitleText());
	      final String pageAsXml = page.asXml();
	      System.out.println(pageAsXml);

 

使用htmlunit读取html,(支持异步ajax执行)

		  final WebClient webClient = new WebClient();
		  
		  
		  //WebClient instance to re-synchronize asynchronous XHR.
		  webClient.setAjaxController(new NicelyResynchronizingAjaxController());
		  
		  //webClient.waitForBackgroundJavaScript(5000);
		  
	      final HtmlPage page = webClient.getPage("http://qa.heika.com/dashboard/test2.html");
	       // Assert.assertEquals("HtmlUnit - Welcome to HtmlUnit", page.getTitleText());
	      final String pageAsXml = page.asXml();
	      System.out.println(pageAsXml);

 

使用htmlunit读取html,设定page的等待时间,模拟ajax请求有较大的延时的情况(支持异步ajax执行)

		  final WebClient webClient = new WebClient(BrowserVersion.FIREFOX_38);
		  		  
		  //WebClient instance to re-synchronize asynchronous XHR.
		  //webClient.setAjaxController(new NicelyResynchronizingAjaxController());
		  		  
		  //webClient.waitForBackgroundJavaScript(5000);
		  //webClient.waitForBackgroundJavaScriptStartingBefore(10000);
	      HtmlPage page = webClient.getPage("http://qa.heika.com/dashboard/test3.html");
	      synchronized (page) {
	    	  	    	  
	    	  page.wait(5000);

          }
	      
	       // Assert.assertEquals("HtmlUnit - Welcome to HtmlUnit", page.getTitleText());
	      final String pageAsXml = page.asXml();
	      System.out.println(pageAsXml);

 

由上方的几个例子可以看出,htmlunit对ajax的支持是没有任何问题的,就如htmlunit官方所说的那样。

但是需要注意的是, ajax异步执行的内容如果包含document.write();  的内容不会被htmlunit抓取到的page更新。  如果使用如下方式 新变更dom,却没发现问题。 

document.getElementById("demo").innerHTML = this.responseText;

发表评论

电子邮件地址不会被公开。 必填项已用*标注