NokogiriNokogiri入门


备注

本节概述了Nokogiri是什么,以及开发人员为什么要使用它。

它还应该提到Nokogiri内的任何大型主题,并链接到相关主题。由于Nokogiri的文档是新的,您可能需要创建这些相关主题的初始版本。

如何检查解析错误

Nokogiri有点像浏览器,因为即使传入的HTML或XML格式错误,它也会尝试提供有用的东西。不幸的是,它通常会默默地执行此操作,但我们可以使用errors 请求错误列表:

require 'nokogiri'

doc = Nokogiri::XML('<node><foo/>')
doc.errors
# => [#<Nokogiri::XML::SyntaxError: 1:13: FATAL: Premature end of data in tag node line 1>]
 

而,正确的XML将导致没有错误:

doc = Nokogiri::XML('<node><foo/></node>')
doc.errors
# => []
 

这也适用于解析HTML,但是,因为HTML是一种轻松的XML形式,Nokogiri会经常传递丢失的端节点,并且只报告格式错误的节点和更多的病态错误:

doc = Nokogiri::HTML('<html><body>')
doc.errors
# => []

doc = Nokogiri::HTML('<html><body><p')
doc.errors
# => [#<Nokogiri::XML::SyntaxError: 1:15: ERROR: Couldn't find end of Start Tag p>]
 

如果在解析后找不到可在编辑器中看到的节点,则可能是问题的原因。有时,通过格式化程序传递HTML有助于查看嵌套是否有助于揭示问题。

并且,因为Nokogiri试图解决问题,但有时无法正确解决问题,因为对软件来说这可能是一件非常困难的事情,我们必须预先处理文件并在交付之前修补线条到Nokogiri。怎么做取决于文件和问题。它可以从简单地找到一个节点和添加一个尾随> ,到删除由一个糟糕的抓取例程注入的嵌入式格式错误标记,所以这取决于程序员如何最好地进行调解。

如何从一个或多个节点提取文本

如何正确地从节点中提取文本是我们看到的最受欢迎的问题之一,并且通过滥用Nokogiri的“搜索”方法几乎总是变得更加困难。

Nokogiri支持使用CSS和XPath选择器。这些是等价的:

doc.at('p').text   # => "foo"
doc.at('//p').text # => "foo"

doc.search('p').size   # => 2
doc.search('//p').size # => 2
 

为方便起见,CSS选择器扩展了许多jQuery的CSS扩展

at search at_css at_xpath 通用版本以及css xpath 。引入nokogiri做出尝试,以确定是否CSS或XPath选择正在被通过。它可以创建一个傻瓜选择atsearch 所以偶尔会产生误解,这就是为什么我们的方法更具体的版本。一般来说,我几乎总是使用通用版本,如果我认为Nokogiri会误解,只使用特定版本。这种做法属于“ 三德 ”的第一个条目。

如果要搜索一个特定节点并想要其文本,则使用at 或其中一个at_cssat_xpath 变体:

require 'nokogiri'

doc = Nokogiri::HTML(<<EOT)
<html>
  <body>
    <p>foo</p>
    <p>bar</p>
  </body>
</html>
EOT

doc.at('p').text # => "foo"
 

at 等同于search(...).first ,所以你可以使用更长的类型版本,但为什么呢?

如果在使用searchcssxpath 之后连接的文本被连接,则添加map(&:text) 而不是简单地使用text

require 'nokogiri'

doc = Nokogiri::HTML(<<EOT)
<html>
  <body>
    <p>foo</p>
    <p>bar</p>
  </body>
</html>
EOT

doc.search('p').text        # => "foobar"
doc.search('p').map(&:text) # => ["foo", "bar"]
 

有关其他信息,请参阅NodeSetNodetext 文档。

如何将HTML或XML解析为Nokogiri XML或HTML文档

Nokogiri的“ 解析HTML / XML文档 ”教程没有太多内容,这是一个简单的主题介绍,所以从那里开始,然后返回到这个页面来帮助填补一些空白。

Nokogiri的基本解析尝试清理格式错误的文档,有时添加缺少的结束标记,并添加一些额外的标记以使其正确。

这是告诉Nokogiri正在解析的文档是一个完整的HTML文件的例子,Nokogiri发现它不是:

require 'nokogiri'

doc = Nokogiri::HTML('<body></body>')
puts doc.to_html 
 

哪个输出:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body></body></html>
 

请注意,添加了DTD语句以及包装<html> 标记。

如果我们想避免这种情况,我们可以将文档解析为DocumentFragment:

require 'nokogiri'

doc = Nokogiri::HTML.fragment('<body></body>')
puts doc.to_html 
 

现在只输出实际传入的内容:

<body></body>
 

还有一个XML变体:

require 'nokogiri'

doc = Nokogiri::XML('<node />')
puts doc.to_xml
 

哪个输出:

<?xml version="1.0"?>
<node/>
 

和:

doc = Nokogiri::XML.fragment('<node />')
puts doc.to_xml
 

导致:

<node/>
 

更冗长的fragment 变体是使用DocumentFragment.parse ,所以有时你会看到它以这种方式编写。

偶尔,Nokogiri将不得不做一些修复工作来尝试理解文档:

doc = Nokogiri::XML::DocumentFragment.parse('<node ><foo/>')
puts doc.to_xml
 

修改后的代码现在是:

<node>
  <foo/>
</node>
 

HTML也是如此。

有时文档会被Nokogiri修复它的能力所破坏,但无论如何都会尝试,导致文档的层次结构发生变化。 Nokogiri不会引发异常,但它确实提供了一种检查错误及其所采取措施的方法。有关详细信息,请参阅“ 如何检查解析错误 ”。

有关解析时使用的各种选项,请参阅Nokogiri :: XML :: ParseOptions文档。

安装或设置

有关获取Nokogiri设置或安装的详细说明。