1

我正在尝试访问在 Github 上拥有超过 5000 颗星的所有存储库。我编写了这个爬虫来使用 Node.js(它在 Cloud9 环境中运行):

var request = require('request');
var fs = require('fs');

var options = {

    url: 'https://api.github.com/repositories',
    headers: {
    'User-Agent': 'myusernamehere'
    },
    qs: {
    stargazers: 5000
    }

};

function callback(error, response, body) {
  if (!error && response.statusCode == 200) {
    console.log(response.headers);

    fs.writeFile('output_teste.json', body, function (err) {
      if (err) throw err;
      console.log('It\'s saved!');
      console.log(response.statusCode);
    });

  } else {
    console.log(response.statusCode);
  }
}

request(options, callback);

但结果并不是所有的存储库,只是所有存储库的第一页。如何在请求模块中使用分页?我试图在文档中找到示例,但它们并不那么清楚。还是我需要用另一个库或另一种语言来做这个?

谢谢!

4

2 回答 2

1

您应该修改您的查询字符串以包含“since”的值。您可以在 github 文档上阅读更多内容。 https://developer.github.com/v3/repos/#list-all-public-repositories

查询字符串为 since 的示例 URL

https://api.github.com/repositories?since=364

于 2018-03-21T15:42:26.490 回答
0

您可以使用调用 GitHub API 时收到的分页数据response.headers.link来确定是否还有更多页面可供调用。

一种方法是遍历页面,直到没有更多新页面,此时您可以写入文件并从函数返回。

在每个循环中,您可以通过使用concat(我假设响应主体作为数组传递)添加到已有的数据中,然后将数据传递给下一个函数调用。

我重写了您的代码以包含这种技术的基本实现:

var request = require('request');
var fs = require('fs');

var requestOptions = function(page) {
  var url = 'https://api.github.com/repositories?page=' + page;

  return {
    url: url,
    headers: {
      'User-Agent': 'myusernamehere'
    },
    qs: {
      stargazers: 5000
    }
  };
};

function doRequest(page, incomingRepos) {
  request(requestOptions(page), function(error, response, body) {
    if (!error && response.statusCode == 200) {
      console.log(response.headers);

      var currentPageRepos = JSON.parse(body);
      var joinedRepos = incomingRepos.concat(currentPageRepos);

      var linkData = response.headers.link;

      // if response does not include reference to next page
      // then we have reached the last page and can save content and return
      if (!(linkData.includes('rel="next"'))) {
        fs.writeFile('output_teste.json', JSON.stringify(joinedRepos), function(err) {
          if (err) throw err;
          console.log('It\'s saved!');
        });
        return;
      }

      page++;
      doRequest(page, joinedRepos);
    } else {
      console.log(response.statusCode);
    }
  });
}
doRequest(1, []);
于 2018-11-06T16:38:03.680 回答