通过web驱动程序异步执行Javascript

Asynchronously execute Javascript through a web driver

本文关键字:执行 Javascript 异步 驱动程序 web 通过      更新时间:2023-09-26

我的目标是系统地收集网页上每个元素的相关信息。具体来说,我想对每个元素执行el.getBoundingClientRect()window.getComputedStyle(el)

我一直在使用SeleniumWebDriverforNodeJS来加载页面和管理浏览器交互。为了简化,我们只关注getComputedStyle:

    driver.findElements(By.xpath("//*"))
        .then(elements => {
            var elementsLeft = elements.length;
            console.log('Entering async map');
            async.map(elements, el => {
                driver.executeScript("return window.getComputedStyle(arguments[0]).cssText",el)
                    .then((styles: any) => {
                        //stuff would be done here with the styles
                        console.log(elements.indexOf(el));
                    });
            });
    });

这段代码将遍历所有元素并检索它们的样式,但速度非常慢。完成一页可能需要几分钟时间。我希望驱动程序异步执行脚本,但这似乎是不可能的,因为每个Selenium驱动程序都有一个"ControlFlow",确保驱动程序的每个命令只在最后一个命令完成后才启动。我需要找到一个解决方法,这样我就可以在页面上异步执行javascript(并加快数据收集速度)。

注意:我还尝试过Selenium的executeSyncScript,它只是executeScript的一个包装器,在完成之前仍然会阻塞。这是我使用executeSyncScript的代码,它的性能与前一个代码一样好:

    driver.findElements(By.xpath("//*"))
        .then(elements => {
            var elementsLeft = elements.length;
            async.map(elements, el => {
                driver.executeAsyncScript( 
                    function(el: any) {
                        var cb = arguments[arguments.length - 1];
                        cb(window.getComputedStyle(el).cssText);
                    }, el)
                    .then((styles: any) => {
                        //stuff would be done here with the styles
                        console.log(elements.indexOf(el));
                    });
            });
    });

我正在寻找一种绕过Selenium的ControlFlow的方法,以便异步执行我的javascript,找到一种提取对象而不受驱动程序绑定的方法,或者找到一种替代工具/解决方案来获取我需要的数据。

由于executeScript可以占用WebElement s,您看到在一个调用中完成所有工作是否比重复调用executeScript更快吗?

driver.findElements(By.xpath("//*"))
    .then(elements => {
        driver.executeScript("return arguments[0].map(function(el) {return [el, window.getComputedStyle(el).cssText];})", elements)
            .then((styles: any) => {
                //stuff would be done here with the styles
                console.log(styles);
            });
    });
});

如果速度太慢,您是否考虑过定位脚本中的所有元素,而不是将它们传入?

driver.findElements(By.xpath("//*"))
    .then(elements => {
        driver.executeScript("return Array.prototype.slice.call(document.getElementsByTagName('*'))" +
                ".map(function(el) {return [el, window.getComputedStyle(el).cssText];})", elements)
            .then((styles: any) => {
                //stuff would be done here with the styles
                console.log(styles);
            });
    });
});