使用node.js的github速率限制

时间:2015-09-20 11:03:32

标签: node.js github

我正在使用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;
&#13;
&#13;

2 个答案:

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