【问题标题】:Eliminating CSS selectors when parsing with Nokogiri?使用 Nokogiri 解析时消除 CSS 选择器?
【发布时间】:2014-03-05 07:28:09
【问题描述】:

我正在从 cnn.com 网站检索最新的新闻文章,并为此编写了一个简单的 Nokogiri 脚本:

url = "http://edition.cnn.com/?refresh=1"
doc = Nokogiri::HTML(open(url))
puts doc.at_css("title").text
  doc.css("#cnn_maintt2bul div+ div a").each do |headline|
  article = headline.text
  puts "#{article}"
end

问题是,CNN 发布的文章和视频链接混杂在一起。现在我只对文章而不是视频感兴趣。例如,当我运行此脚本时,它会检索所有文章,但会在文章链接到视频时留下一个空格。

Pakistan airstrikes kill dozens
Could U.S. leave Afghanistan?
Editor's stabbing draws outrage
Ukrainian city fears uprising

U.S. hate groups in decline

这意味着Ukrainian city fears uprising 实际上会链接到视频。它会一直这样做,直到检索到最后一篇文章。

我发现文章有一个名为.cnnVideoIcon 的选择器。关于如何消除这种情况以从我的结果中删除链接到视频的文章有什么想法吗?

解析时如何消除此类链接?它们可以出现在任何地方。

【问题讨论】:

  • 你能提供一个你正在抓取的网站的链接吗?

标签: css ruby nokogiri


【解决方案1】:

我查看了CNN网站的HTML源代码,发现一个视频标题的“li”标签有四个子元素,而带有文字标题的子元素只有三个。

<li class="c_hpbullet3" data-vr-contentbox=""> 
   <span class="cnnPreWOOL"></span> 
   <a href="/video/data/2.0/video/world/2014/02/25/ctw-ukraine-political-aftermath-ian-bremmer-intv.cnn.html?hpt=hp_t5">Ukrainian politics remain in flux</a> 
   <span class="cnnPostWOOL"></span> &nbsp;
   <a href="/video/data/2.0/video/world/2014/02/25/ctw-ukraine-political-aftermath-ian-bremmer-intv.cnn.html?hpt=hp_t5" target=""><img class="cnnVideoIcon" width="16" height="10" border="0" alt="Ukrainian politics remain in flux" src="http://i.cdn.turner.com/cnn/.e/img/3.0/global/icons/video_icon.gif"></a> 
</li>

所以,我们可以使用下面的 XPath 语法:

doc.xpath("//div[@id='cnn_maintt2bul']/div/div/ul/li[count(*)=3]/a").each do |headline|
  article = headline.text
  puts "#{article}"
end

【讨论】:

【解决方案2】:

如果您查看从 http://edition.cnn.com/?refresh=1 抓取的块的源代码,您会注意到视频是带有视频图标(没有文字)的链接,如下所示:

<a href="/video/data/...">
   <img class="cnnVideoIcon" alt="Ukrainian city fears uprising" ... 
        height="10" width="16">
</a>

这解释了为什么会出现一些空行。

您可以使用更精细的选择器跳过这些链接,例如:

#cnn_maintt2bul div + div a:empty

使用a:empty,您将只检索没有图像或内部其他元素的链接,或者换句话说,所有只有描述文本的链接。


另一种(优化程度较低的)方法是简单地使用 if 语句跳过空行:

doc.css("#cnn_maintt2bul div + div a").each do |headline|
article = headline.text
if (article != "")
    puts "#{article}"
...

【讨论】:

    【解决方案3】:

    您应该使用 CSS 属性以外的其他东西来查找所需的标签。使用 search 而不是 css 并为其提供一个 XPath,该 XPath 仅选择没有视频链接的元素作为子元素。

    当您提供指向要从中获取信息的站点的真实 URL 时,我将使用指定的 XPath 更新答案。

    【讨论】:

    • 该 url 是上面显示的脚本中的确切 url。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-03
    • 1970-01-01
    • 2010-12-27
    • 1970-01-01
    • 1970-01-01
    • 2018-08-19
    • 1970-01-01
    相关资源
    最近更新 更多