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

我试图用骑士login到一个网站,find一组链接,打开每一个,刮一些数据,并返回它。

这是我到目前为止…

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); }) }) 

编辑 – 现在我可以使用上面的代码得到结果,但它们都是相同的结果,使用链中的最后一个链接。 我想现在发生的是每个循环在前一个URL完成之前打开每个URL,所以只返回最后打开的链接的结果。 我怎样才能确保这些承诺顺序执行同步?

我使用了对这个问题的答案中列出的workOneByOne函数来顺序创build和解决承诺。 不知道这是否是最好的方法,但它的工作原理。

 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 )); }) }) 

login后可以考虑这个

 var links = ["http://link1.com","http://link2.com"]; scrapeData = []; var it = 0; doit(); function doit(){ var Horseman = require("node-horseman"); horseman .userAgent('Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0') .open(links[it]) .waitForSelector('#details > fieldset > table') .html('body') .then(function(html){ var $ = cheerio.load(html); 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() }; scrapeData.push(data); it = it + 1; if(it < links.length){ doit(); } return horseman.close(); });