ajax動態網頁爬取總結

這幾天對JS動態網頁的爬取作了一下研究,主要涉及到的對象有HtmlUnitHttpUnitSelenium WebDriverCasperJsHttpClient模擬等操做。咱們能夠經過對天貓商品的促銷價爬取來對他們進行下對比。html

測試網頁以下:前端

http://detail.tmall.com/item.htm?spm=0.0.0.0.HkxFxe&id=520129049356java

促銷價在天貓的網站上是動態生成的,在源碼中是看不到的。 web

1 HtmlUnitajax

HtmlUnit是一款開源的Java 頁面分析工具,讀取頁面後,能夠有效的使用HtmlUnit分析頁面上的內容。項目能夠模擬瀏覽器運行,被譽爲java瀏覽器的開源實現。它對於動態生成的數據提供了支持,使咱們可以獲得ajax執行後的源代碼。並且它操做簡單隻需將相關的jar包引入即可使用。瀏覽器

測試代碼:cookie

public class HtmlUnitTest {網絡

String url = "http://detail.tmall.com/item.htm?spm=0.0.0.0.HkxFxe&id=520129049356";app

static WebClient webClient;函數

 

@BeforeClass

public static void init() {

// 指定瀏覽器,並指定瀏覽器模擬的版本;

webClient = new WebClient(BrowserVersion.CHROME);

// webclient參數載體

WebClientOptions clientOptions = webClient.getOptions();

ProxyConfig proxyConfig = new ProxyConfig();

proxyConfig.setProxyHost("proxy.asiainfo.com");

proxyConfig.setProxyPort(8080);

// 設置webClient的相關參數

clientOptions.setJavaScriptEnabled(true);

clientOptions.setCssEnabled(false);

clientOptions.setTimeout(10000);

clientOptions.setThrowExceptionOnScriptError(false);

clientOptions.setProxyConfig(proxyConfig);

webClient.setAjaxController(new NicelyResynchronizingAjaxController());

}

 

@Test

public void test() {

long start = System.currentTimeMillis();

// 模擬瀏覽器打開一個目標網址

HtmlPage rootPage;

try {

rootPage = webClient.getPage(url);

     HtmlElement htmlElement = rootPage.getBody();

     String xmlContent = htmlElement.asXml();

long end = System.currentTimeMillis();

System.out.println("time:" + (end - start));

System.out.println(xmlContent);

// 測試js生成的部分是否加載成功

Document doc = Jsoup.parse(xmlContent);

Elements select = doc.select("#J_PromoPrice .tm-price");

if (select != null && select.size() > 0) {

String text = select.get(0).text();

System.out.println(text);

}

catch (FailingHttpStatusCodeException e) {

e.printStackTrace();

catch (MalformedURLException e) {

e.printStackTrace();

catch (IOException e) {

e.printStackTrace();

}

}

}

執行結果:

經過代碼及測試咱們會發現,它簡單易用,可是在抓取時間上耗時仍是不少的。

2 HttpUnit

上面談到HtmlUnit咱們還要提一下這個HttpUnit,名字類似、功能類似,若是不注意每每會混淆。網上搜索HttpUnit的官方文檔,你會發現它的版本已經有好幾年沒有更新了,並且對ajax動態數據的解析不支持,沒法解決咱們現有的問題,放棄。

3 Selenium WebDriver

如今的網絡訪問不了官方網站,只能從其餘地方收集一些資料,它包含了多種Driver,以下圖所示:

1HtmlUnitDriver

從這些子類中咱們能夠看出Selenium包含了HtmlUnitDriver,經過查看源碼以及使用發現它實際上就是調用的HtmlUnit的部分方法,不過與HtmlUnit不一樣的是它並無提供Ajax支持,所以對於天貓這類的網頁它是解析不了促銷價格的。

2)各類瀏覽器Driver

咱們在使用時,不一樣的瀏覽器須要配置不一樣的參數來指定瀏覽器的安裝路徑。每次初始化操做都會打開一個瀏覽器。下面讓咱們以火狐瀏覽器爲例:

測試代碼:

public class SelenimuWebDriverTest {

WebDriver webDriver;

String url = "http://detail.tmall.com/item.htm?spm=0.0.0.0.HkxFxe&id=520129049356";

 

@Before

public void setUp() {

DesiredCapabilities capability = DesiredCapabilities.firefox();

capability.setCapability("firefox_binary""E:\\Program Files\\Mozilla Firefox\\firefox.exe");

webDriver = new FirefoxDriver(capability);// 初始化一個火狐瀏覽器

webDriver.manage().window().maximize(); // 最大化瀏覽器

}

 

@Test

public void test1() throws Exception {

long start = System.currentTimeMillis();

webDriver.get(url);

String pageSource = webDriver.getPageSource();

long end = System.currentTimeMillis();

System.out.println("time:" + (end - start));

Document doc = Jsoup.parse(pageSource);

Elements select = doc.select("#J_PromoPrice .tm-price");

if (select != null && select.size() > 0) {

String result = select.get(0).text();

System.out.println(result);

else {

System.out.println("no result");

}

webDriver.close();

}

}

執行結果:

 

從網頁的抓取時間上來講,它的效率仍是能夠的,初始化瀏覽器的過程咱們須要注意防止瀏覽器打開過多,以避免耗時且耗資源。而且這個在使用的時候有時候打開瀏覽器的時候會提示導入嚮導,這種還須要調整瀏覽器的配置參數。

3PhantomJSDriver

PhantomJSDriver的使用很是簡單、接近真實瀏覽器且不須要打開瀏覽器,所以,直接建立一個PhantomJSDriver對象就能夠用了。前提是須要安裝phantomjs而且配置好環境變量,不過這一步是很是簡單的。

測試代碼:

@Before

public void setUp() {

webDriver = new PhantomJSDriver();

}

//其餘同上

結果:

這個用起來仍是很方便的,不知道是不是網絡的緣由,測試過程當中抓取時間的變化在2s-7s範圍波動,從抓取來看時間也不是最慢的,簡單易用。

4 CasperJs

因爲最早研究的是這個東西,在此仍是要先簡單說一下吧。

CasperJS[1] 是一個開源的導航腳本處理和測試工具,基於PhantomJS(前端自動化測試工具)編寫。CasperJS簡化了完整的導航場景的過程定義,提供了用於完成常見任務的實用的高級函數、方法和語法。它的寫法與JSJquery的方法相似,咱們能夠在他的腳本中使用js或者Jquery的函數。

因爲官方文檔寫的不是很詳細,所以對於初學者來講也是有必定難度的。且它的抓取效率也是秒級的。因爲它不是Java編寫的,所以咱們須要經過相關的方法來調用腳本。它是基於PhantomJS的,所以咱們也須要安裝PhantomJS,配置相關的環境變量。

官方地址http://docs.casperjs.org/en/latest/installation.html

調用CasperJs的腳本,來獲得頁面源代碼,示例代碼以下:

public static void useSperjs() {

String url = "http://detail.tmall.com/item.htm?spm=a220m.1000858.1000725.1.MbFIev&id=45844061725&skuId=93180315832&areaId=110000&cat_id=52810004&rn=21d1496d974e4f9984611fad013f1696&user_id=728628560&is_b=1";

long start = System.currentTimeMillis();

try {

Process exec = Runtime.getRuntime().exec("casperjs D:/jade/casperjs/jadeFile/test.js --url=" + url);

InputStream in = exec.getInputStream();

InputStreamReader isr = new InputStreamReader(in"gbk");

BufferedReader br = new BufferedReader(isr);

String line = null;

StringBuilder sb = new StringBuilder();

while ((line = br.readLine()) != null) {

sb.append(line + "\n\r");

}

System.out.println(sb.toString());

catch (IOException e) {

e.printStackTrace();

}

long end = System.currentTimeMillis();

System.out.println("casperjs time:" + (end - start) / 1000);

}

示例腳本以下:

//test.js

var casper = require('casper').create({

verbose: false,

logLevel: 'debug',

waitTimeout: 10000,

pageSettings:{

loadImages: false, // The WebPage instance used by Casper will

loadPlugins: false // use these settings

}

});

phantom.outputEncoding = "gbk";//解決亂碼問題

phantom.cookiesEnabled = true;

var url =casper.cli.get('url');

 

casper.start(url, function() {

this.scrollToBottom();

casper.GetDetailUrl(url);

});

 

casper.GetDetailUrl = function(detailUrl) {

  casper.thenOpen(detailUrl, function() {

   console.log(this.getCurrentUrl());

});

};

 

casper.then(function getPic() {

return this.echo(this.getHTML());

});

casper.run();

 

咱們能夠經過上述的方式來獲得AJax加載後的源代碼,而後經過流的方式取得頁面的源碼,不過這個須要咱們掌握CasperJs腳本的編寫規則。在性能方面也是秒級的。

5 HttpClient模擬請求

這種狀況相對於前面全部的方法來講就比較複雜了,由於它須要咱們對網頁進行分析,因爲不一樣的網站結構不同,所以採用這種方式須要咱們對網頁請求進行分析。通常都須要藉助一些專業的工具如httpwatch等。

好比咱們要提取價格,咱們須要找到價格對應的請求連接,而後再去請求數據,這種狀況在提取多個屬性信息的時候也是不方便的,由於涉及到屢次請求,並且通常不具備通用性。好處是httpclient抓取性能較高,抓取效率是毫秒級的。

總結

從簡單的測試結果來看,我認爲HtmlUnitSelenium WebDriverPhantomJSDriver都是不錯的選擇,模擬瀏覽器簡單易用且都能知足咱們目前的需求。

以上是我這幾天的調查結果,有不少的不足之處,對於本人粗陋的總結,對於後期的工做就當是拋磚引玉吧。

相關文章
相關標籤/搜索