我正在使用node.js编写应用程序,该应用程序向github发送请求并获取github项目问题的html页面。当我发送第40页的更多请求时,我得到429响应请求。我怎样才能克服github的这个RATE限制?
function requestPage(pageNo){
var changedUrl = url+"?page="+pageNo+"&q=is%3Aissue+is%3Aopen"; //URL for requesting all the pages individually
request(changedUrl, function(error, response, html){ //requesting thee web page
if(error){
return error;
}
else{
var $ = cheerio.load(html);
if(pageNo == 40){
console.log(response.statusCode);
fs.writeFile("page.html", html ,'utf8',function(err){
if(err) {
return console.log(err);
}
console.log("The file was saved!");
});
}
//functions
}
});
}
for (var i = 1; i <= noOfPages; i++) {
requestPage(i);
}
&#13;
答案 0 :(得分:1)
首先,请注意您最好使用github API而不是请求HTML页面。它应该使您的工作更轻松,因为您将直接以JSON格式获取您感兴趣的数据,而无需解析HTML。 问题API端点记录在案here。
您还应该检查github是否允许您抓取他们的页面,并确保您的服务器不会因您的请求而超载。
但是,如果你想继续你正在做的事情,你可以这样安排你的代码:
处理率限制
在request
函数内部回调中,你应该添加一个条件来检查来自github的响应:
request(changedUrl, function(error, response, html){
if(error){
return error;
}
else{
if (response.headers.status === '429 Too Many Requests') {
setTimeout(function() {requestPage(pageNo)}, 54000000}) // retry in some delay (find out the appropriate timeout value)
}
else {
... //continue the processing
表现良好
您的代码中所需的其他更改可能会避免您受到速率限制。它也应该节省你的CPU和github服务器。
这很糟糕:
for (var i = 1; i <= noOfPages; i++) {
requestPage(i);
}
原因:您正在准同时向github发送noOfPages
个请求。
如何修复:使用递归函数而不是for
循环,并在调用之间设置延迟。
固定代码:
function requestPage(pageNo){
var changedUrl = url+"?page="+pageNo+"&q=is%3Aissue+is%3Aopen"; //URL for requesting all the pages individually
request(changedUrl, function(error, response, html){ //requesting thee web page
if(error){
return error;
}
else{
if (response.headers.status === '429 Too Many Requests') {
// retry to request the same page after some delay
setTimeout(function() {requestPage(pageNo)}, 54000000})
}
else {
var $ = cheerio.load(html);
if(pageNo == 40){
console.log(response.statusCode);
fs.writeFile("page.html", html ,'utf8',function(err){
if(err) {
return console.log(err);
}
console.log("The file was saved!");
});
if (i < noOfPages) {
// request next page after a small delay
setTimeout(function() {requestPage(pageNo+1)}, 15000})
}
}
}
});
}
// request the first page immediately
requestPage(1);
我接下来要清理硬编码的if(pageNo == 40){
,它可能应该是if(pageNo == noOfPages){
,并且可以使用以下if子句进行排列。
答案 1 :(得分:0)
在带有babel的ES7中,一次只有一页:
import req from 'request-promise';
async function getPages(urls) {
for (let url of urls) {
let html = await req(url);
console.log(html);
}