【问题标题】:Parsing HTML between tags with Nokogiri使用 Nokogiri 解析标签之间的 HTML
【发布时间】:2015-07-16 00:17:10
【问题描述】:

这是我的 HTML 文件的样子:

<a href='http://crossfitquantico.blogspot.com/' target='_blank'>CrossFit Quantico</a> - Quantico,&nbsp;VA<br />
<a href='http://www.crossfitcherrypoint.com' target='_blank'>CrossFit Cherry Point</a> - Havelock,&nbsp;NC<br />
<a href='http://crossfitpentagon.com/' target='_blank'>CrossFit Pentagon</a> - Washington,&nbsp;DC<br />
<a href='http://crossfitwtbn.blogspot.com/' target='_blank'>CrossFit WTBN</a> - Quantico,&nbsp;VA<br />
<a href='http://cfnewriver.blogspot.com/' target='_blank'>CrossFit New River</a> - Jacksonville,&nbsp;NC<br />
<a href='http://xfitmiramar.com' target='_blank'>CrossFit Miramar</a> - San Diego,&nbsp;CA<br />
<a href='http://www.crossfitfortmeade.com/' target='_blank'>CrossFit Fort Meade</a> - Odenton,&nbsp;MD<br />

我能够提取链接内容/副本和 URL,但我还需要提取 &lt;/a&gt; 结尾和下一个 &lt;a&gt; 开头之间的信息,无论是在 &lt;br /&gt; 之前.例如,在第一行我需要提取"Quantico,&amp;nbsp;VA"

这是我的部分代码,我从中提取了我需要的部分信息: 这是我目前正在做的事情(一旦我得到页面对象,我将有一个循环来遍历我拥有的每一行 html 源代码,以便提取我需要的所有数据):

page = Nokogiri::HTML(open("http://www.crossfit.com/cf-info/main_affil.htm")) 
if page.text != ""
    ## Get the URL and Name
    if page.css("a")[i] != nil
        name = page.css("a")[i].text
    else
        name = 'NA'
    end
    if page.css("a")[i] != nil
        url = page.css("a")[i]["href"]
    else
        url = 'NA'
    end
end if

【问题讨论】:

  • 这是一种非常粗暴的 HTML 解析方式。无论如何,你可以用'-'分割每一行,然后在数组中获取最后一个值,这就是你所追求的。
  • 显示您用于提取 URL 的相关代码,以便为我们提供更多上下文
  • 欢迎来到 Stack Overflow。我们并不真正关心你的“新手”,我们只是喜欢好问题。您需要展示您的代码的最小示例,以便我们可以看到您缺少什么。就像你要求我们为你写的一样。此外,您的 HTML 格式不符合您的要求。而不仅仅是链接和尾随中断,应该有包装标签,最好是&lt;html&gt;&lt;body&gt;...&lt;/body&gt;&lt;/html&gt;。 Stack Overflow 需要完整的示例来在寻求帮助调试时演示问题。
  • 感谢您提供的所有帮助。对不起,没有发布我的代码,因为它非常基本,但我在上面的问题中添加了部分代码。再次感谢!
  • 你需要正确缩进你的代码。这是您遇到的最好的调试技巧之一。

标签: html ruby-on-rails ruby xpath nokogiri


【解决方案1】:

通读XML::NodeXML::NodeSet 文档。可用的方法使导航和提取节点成为可能:

require 'nokogiri'

doc = Nokogiri::HTML(<<EOT)
<html>
<body>
<a href='http://crossfitquantico.blogspot.com/' target='_blank'>CrossFit Quantico</a> - Quantico,&nbsp;VA<br />
<a href='http://www.crossfitcherrypoint.com' target='_blank'>CrossFit Cherry Point</a> - Havelock,&nbsp;NC<br />
</body>
</html>
EOT

data = doc.search('a').map{ |link|
  link_href = link['href']
  link_text = link.text
  trailing_text = link.next_sibling.text
  {
    href: link_href,
    text: link_text,
    trailing_text: trailing_text
  }
}

data 将包含:

data 
# => [{:href=>"http://crossfitquantico.blogspot.com/",
#      :text=>"CrossFit Quantico",
#      :trailing_text=>" - Quantico,\u00A0VA"},
#     {:href=>"http://www.crossfitcherrypoint.com",
#      :text=>"CrossFit Cherry Point",
#      :trailing_text=>" - Havelock,\u00A0NC"}]

不要这样做:

page = Nokogiri::HTML(open("http://www.crossfit.com/cf-info/main_affil.htm")) 
if page.text != ""
    ## Get the URL and Name
    if page.css("a")[i] != nil
        name = page.css("a")[i].text
    else
        name = 'NA'
    end
    if page.css("a")[i] != nil
        url = page.css("a")[i]["href"]
    else
        url = 'NA'
    end
end if

if page.text != "" 并没有真正告诉你你想知道什么,就是有没有链接。只需搜索文档即可告诉您。

您每次使用 page.css("a") 时都在 DOM 中搜索链接,这会浪费 CPU。测试page.css("a")[i] != nil 也是一种浪费。如果您正确地遍历包含链接的语法正确的文档,您将永远不会遇到找不到链接的情况,因为 search 或其类似行为会将它们交给您。

以下是对上述代码的小调整,以提供“NA”值:

require 'nokogiri'

doc = Nokogiri::HTML(<<EOT)
<html>
  <body>
    <a href='http://crossfitquantico.blogspot.com/' target='_blank'>CrossFit Quantico</a> - Quantico,&nbsp;VA<br />
    <a href='http://www.crossfitcherrypoint.com' target='_blank'>CrossFit Cherry Point</a> - Havelock,&nbsp;NC<br />
    <a ></a>  
  </body>
</html>
EOT

doc.search('a').class # => Nokogiri::XML::NodeSet
doc.search('a').size # => 3

data = doc.search('a').map{ |link|
  link_href = link['href']
  link_text = link.text
  trailing_text = link.next_sibling.text
  {
    href: link_href || 'NA',
    text: link_text.empty? ? 'NA' : link_text,
    trailing_text: trailing_text
  }
}

data.size # => 3
data.class # => Array
data.first.class # => Hash

data 
# => [{:href=>"http://crossfitquantico.blogspot.com/",
#      :text=>"CrossFit Quantico",
#      :trailing_text=>" - Quantico,\u00A0VA"},
#     {:href=>"http://www.crossfitcherrypoint.com",
#      :text=>"CrossFit Cherry Point",
#      :trailing_text=>" - Havelock,\u00A0NC"},
#     {:href=>"NA", :text=>"NA", :trailing_text=>"  \n  "}]

【讨论】:

  • 很抱歉再次打扰,但我能够提取单行 html 的数据,但是因为我需要从下一行获取相同的数据,依此类推,我将代码放在上面循环内。但是,如何使用您的示例进入下一行?在我拥有一个用作计数器的变量之前的代码上,这很方便,因为我使用了 children[counter] 方法......请建议。再次感谢!
  • 我示例中的代码将遍历文档中的所有链接。它已经是一个循环;这就是search('a').map{ |link| ... } 正在做的事情。它返回一个包含来自每个链接的信息的哈希数组。查看添加的代码。
  • 非常感谢!欣赏!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-16
  • 2013-08-15
  • 1970-01-01
相关资源
最近更新 更多