【问题标题】:How do I scrape a url from xml in Node.js?如何从 Node.js 中的 xml 中抓取 url?
【发布时间】:2017-08-10 05:53:25
【问题描述】:

我的最终目标是让我的应用显示来自给定用户的 500px.com 帐户(这是一个摄影网站)的 X 个最新图像的缩略图。据我所知,该网站没有 API,但它确实有一个供个人用户使用的 rss 提要,即https://500px.com/janedoe/rss,它会输出 xml。

使用 xml2js,我可以将 xml 解析为 js 对象并导航到包含我想要的 url 的 html 的“描述”容器,就像这样(这只是使用第一项的概念证明RSS提要):

var express = require('express');
var router = express.Router();
var request = require('request');
var parseString = require('xml2js').parseString;

var EventEmitter = require('events').EventEmitter;
var body = new EventEmitter();

/* GET home page. */
router.get('/', function(req, res, next) {


  request("https://500px.com/janedoe/rss", function(error, response, data) {
        body.data = data;
        body.emit('update');
    }); 

    body.on('update', function() {
        parseString(body.data, function (err, result) {
            var photoLink = result.rss.channel[0].item[0].description[0];
            res.render('index', { title: 'Express', photoName});
        });
    });



});

这会将“!CDATA”标签的整个 html 内容放入 photoLink 变量中。我想要做的是定位该 html 中 img src 中的内容,以便我可以将 url 作为要在页面上呈现的字符串传递。

我可以设想使用字符串方法来查找第一个“img src”标签,然后一直读到地址的末尾,但是有没有更优雅和简单的方法来做到这一点?

【问题讨论】:

  • 没什么大不了的,真的。使用 XML 解析器解析 RSS 并导航到有问题的元素以提取 HTML 文本。使用 HTML 解析器解析 HTML 并导航到相关元素以提取属性值。您绝对应该做的一件事是“使用字符串方法”。
  • 既然您已经完成了第 1 步(RSS 解析),剩下的就是第 2 步(HTML 解析)。看看cheerio(基本上是 jQuery for node)来帮助你。
  • 谢谢!使用cheerio 效果很好。

标签: node.js xml express web-scraping


【解决方案1】:

试试这个:在这个例子中,我找到了所有的图片网址

const transform = require('camaro')
const cheerio = require('cheerio')

const xml = require('fs').readFileSync('feed.xml', 'utf-8')

const template = {
    data: ['//item/description', '.']
}

const result = transform(xml, template)

const links = result.data.map(html => {
    const $ = cheerio.load(html)
    const links = $('img')
    const urls = []
    $(links).each(function(i, link) {
        urls.push($(link).attr('src'))
    })
    return urls
})

console.log(links)

输出:

[ [ 'https://drscdn.500px.org/photo/629350/m%3D900/v2?webp=true&sig=4a9fa5788049efb196917cc3f1a55601af901c7157b59ec86c8aa3378c6ee557' ],
  [ 'https://drscdn.500px.org/photo/625259/m%3D900/v2?webp=true&sig=55eab44535f05625ad25dae3e805b2559c1caeb4c97570d04ee0a77c52c7fb19' ],
  [ 'https://drscdn.500px.org/photo/625253/m%3D900/v2?webp=true&sig=174d1b27e6f87e0a98192cf6ae051301681a51beb7297df9733956d2763af163' ],
  [ 'https://drscdn.500px.org/photo/509064/m%3D900/v2?webp=true&sig=698e56114e1d8b67ad11823390f8456ae723d3a389191c43192718f18213caa8' ],
  [ 'https://drscdn.500px.org/photo/509061/m%3D900/v2?webp=true&sig=2998212f82a1c3428cebb873830a99b908f463474045d4e5ebba3257808685dd' ],
  [ 'https://drscdn.500px.org/photo/509060/m%3D900/v2?webp=true&sig=8082904fe1935c51fc301a0d10529475ee15124d3797f69cbaeac3fd6c5f0dcb' ],
  [ 'https://drscdn.500px.org/photo/509056/m%3D900/v2?webp=true&sig=4b85086a7bf55709e77febb202636b0e09415c8ca3fc3657bfb889ad827b3cab' ] ]

【讨论】:

  • 谢谢 - 这种方法效果很好。看起来 camaro 执行的功能与 xml2js 相同,但速度更快。
  • @testingtesting 是的,这就是 camaro 的主要用途。以及转换 xml 的能力;不只是转换。
【解决方案2】:

您不需要完整的解析器,只需使用正则表达式即可:

var links = [];
var re    = new RegExp("<img.*?src=['\"](.*?)['\"].*?>", "gmi");
var res;

while(res = re.exec(body)) links.push(res[1]);

例子:

 var a = '<div class="quote"><div class="quote-profile"><img alt="voyages-sncf.com logo" class="img-responsive img-circle" style="height: 80px" src="/img/app_website/index/logo.jpg"> </div><!--//profile--><img alt="voyages-sncf.com logo" class="img-responsive img-circle" style="height: 80px" src="/img/app_website/index/logo2.jpg" data-attr = "lkjlk"/>'

var links = [];
var re    = new RegExp("<img.*?src=['\"](.*?)['\"].*?>", "gmi");
var res;

while(res = re.exec(a)) links.push(res[1]);
//["/img/app_website/index/logo.jpg", "/img/app_website/index/logo2.jpg"]

【讨论】:

  • 请不要推荐正则表达式来解析 HTML。这已经被驳斥了一百万次。这真是个糟糕的建议。 “但它避免了成熟的解析器” 不是一个理由。 HTML 解析器比正则表达式复杂得多,因为正则表达式无法解析 HTML。
猜你喜欢
  • 2019-03-27
  • 2017-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-27
  • 1970-01-01
  • 1970-01-01
  • 2017-04-06
相关资源
最近更新 更多