在使用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。