javascript - 如何使用 horseman 和 nodejs 打开一个 URL 数组?

标签 javascript node.js web-scraping phantomjs

我正在尝试使用 horseman登录网站,找到一组链接,打开每个链接,抓取一些数据并将其返回。

这是我目前所拥有的......

function getLinks() {
    return horseman.evaluate(function () {
        var links = [];
        $('#cards > tbody > tr:not(:first-child) a').each(function (i, el) {
            links.push($(el).attr('href'));
        });
        return links;
    });
}

function scrapeDataFromLink(link) {
    return horseman
        .open(link)
        .waitForSelector('#details > fieldset > table')
        .evaluate(function () {
            var data = {
                name: $('#name > td:nth-child(2)').html().trim(),
                type: $('#type > td:nth-child(2)').html().trim(),
                expiry: $('#expiry > td:nth-child(2)').html().trim()
            };
            return data;
        }
    )
}


horseman
    .userAgent('Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0')
    .open(LOGIN_URL)
    .type('input[id=username]', username)
    .type('input[id=password]', password)
    .click('[id="login"]')
    .waitForSelector('table[id=cards]')
    .then(getLinks)
    .then(function(links){
        var promises = [];

        links.forEach(function(link){
            promises.push(scrapeDataFromLink(link));

        });
        Promise.all(promises).then((result) => {
            console.log(result);
        })
    })

编辑 - 我现在可以使用上面的代码取回结果,但它们都是相同的结果,使用链中的最后一个链接。我认为正在发生的事情是 for each 循环在前一个 URL 完成之前打开每个 URL,因此只返回最后打开的链接的结果。我如何确保这些 promise 按顺序同步执行?

最佳答案

我使用了此 question 的答案中概述的 workOneByOne 函数依次创建和解决 promise 。不确定这是否是最佳方式,但它确实有效。

var scrapedData = []

function getLinks() {
    return horseman.evaluate(function () {
        var links = [];
        $('#cards > tbody > tr:not(:first-child) a').each(function (i, el) {
            links.push($(el).attr('href'));
        });
        return links;
     });
}

function scrapeDataFromLink(link) {
    return horseman
    .open(link)
    .waitForSelector('#details > fieldset > table')
    .evaluate(function () {
        var data = {
            name: $('#name > td:nth-child(2)').html().trim(),
            type: $('#type > td:nth-child(2)').html().trim(),
            expiry: $('#expiry > td:nth-child(2)').html().trim()
        };
        return data;
        }
    )
}


function workOneByOne(items, someAsyncFuntionReturningPromise) {
    var lastResultPromise = items
        .map(function(item) {
            return function(previousResult) {
                if (previousResult) {
                    console.log(previousResult);
                    scrapedData.push(previousResult);
                }

                return someAsyncFuntionReturningPromise(item);
            }})
        .reduce(Q.when, Q());

    return lastResultPromise;
}


horseman
.userAgent('Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0')
.open(LOGIN_URL)
.type('input[id=username]', username)
.type('input[id=password]', password)
.click('[id="login"]')
.waitForSelector('table[id=cards]')
.then(getLinks)
.then(function(links){
    workOneByOne(links, scrapeDataFromLink).then(function(result) {
            scrapedData .push(result);
            res.setHeader('Content-Type', 'application/json');
            res.send(JSON.stringify(scrapedData ));
        })
})

关于javascript - 如何使用 horseman 和 nodejs 打开一个 URL 数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37764609/

相关文章:

Python网页抓取无法找到网页中的所有标签

javascript - 将表单提交到弹出窗口?

javascript - 如何使用javascript查找并替换字符串中的2个整数

javascript - 如何将javascript数组发送到php?

javascript - 如何发送时区以及日期时间格式?

python - 值错误: could not convert string to float: 'False' in python

javascript - 隐藏动态创建的单选按钮组件

node.js - 如何在surge.sh上部署Express应用程序

javascript - 无法使用 mysql 和 Node js 返回选择查询值

python - 尝试抓取网页时出现 SSL 错误