代码之家  ›  专栏  ›  技术社区  ›  Argus9

nokogiri-将多行`<link>`标记分析为链接和文本

  •  3
  • Argus9  · 技术社区  · 6 年前

    我正在使用Nokogiri解析播客的RSS源。我正试图抓取一段特定的数据,其中包含到该集的链接,所以我使用Nokogiri来解析RSS提要的XML响应。

    相关位如下:

    <item>
      <title>An awesome title!</title>
      ...
      <link>
        http://www.foobar.com/episodes/1
      </link>
    </item>
    

    Nokogiri似乎很难抓住 <link> 不过,我可以 <item> 标记为 Nokogiri::Node 对象,我可以抓住标题 node.css('title').text 但是当我用同样的方法 node.css('link').text ,我得到一个空字符串。

    我试过打电话 node.children.to_a 为了检查这个节点中的所有子节点,我注意到一些奇怪的事情:在 <链接> 正在将标记分析为单独的子级:

    [0] = {Nokogiri::XML::Element} <title>An awesome title!</title>\n
    [1] = {Nokogiri::XML::Element} <link>
    [2] = {Nokogiri::XML::Text} http://www.foobar.com/episodes/1\n
    

    有没有一种方法可以帮助Nokogiri正确解析这个多行标记,这样我就可以获取里面的文本?

    更新: 这是我遇到这个问题时正在执行的确切代码。

    require 'open-uri'
    doc = Nokogiri::HTML(open('https://rss.acast.com/abroadinjapan')) # Returns Nokogiri::HTML::Document
    node = doc.css('//item').first # Returns Nokogiri::XML::Element
    node.css('title').text # Returns "Abroad in Japan: Two weeks more in Japan!"
    node.css('link').text # Returns ""
    node.css('link').inner_text # Also returns "" - saw this elsewhere and thought I'd try it
    node.children.to_a # Result, parsed by RubyMine for readability:
    
    result = Array (14 elements)
     [0] = {Nokogiri::XML::Element} <title>Abroad in Japan: Two weeks more in Japan!</title>\n
     [1] = {Nokogiri::XML::Element} <subtitle>Chris and Pete return and they've planned out a very different route through Northern Japan.&amp;nbsp;\n\n\nOur Google Map can be found here:&amp;nbsp;\ngoo.gl/3t4t3q&amp;nbsp;\n\n\nGet in touch:&amp;nbsp;abroadinjapanpodcast@gmail.com&amp;nbsp;\nMore Abr...</subtitle>
     [2] = {Nokogiri::XML::Element} <summary></summary>
     [3] = {Nokogiri::XML::Element} <guid ispermalink="false"></guid>
     [4] = {Nokogiri::XML::Element} <pubdate>Wed, 16 May 2018 21:00:00 GMT</pubdate>
     [5] = {Nokogiri::XML::Element} <duration>01:00:00</duration>
     [6] = {Nokogiri::XML::Element} <keywords></keywords>
     [7] = {Nokogiri::XML::Element} <explicit>no</explicit>
     [8] = {Nokogiri::XML::Element} <episodetype>full</episodetype>
     [9] = {Nokogiri::XML::Element} <image href="https://imagecdn.acast.com/image?h=1500&amp;w=1500&amp;source=https%3A%2F%2Fmediacdn.acast.com%2Fassets%2Fcb30d29f-7342-46f0-a649-12f1b4e601f7%2Fcover-image-jgyt2ecc-japan.jpg"></image>
     [10] = {Nokogiri::XML::Element} <description>Chris and Pete return and they've planned out a very different route through Northern Japan. <p><br></p>\n<p>Our Google Map can be found here: </p>\n<p><a href="https://foobar.com/zqWZss9GSF" target="_blank">goo.gl/3t4t3q </a></p>\n<p><br></p>\n<p>Get in touch: <a href="mailto:abroadinjapanpodcast@gmail.com" target="_blank">abroadinjapanpodcast@gmail.com</a> </p>\n<p>More Abroad In Japan shows available below, do subscribe, rate and review us on iTunes, and please tell your friends! </p>\n<p><br></p>\n<p><a href="http://www.radiostakhanov.com/abroadinjapan/" target="_blank">http://www.radiostakhanov.com/abroadinjapan/</a></p>]]&gt;</description>
     [11] = {Nokogiri::XML::Element} <link>
     [12] = {Nokogiri::XML::Text} https://www.acast.com/abroadinjapan/abroadinjapan-twoweeksmoreinjapan-\n                
     [13] = {Nokogiri::XML::Element} <enclosure url="https://media.acast.com/abroadinjapan/abroadinjapan-twoweeksmoreinjapan-/media.mp3" length="28806528" type="audio/mpeg"></enclosure>
    

    注意:上面的一个URL使用了一个URL缩短器,这是不喜欢的,所以我将它替换为 foobar.com .

    1 回复  |  直到 6 年前
        1
  •  3
  •   Casper    6 年前

    修复比你想象的要简单得多。RSS源不是有效的HTML,但它与XML一起使用:

    doc = Nokogiri::XML(open('...'))
    

    Ruby也有一个 module named RSS 可能更适合这样的情况:

    require 'rss'
    doc = RSS::Parser.parse(open('...'))
    doc.items.first.link
    => "https://...."