Selenium/HtmlUnit設定代理獲取JS生成的網頁

Gin.p發表於2017-04-02

通常我們使用Java提供的HttpURLConnection或者Apache的HttpClient獲取的網頁原始碼都是直觀可見的,其程式碼的內容和通過瀏覽器右鍵網頁->點選檢視網頁原始碼的內容一致。

但是現在越來越多的網站使用Js來動態生成內容來提高相應速度,而HttpClient只是返回後端相應的response的請求主體,並沒有返回瀏覽器生成的網頁,所以對於Js生成的內容HttpClient是獲取不了的。

對於獲取Js生成的網頁,我們主要通過模擬瀏覽器的執行,渲染response的請求主體最終得到對應的內容,得到的內容和通過瀏覽器右鍵網頁->點選檢查/檢視元素的內容一致。

我們這裡講的模擬方法大概有兩種:

  • 一種是使用Selenium
  • 一種是使用HtmlUnit

抓取目標

我們這次的目標是獲取bilibili動態生成的動畫列表,左上是抓取的目標列表,左下是瀏覽器渲染的html內容,右面是伺服器返回的response的正文。通過對比,我們可以看出目標列表是Js生成。
bilibili

使用Selenium獲取頁面

Selenium是一個用於Web應用自動化測試的工具,更多的介紹就谷歌。這裡我們主要用作模擬頁面的執行並將結果返回,對於網頁截圖的功能也是可行的。

Selenium支援模擬很多瀏覽器,但是我們這裡只模擬PhantomJS,因為PhantomJS 是一個指令碼化的無介面 WebKit,以 JavaScript 為指令碼語言實現各項功能。由於是無介面的,所以速度效能方面會較好。

1.下載
使用PhantomJS需要到官網下載最新的客戶端,這裡使用phantomjs-2.1.1-windows.zip

2.maven依賴引入:

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>2.53.0</version>
</dependency>
<dependency>
    <groupId>com.codeborne</groupId>
    <artifactId>phantomjsdriver</artifactId>
    <version>1.2.1</version>
    <exclusions>
        <exclusion>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-remote-driver</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
        </exclusion>
    </exclusions>
</dependency>

3.示例程式碼

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.phantomjs.PhantomJSDriver;
import org.openqa.selenium.phantomjs.PhantomJSDriverService;
import org.openqa.selenium.remote.DesiredCapabilities;

import java.util.ArrayList;

/**
 * @author GinPonson
 */
public class TestSelenium {

    static final String HOST = "127.0.0.1";
    static final String PORT = "80";
    static final String USER = "gin";
    static final String PWD = "12345";

    public static void main(String[] args){
        System.setProperty("phantomjs.binary.path", "D:\\phantomjs-2.1.1-windows\\bin\\phantomjs.exe");
        DesiredCapabilities capabilities = DesiredCapabilities.phantomjs();

        //設定代理或者其他引數
        ArrayList<String> cliArgsCap = new ArrayList<>();
        //cliArgsCap.add("--proxy=http://"+HOST+":"+PORT);
        //cliArgsCap.add("--proxy-auth=" + USER + ":" + PWD);
        //cliArgsCap.add("--proxy-type=http");
        capabilities.setCapability(PhantomJSDriverService.PHANTOMJS_CLI_ARGS, cliArgsCap);
        //capabilities.setCapability("phantomjs.page.settings.userAgent", "");

        WebDriver driver = new PhantomJSDriver(capabilities);
        driver.get("http://www.bilibili.com/video/bangumi-two-1.html");
        System.out.println(driver.getPageSource());
        driver.quit();
    }
}

4.其他功能

  • 設定引數或者代理:去掉上面的註釋,就可以使用自己的代理了。
  • 操作頁面,返回操作後頁面內容:不多說了,這裡介紹一下可以做。
  • 頁面截圖:返回瀏覽器的全屏截圖。

使用HtmlUnit獲取頁面

HtmlUnit功能上算是是Selenium的一個子集,Selenium有對應的HtmlUnit實現。HtmlUnit是用Java寫的無介面的瀏覽器,正因為其沒有介面,因此執行的速度還是可以的。

1.maven依賴引入

<dependency>
    <groupId>net.sourceforge.htmlunit</groupId>
    <artifactId>htmlunit</artifactId>
    <version>2.25</version>
</dependency>

2.Java程式碼

/**
 * @author GinPonson
 */
public class TestHtmlUnit {
    static final String HOST = "127.0.0.1";
    static final String PORT = "80";
    static final String USER = "gin";
    static final String PWD = "12345";

    public static void main(String[] args) throws Exception{
        WebClient webClient = new WebClient();
        //設定代理
        //ProxyConfig proxyConfig = webClient.getOptions().getProxyConfig();
        //proxyConfig.setProxyHost(HOST);
        //proxyConfig.setProxyPort(Integer.valueOf(PORT));
        //DefaultCredentialsProvider credentialsProvider = (DefaultCredentialsProvider) webClient.getCredentialsProvider();
        //credentialsProvider.addCredentials(USER, PWD);

        //設定引數
        //webClient.getOptions().setCssEnabled(false);
        //webClient.getOptions().setJavaScriptEnabled(false);
        webClient.getOptions().setThrowExceptionOnScriptError(false);
        HtmlPage page = webClient.getPage("http://www.bilibili.com/video/bangumi-two-1.html");

        System.out.println(page.asXml());
        webClient.close();
    }
}

3.其他功能

  • 設定引數或者代理:去掉上面的註釋,就可以使用自己的代理了。
  • 操作頁面,返回操作後頁面內容:不多說了,這裡介紹一下可以做。
  • 解析頁面

總結

PhantomJS和HtmlUnit模擬瀏覽器頁面的生成功能都不錯,PhantomJS作為一個無介面的WebKit,渲染頁面的功能非常完善,而且帶有瀏覽器截圖功能,能模擬登入操作。HtmlUnit使用Rhino引擎來解析Js,有時候解析速度非常慢,就像上面的例子,費了很長時間,但是HtmlUnit可以獲取頁面,解析元素一套做完(當然解析元素還是使用Jsoup好),是不錯的工具。
HtmlUnit遇到錯誤後,前後處理相差7分鐘,可能是我不會用QAQ
截圖
歡迎補充:)

相關文章