【问题标题】:scraping a page that redirects抓取重定向的页面
【发布时间】:2018-02-28 02:37:34
【问题描述】:

我尝试抓取一个简单的页面(需要cheerio 和请求): https://www.ishares.com/uk/individual/en/products/251824/

代码失败。我相信这是因为,为了达到上述目的,用户会在上一页被提示输入“个人”或“机构”,因此被重定向。

我尝试了不同的 url 变体,但都失败了。

如何使用 node.js 获取原始 HTML?

代码如下:

var express = require('express');
var path = require('path');
var request = require('request');
var cheerio = require('cheerio');   // fast flexible implement of jQuery for server.
var fs = require('fs');

var app = express();
var port = 8000;
var timeLog = [];  // for dl to measure the time of events.

// var startTime = Date.now();


timeLog[0] = Date.now();
console.log('program initiated at time: '+new Date());


// example 1:  pull the webpage and print to console
var url ="https://www.ishares.com/uk/individual/en/products/251824/ishares-jp-morgan-emerging-markets-bond-ucits-etf";
url = "https://www.ishares.com/uk/individual/en/products/251824/";
url="https://www.ishares.com/uk/individual/en/products/251824/ishares-jp-morgan-emerging-markets-bond-ucits-etf?siteEntryPassthrough=true&locale=en_GB&userType=individual";


request(url,function functionName(err,resp,body) {
 var $ = cheerio.load(body);

 var distYield = $('.col-distYield');
 var distYieldText = distYield.text();
 console.log('we got to line 24');
 console.log(distYieldText);


 timeLog[2] = Date.now();
 console.log('data capture time: '+(timeLog[2] - timeLog[0])/1000+' seconds');

  if (err) {
    console.log(err);
  }else {
    //console.log(body);
    console.log('the body was written: success');
  }
});

// example 2:  download webpage and save file
var destination = fs.createWriteStream('./downloads/iSharesSEMB.html');
request(url)
  .pipe(destination);


// example 3:
var destination = fs.createWriteStream('./downloads/iSharesSEMB2.html');
request(url)
  .pipe(destination)
  .on("finish",function () {
    console.log('done');
  })
  .on('error',function (err) {
    console.log(err);
  });



timeLog[1] = Date.now();
console.log('program completed at time: '+new Date());
console.log('Asynchronous program run time: '+(timeLog[1] - timeLog[0])/1000+' seconds');

【问题讨论】:

  • 您是否遇到错误或只是未能抓取您想要的 HTML 部分?你到底想刮什么部位?
  • 没有收到错误。实际发生的是获取第一页的 HTML,而不是包含所需信息的重定向页面(在回答问题后)(例如在该页面上,分发收益)。可以在此处查看输出 HTML:var destination = fs.createWriteStream('./downloads/iSharesSEMB.html');

标签: node.js cheerio


【解决方案1】:

好的,我开始工作了。我为request 启用了cookie 支持,但随后进入了重定向循环。添加一个承诺就解决了。这里只是相关的 HTML 请求部分:

const request = require('request'),
    cheerio = require('cheerio');


const url = "https://www.ishares.com/uk/individual/en/products/251824/ishares-jp-morgan-emerging-markets-bond-ucits-etf?siteEntryPassthrough=true&locale=en_GB&userType=individual";

options = {
    jar: true
}

const getDistYield = url => {
    return new Promise((resolve, reject) => {
        request(url, options, function(err,resp,body) {
            if (err) reject(err);
            let $ = cheerio.load(body);
            resolve($('.col-distYield'));
        })
    })
}

getDistYield(url)
    .then((tag) => {
        console.log(tag.text())
    }).catch((e) => {
        console.error(e)
    })

输出:

分配收益
分配收益率代表过去 12 个月分配的收入与基金当前资产净值的比率。
截至 2018 年 2 月 20 日
4.82

另外,请注意我使用了您提供的最后一个 URL。

我希望这对你有用:)

【讨论】:

  • 谢谢。这行得通。我注意到您已在 request() 函数中添加为第二个参数.... 'options = { jar: true }' 这是启用 cookie 支持的方式吗?
  • @D.L 是正确的。您将在请求 npm 页面中找到所有可用选项的列表。 npmjs.com/package/request#requestoptions-callback
  • 如果用户只需要提取似乎是类中的类的值,他们将如何做到这一点?所以在这种情况下,只有 4.82(而不是文本的其余部分)。
【解决方案2】:

修改了解析部分,只获取嵌套类的值(而不是文本)。

resolve($('.col-distYield > span:nth-child(2)'));

【讨论】:

    猜你喜欢
    • 2018-11-19
    • 2011-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-18
    • 1970-01-01
    相关资源
    最近更新 更多