Java selenuim用執行js模擬鼠標滾動的方式完成頁面滾動的異步加載及Java接收瀏覽器js的返回值

    在使用selenuim webdriver爬取網頁時,經常會有很多網頁並不是訪問鏈接就會加載全部內容的,而是需要鼠標向下滾動,動態的加載內容,比如知乎首頁。這樣在爬取的過程中並不能直接抓數據,需要先模擬鼠標滾動,讓頁面先加載出來纔行。


    我使用的方法是利用如下js代碼來完成頁面的滾動,每次滾動多少可以根據不同情況自行調整。

scroll(0,document.body.scrollHeight)

    在瀏覽器控制檯輸入js代碼即可看到效果,和程序中使用起來是一樣的。可以先在真實場景調試好每次要滾動多少會觸發加載,然後再寫進代碼中使用。同理想要橫向滑動的話,就改變第一個參數,第二個參數置爲0。

    對於部分網頁來說,是不會允許無限制的加載新數據的,換句話說就是滾動加載出的數據是有一定限制的。那麼如何使頁面滾動到恰好加載到沒新數據可加載 就是一個新問題了。想到加載過程中 document.body.scrollHeight 這個值是會根據每次新加載數據動態變化的,那麼也就是說 當執行一次js代碼後,這個值沒有發生改變,就代表本次沒有加載新的數據了。

    接下來的問題就是如何使Java代碼能夠接收到瀏覽器執行的js代碼返回值的問題了。很簡單,在js代碼上加上return  即可。注意有一個空格。

import org.apache.commons.io.FileUtils;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

import java.io.File;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

/**
 * 描述 :谷歌瀏覽器驅動工具類
 * 作者 :WYH
 * 時間 :2019/8/29 13:57
 **/
public class ChromeDriverUtil {

    private static WebDriver driver;

    private final static int DEFAULT_TIMEOUT = 30;

    static {
        System.setProperty("java.awt.headless", "true");
        String driverPath = "D:/chromedriver.exe";//驅動需下載到指定目錄
        ChromeOptions option = new ChromeOptions();
        option.addArguments("disable-infobars");
        option.addArguments("start-maximized");
        //option.addArguments("headless");
        System.setProperty("webdriver.chrome.driver", driverPath);
        driver = new ChromeDriver(option);
        driver.manage().timeouts().pageLoadTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        driver.manage().timeouts().setScriptTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);

    }

    public static void setTimeOut(int second) {
        driver.manage().timeouts().pageLoadTimeout(second, TimeUnit.SECONDS);
        driver.manage().timeouts().setScriptTimeout(second, TimeUnit.SECONDS);
    }

    public static WebDriver getDriver() {
        return driver;
    }

    public static void quit() {
        if (driver != null) {
            driver.quit();
        }
    }

    /**
     * 滑動頁面到最底部 返回true代表加載了新的 false代表已經沒有再加載的了
     */
    private static boolean scrollDown() {
        boolean flag = false;
        if (driver != null) {
            try {
                Long before = (Long) ((JavascriptExecutor) driver).executeScript("return document.body.scrollHeight");
                ((JavascriptExecutor) driver).executeScript("scroll(0,document.body.scrollHeight)");
                //給頁面預留加載時間
                Thread.sleep(2000);
                Long after = (Long) ((JavascriptExecutor) driver).executeScript("return document.body.scrollHeight");
                if (!(before.equals(after))) flag = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return flag;
    }

    public static void loadAll() {
        while (scrollDown());
    }
}

只要是true,就繼續執行scrollDown函數,直到它返回false。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章