使用请求和 cheerio 模块延迟请求
delaying requests using request and cheerio modules
这是我用来抓取网页的代码(我使用的是请求和 cheerio 模块:
for (let j = 1; j < nbRequest; j++)
{
const currentPromise = new Promise((resolve, reject) => {
request(
`https://www.url${j}`,
(error, response, body) => {
if (error || !response) {
console.log("Error: " + error);
}
console.log("Status code: " + response.statusCode + ", Connected to the page");
var $ = cheerio.load(body);
let output = {
ranks: [],
names: [],
numbers: [],
};
$('td.rangCell').each(function( index ) {
if ($(this).text().trim() != "Rang")
{
output.ranks.push($(this).text().trim().slice(0, -1));
nbRanks = nb_ranks+1;
}
});
$('td.nameCell:has(label)').each(function( index ) {
output.names.push($(this).find('label.nameValue > a').text().trim());
});
$('td.numberCell').each(function( index ) {
if ($(this).text().trim() != "Nombre")
{
output.numbers.push($(this).text().trim());
}
});
console.log("HERE 1");
return resolve(output);
}
);
});
promises.push(currentPromise);
}
之后,我使用节点模块解析结果并将其保存在 csv 文件中。
在这一点上,我已经能够抓取大约 100 个页面,但是当涉及到更大的数字(1000+)时,我收到了 500 个响应,这意味着我认为我被踢了。
所以我认为最好的解决方案是延迟请求,但我没有找到解决方案。
你们知道代码会是什么样子吗?
您要找的是 "Control Flow",您可以使用 async.queue 来实现。
如果将每个请求都添加到队列中,您可以通过工作人员数量来控制并行请求的数量。并且你可以在请求回调的最后部分添加setTimeouts来实现请求的延迟。
此外,我建议使用 "crawler" 包(而不是自己构建),例如npm-crawler 因为他们内置了速率限制,并且已经处理了您接下来可能会遇到的其他事情 :) 例如用户代理池
更新:
const async = require("async");
const delayTime = 1500; //wait 1,5 seconds after every new request
getRequestPromise(csvLine){
return new Promise( make you request here );
}
const asyncQueue = async.queue(function(task, callback) {
getRequestPromise(task).then(_ => {
setTimeout(() => {
callback(null);
}, delayTime);
});
}, 1); //1 one request at a time
for(csv){ //pseudo
asyncQueue.push(csv[i], () => {});
}
asyncQueue.drain = () => {
console.log("finished.");
};
这是我用来抓取网页的代码(我使用的是请求和 cheerio 模块:
for (let j = 1; j < nbRequest; j++)
{
const currentPromise = new Promise((resolve, reject) => {
request(
`https://www.url${j}`,
(error, response, body) => {
if (error || !response) {
console.log("Error: " + error);
}
console.log("Status code: " + response.statusCode + ", Connected to the page");
var $ = cheerio.load(body);
let output = {
ranks: [],
names: [],
numbers: [],
};
$('td.rangCell').each(function( index ) {
if ($(this).text().trim() != "Rang")
{
output.ranks.push($(this).text().trim().slice(0, -1));
nbRanks = nb_ranks+1;
}
});
$('td.nameCell:has(label)').each(function( index ) {
output.names.push($(this).find('label.nameValue > a').text().trim());
});
$('td.numberCell').each(function( index ) {
if ($(this).text().trim() != "Nombre")
{
output.numbers.push($(this).text().trim());
}
});
console.log("HERE 1");
return resolve(output);
}
);
});
promises.push(currentPromise);
}
之后,我使用节点模块解析结果并将其保存在 csv 文件中。 在这一点上,我已经能够抓取大约 100 个页面,但是当涉及到更大的数字(1000+)时,我收到了 500 个响应,这意味着我认为我被踢了。 所以我认为最好的解决方案是延迟请求,但我没有找到解决方案。 你们知道代码会是什么样子吗?
您要找的是 "Control Flow",您可以使用 async.queue 来实现。
如果将每个请求都添加到队列中,您可以通过工作人员数量来控制并行请求的数量。并且你可以在请求回调的最后部分添加setTimeouts来实现请求的延迟。
此外,我建议使用 "crawler" 包(而不是自己构建),例如npm-crawler 因为他们内置了速率限制,并且已经处理了您接下来可能会遇到的其他事情 :) 例如用户代理池
更新:
const async = require("async");
const delayTime = 1500; //wait 1,5 seconds after every new request
getRequestPromise(csvLine){
return new Promise( make you request here );
}
const asyncQueue = async.queue(function(task, callback) {
getRequestPromise(task).then(_ => {
setTimeout(() => {
callback(null);
}, delayTime);
});
}, 1); //1 one request at a time
for(csv){ //pseudo
asyncQueue.push(csv[i], () => {});
}
asyncQueue.drain = () => {
console.log("finished.");
};