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