Java selenuim用执行js模拟鼠标滚动的方式完成页面滚动的异步加载及Java接收浏览器js的返回值

news/2024/7/19 14:33:34 标签: Java, selenuim, 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。


http://www.niftyadmin.cn/n/1786765.html

相关文章

SpringCloud 使用feign报错

在学习廖师兄的spring cloud视频过程中&#xff0c;feign依赖加入后项目启动报错&#xff0c;升级版本后解决。 springboot版本为 2.0.0.M3 springcloud版本为&#xff1a; Finchley.M2 视频中使用的依赖为&#xff1a; <dependency><groupId>org.springframe…

解决虚拟机Centos7 报错 curl#56 - Recv failure: Connection reset by peer yum无法更新下载

win10上安装的centos7虚拟机 在虚拟机yum安装及yum update命令中 都报错 无法连接&#xff0c;尝试其他镜像等。 网上几篇文章都是复制的一样的关centos防火墙的两个命令 systemctl disable firewalld systemctl stop firewalld 关闭后依然打不开 尝试把win10的网络防火墙关…

Mysql 事务的隔离级别 一看就懂

事务 简单来说&#xff0c;事务就是要保证一组数据库操作&#xff0c;要么全部成功&#xff0c;要么全部失败。 在MySQL中&#xff0c;事务支持是在引擎层实现的。而MySQL原生的MyISAM引擎就不支持事务&#xff0c;这也是MyISAM被InnoDB取代的重要原因之一。 一、隔离性与隔离…

Java 面试题全记录 多处搜集 灵魂拷问 持续更新

大佬总结的面试题纲&#xff1a; https://github.com/farmerjohngit/myblog/issues/21 Hashmap 源码级掌握&#xff0c;扩容&#xff0c;红黑树&#xff0c;最小树化容量&#xff0c;hash 冲突解决&#xff0c;有些面试官会提出发自灵魂的审问&#xff0c;比如为什么是红黑树…

Java 忽略HtmlUnit执行过程中日志打印的javascript报错信息 Error during JavaScript execution

进行各种各样的网页爬虫过程中&#xff0c;有些网页直接httpclient拿过来就能用&#xff0c;但是有些网站是需要等待js加载样式或者某些值的&#xff0c;使用httpclient没办法设置js等待时间&#xff0c;然后再抓取值。 htmlunit可以完美解决这个问题。但是在使用htmlunit访问…

ES 创建索引时使用Dynamic Mapping动态映射 对字符串字段生成keyword字段

1.ES5.0及以后的版本取消了string类型&#xff0c;将原先的string类型拆分为text和keyword两种类型。它们的区别在于text会对字段进行分词处理而keyword则不会。这就是造成部分字段还会自动生成一个与之对应的“.keyword”字段的原因。 Text vs. keyword Text&#xff1a;会分…

解决ES搜索过程中使用高亮插件导致结果不完整的问题

对一个内容长度比较长的字段进行搜索并使用高亮显示插件时&#xff0c;通过获得结果中的高亮字段获取的内容只有一部分&#xff0c;而非全部内容 当需要获取全部内容时&#xff0c;只需要设置 number_of_fragments 为0 即可返回完整内容 HighlightBuilder highlightBuilder …

Java 判断一个字符串是不是由数字组成

可以使用 org.apache.commons.lang3.StringUtils的isNumeric()方法 其实就是对每一位分别调用Character的isDigit()方法 public static boolean isNumeric(CharSequence cs) {if (isEmpty(cs)) {return false;} else {int sz cs.length();for(int i 0; i < sz; i) {if …