无法并行运行Selenium PhantomJS实例

时间:2015-07-16 14:05:13

标签: javascript node.js selenium selenium-webdriver phantomjs

我使用Selenium的node.js API针对一系列网页运行PhantomJS实例。我用来在页面上执行操作的代码运行正常,但似乎只有一个Selenium / PhantomJS实例可以一次运行。这个函数在同一个模块中被多次调用,并逐步遍历网上商店中的页面,在这里,客户端处理分页(这就是为什么我需要Selenium / PhantomJS环境 - 从每个页面中提取数据)。

再一次,代码本身工作正常,但它无法并行执行。可能导致这种情况的原因是什么?

module.exports = function (crawler, page, parsePage, done) {
    "use strict";

    var _ = require("lodash"),
        format = require("util").format,
        path = require("path"),
        webdriver = require("selenium-webdriver"),
        By = webdriver.By,
        until = webdriver.until;

    var phantomPath = path.resolve(__dirname, "../node_modules/.bin/phantomjs"),
        isWin = process.platform === "win32";

    var driver = new webdriver.Builder()
        .withCapabilities({
            "phantomjs.binary.path": isWin ? phantomPath + ".cmd" : phantomPath
        })
        .forBrowser("phantomjs")
        .build();

    var windowHandle = new webdriver.WebDriver.Window(driver);
    windowHandle.setSize(1100, 1000);

    var getAllPagesContent = function (driver) {
        var pagesContent = [],
            pageNo = 1;

        var getNextPage = function () {
            var nextPageLink;

            return driver.findElements(By.css(".pagination li")).then(function (elements) {
                return elements[elements.length - 1];
            }).then(function (element) {
                nextPageLink = element;
                return element.getAttribute("class");
            }).then(function (className) {
                return _.includes(className, "active");
            }).then(function (isLastPage) {
                return (!isLastPage) ? driver.getPageSource() : false;
            }).then(function (content) {
                if (content)
                    pagesContent.push(content);

                content && console.log("Got page %d", pageNo++);

                return nextPageLink.findElement(By.css("a")).then(function (element) {
                    return element.click();
                }).then(function () {
                    return driver.wait(until.stalenessOf(nextPageLink), 10 * 1000);
                }).then(function () {
                    return content ? getNextPage() : pagesContent;
                });
            });
        };

        return getNextPage();
    };


    var processTimeout = setTimeout(function () {
        console.log("PhantomJS for page %s took too long to execute", page.url);
        driver.quit().then(done);
    }, 60 * 1000);

    driver.get(page.url).then(function () {
        var pageOverlay = driver.findElement(By.css("#overlay-the-new"));

        return pageOverlay.isDisplayed().then(function (visible) {
            if (visible) {
                pageOverlay.click();
                return driver.wait(until.elementIsNotVisible(pageOverlay), 10000);
            }
        }).then(function () {
            return getAllPagesContent(driver);
        });
    }).then(function (contents) {
        clearTimeout(processTimeout);
        console.log("Got %d pages for %s", contents.length, page.url);

        _.forEach(contents, function (pageContent) {
            parsePage(page.url, pageContent);
        });

        return driver.quit();
    }).then(function () {
        done();
    });
}

4 个答案:

答案 0 :(得分:1)

虽然现在不推荐使用PhantomJS,但您仍然可以使用Docker在并行隔离的Selenoid容器中运行它。这里有一个可以使用的最新版本的图像:https://hub.docker.com/r/selenoid/phantomjs/tags/

答案 1 :(得分:0)

使用Remote WebDrivers和Selenium Grid2 Framework进行与Selenium的并行执行。

这个教程WeDoQA似乎是你想要的东西。简单地说,它将每个测试放在一个单独的类中,而中央测试基类指向Grid2的中心,然后(在教程中)使用Firefox驱动程序并行执行测试。您可以轻松地重新调整此项以使用phantomjs,但您可能需要重新设计测试结构。

答案 2 :(得分:0)

看起来你只使用一个驱动程序。我初始化第二个驱动程序,然后使用线程并行运行。我认为这可以完成工作。

答案 3 :(得分:-1)

使用Thread并行运行,或者您可以使用任何可以并行运行测试的测试框架。