我尝试使用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);
})
})
编辑 - 我现在可以使用上面的代码获取结果,但它们都是相同的结果,使用链中的最后一个链接。我认为正在发生的是每个循环在前一个URL完成之前打开每个URL,因此只返回最后打开的链接的结果。如何确保这些承诺按顺序同步执行?
答案 0 :(得分:2)
我使用了对此question的回答中概述的 workOneByOne 功能来顺序创建和解决承诺。不确定这是否是最佳方式,但它确实有效。
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 ));
})
})
答案 1 :(得分:0)
您可以在登录后考虑这一点
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();
});