【问题标题】:how to access pages with querystring using request and node.js如何使用 request 和 node.js 访问带有查询字符串的页面
【发布时间】:2017-05-15 06:53:59
【问题描述】:

我使用 Node.js 编写了一个简单的网络抓取工具的代码,并编写了一个在线教程来收集 BuzzFeed 测验的信息。它适用于主页(https://www.buzzfeed.com/quizzes)但当我尝试在任何其他页面(即https://www.buzzfeed.com/quizzes?page=4)上使用它时,我没有得到任何结果。我不确定有什么问题?这是我的代码:

var request = require('request');
var cheerio = require('cheerio');
var fs = require('fs');
var options = {
    method: 'GET',
    uri: 'https://www.buzzfeed.com/quizzes',
    qs: {
      page: 4
    }
}

request(options, function(error, response, html) {
    if(!error && response.statusCode == 200) {
      var $ = cheerio.load(html);

      $('div.card.js-feed-item').each(function( index ) { 
        var title = $(this).find('h2').text().trim();
        var link = $(this).find('a.link-gray').attr('href');
        var image = $(this).find('a.link-gray > div.js-progressive-image').attr('data-background-src');
        fs.appendFileSync('buzzfeed.txt', title + '\n' + link + '\n' + image + '\n\n');
      });
}});

基本上,如果我注释掉这个:

qs: {
    page: 4
}

它工作正常。我是不是用错了qs?

【问题讨论】:

    标签: javascript jquery node.js web-scraping httprequest


    【解决方案1】:

    看起来 BuzzFeed 服务器想要发回压缩响应。如果您查看documentation for the request module,您可以找到这个选项:

    gzip - 如果是true,添加Accept-Encoding 标头以从服务器请求压缩的内容编码(如果不存在)并在响应中解码支持的内容编码。

    因此,在您的情况下,只需将 gzip: true 添加到您的 options 对象即可。但请注意,根据页面依赖 JS 显示其内容的程度,HTML 可能不是您所期望的。


    我是如何解决这个问题的?基本上,如果您检查返回的 response 对象(在 if 语句之外),您可以获得一些非常有用的信息。

    例如,我们可以通过使用 response.request.url(或 response.request.href)检查请求 url 并查看(通过 console.log 或调试器)是否正确地形成了查询字符串( ?page=4),所以这不是问题。

    进一步挖掘我们可以看到response.statusCode500response.body(或html 参数)是{"message": "INTERNAL_ERROR"}。这似乎表明“服务器错误”,但是我们可以在浏览器中正常访问该页面,因此实际上服务器似乎不喜欢我们出于某种原因形成请求的方式。

    在这种情况下,值得一试response.headers,我们可以在其中看到例如content-typeapplication/json (这显然不是你想要的)。但更有趣的是,有一个vary 标头,其中一个值为Accept-Encoding - 这基本上是在说“如果您使用不同的Accept-Encoding 标头再次发出此请求,您将得到不同的响应”。 Accept-Encoding 几乎总是用于指定您可以处理的压缩类型,其中 gzip 是服务器最常支持的,因此 Node 请求模块提供了 gzip 选项。如果您打开浏览器 devtools 的网络选项卡并浏览到 URL,您可以看到正在设置相同的标头(在 Chrome 中,通过“Doc”过滤请求以更容易地找到它)。

    编辑:您的原始代码现在似乎对我有用,所以也许这毕竟是服务器问题。

    【讨论】:

      【解决方案2】:

      查看页面完成的请求,实际上你可以废弃这个 URL:“https://www.buzzfeed.com/quizzes?render_template=0”,它会为你提供一个包含 2 个字段的 json:cards(信息数组)和 nextPage(类似于 /quizzes?render_template= 0&page=2) ,你可以使用我认为相同的数据。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-21
        • 1970-01-01
        • 1970-01-01
        • 2011-05-03
        • 1970-01-01
        • 2014-07-15
        • 2017-03-04
        相关资源
        最近更新 更多