【问题标题】:rate limit of github using node.jsgithub使用node.js的速率限制
【发布时间】:2015-12-17 04:09:09
【问题描述】:

我正在使用 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);
}

【问题讨论】:

  • 当您的请求收到429 响应时,您可以使用setTimeout 和/或队列仅在等待延迟过去后触发您的下一个请求...返回请求标头X-RateLimit-Remaining by github应该会让你知道你需要等待多长时间。
  • 我是新手,你能告诉我如何检查“X-RateLimit-Remaining”作为回应
  • 当然可以,但您应该先分享您的代码:如何连接到 github 的 API?
  • @SunilKumar 请edit您的问题包括相关的代码。评论不适合它。
  • 另外,请使用谷歌。很快搜索“github api limits”给了我这篇文章:developer.github.com/v3/rate_limit

标签: node.js github


【解决方案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子句来安排。

【讨论】:

  • 感谢您的回答。除了递归还有其他方法吗?因为如果页面更多,则需要更多时间
  • 为了加快速度,您可以使用队列系统,并引入一些并行性。 Caolan 的async 模块将为您提供帮助。但首先,真正开始使用 API。
  • 如何从 node.js 对 github 进行身份验证
【解决方案2】:

在带有 babel 的 ES7 中,一次只有一页:

import req from 'request-promise';

async function getPages(urls) {
  for (let url of urls) {
    let html = await req(url);
    console.log(html);   
 }

【讨论】:

    猜你喜欢
    • 2018-06-10
    • 2021-05-15
    • 2018-09-23
    • 1970-01-01
    • 2015-11-17
    • 1970-01-01
    • 2019-04-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多