Ruby Nokogiri库怎么解析HTML和XML?

来源:安卓APP网作者:又改需求头衔:程序员
导读:本期聚焦于又改需求创作的《Ruby Nokogiri库怎么解析HTML和XML?》,敬请观看详情。正则表达式处理不规则HTML时经常失效,嵌套和缺失标签会让匹配逻辑变得非常脆弱。Ruby 的 Nokogiri 库通过底层 libxml2 把 HTML 或 XML 解析成节点树,让开发者用 CSS 选择器和 XPath 直接定位元素,而不必关心标签是否闭合。本文从安装讲起,介绍解析字符串、文件和抓取网页的完整流程,演示 at_css、css、xpath、attribute、content 等核心方法的用法。针对 XML 场景,还会说明命名空间查询和严格解析模式,以及 HTML 容错解析的差异。除了读取数据,文章也包含修改节点、删除元素、创建新节点和序列化输出等操作,帮助你把解析结果重新写回文档。掌握这些技巧后,可以在爬虫、数据清洗、RSS 订阅解析、SOAP 接口对接等工作中稳定使用 Nokogiri。

在 Ruby 生态中,Nokogiri 是解析 HTML 和 XML 的首选方案。它会把一份文档转换成可遍历的节点树,每一个标签、属性、文本片段都变成对应的节点对象。这样一来,抓取网页数据时就不用再拼接正则表达式和字符串截取,解析 XML 接口时也能依靠标准化的查询语法。Nokogiri 底层依赖 libxml2 和 libxslt,处理速度较快,同时提供了 Ruby 风格的方法调用。下面从安装开始,分几个场景说明它的核心用法。

Ruby Nokogiri库怎么解析HTML和XML?

安装与基础解析方法

安装 Nokogiri 最直接的方式是使用 gem 命令,也可以在 Gemfile 里声明依赖。不同操作系统可能需要编译原生扩展,安装前通常需要确保系统已有 libxml2 和 libxslt 开发包。对于 Debian 或 Ubuntu 系统,可以先安装 libxml2-devlibxslt1-dev,再执行 gem 安装。Windows 平台一般使用预编译包,RubyInstaller 会处理大部分依赖问题。

gem install nokogiri
bundle add nokogiri

解析 HTML 使用 Nokogiri::HTML,解析 XML 使用 Nokogiri::XML。两个方法都接受字符串、File 对象或 IO 对象。HTML 模式会自动补全缺失的 <html><body> 等结构,所以只解析一段片段也能得到完整文档树。XML 模式则更严格,遇到未闭合标签会直接抛出错误,适合用来校验接口返回的格式是否合法。

require 'nokogiri'

html = '<div><p>Hello</p></div>'
doc = Nokogiri::HTML(html)
puts doc.at_css('p').text

xml = '<root><item id="1">数据</item></root>'
xml_doc = Nokogiri::XML(xml)
puts xml_doc.root.name
puts xml_doc.at_xpath('//item')['id']

从磁盘读取时,直接传 File 对象或字符串都可以。遇到中文页面建议先通过响应的 charset 设置编码,或者用 Nokogiri::HTML(html, nil, 'UTF-8') 指定编码,避免乱码。对于片段解析,使用 Nokogiri::HTML.fragment 可以避免自动包裹完整文档结构,这对把解析结果插入到其他文档时特别有用。

CSS选择器与XPath定位

Nokogiri 同时支持 CSS 选择器和 XPath,两者可以混合使用,也可以在同一节点上连续调用。css 方法返回一个 NodeSet,类似数组,可以遍历;at_css 只返回第一个匹配项。获取属性可以用 []attribute,获取文本用 textcontent。CSS 写法直观,适合抓取结构清晰的网页。

html = '<div class="content"><p>第一段</p><p>第二段</p></div>'
doc = Nokogiri::HTML(html)

doc.css('div.content p').each do |p|
  puts p.text
end

first_p = doc.at_css('div.content p')
puts first_p['class'].inspect

XPath 更擅长处理复杂条件,例如按文本内容匹配、选择包含某个属性的节点、按照位置选择子节点。处理 XML 时如果节点带命名空间,直接写 //ex:item 会找不到,需要把前缀和命名空间 URI 组成哈希传给 at_xpathxpath。这种场景在解析 RSS、SOAP 响应时非常常见。

xml = '<root xmlns:ex="http://bbccb.com"><ex:item>数据</ex:item></root>'
doc = Nokogiri::XML(xml)
ns = { 'ex' => 'http://bbccb.com' }
item = doc.at_xpath('//ex:item', ns)
puts item.text

在大型文档中,频繁调用 cssxpath 会反复遍历整棵树。建议先在父节点上搜索一次,把结果保存为 NodeSet,再在需要时调用 NodeSet#at_css 等相对查询方法。比如已经拿到某个卡片节点,再用 card.at_css('.title'),范围会比从 doc 全局搜索小很多。

遍历、修改和序列化节点树

节点树可以沿着父子关系移动。常用方法包括 childrenparentnext_elementprevious_elementancestors。要注意 children 返回的不仅仅是元素节点,还可能包括文本节点和注释节点,如果只想处理标签,可以使用 element_children。下面例子演示如何遍历一个列表项并过滤掉换行以外的文本节点。

html = '<ul id="list"><li>苹果</li><li>香蕉</li></ul>'
doc = Nokogiri::HTML(html)

doc.at_css('#list').element_children.each do |li|
  puts li.text
end

修改节点内容非常直接。给 content= 赋值会替换节点内部的全部文本,给属性赋值可以写 node['class'] = 'new-class'。删除节点调用 remove,如果需要保留子节点,可以先解绑再删除。创建新节点时,推荐使用 Nokogiri::XML::Node.new 并传入当前文档对象,这样新节点会继承文档的编码和命名空间设置。添加节点可以用 add_childbeforeafter

html = '<div><h1>原始标题</h1></div>'
doc = Nokogiri::HTML(html)

heading = doc.at_css('h1')
heading.content = '新标题'
heading['class'] = 'main-title'

doc.css('script, style').each(&:remove)

new_p = Nokogiri::XML::Node.new('p', doc)
new_p.content = '这是新增的段落'
doc.at_css('div').add_child(new_p)

puts doc.to_html

最后可以通过 to_htmlto_xml 把修改后的文档序列化回去。HTML 模式输出的内容会比较紧凑,如果需要格式化,可以使用 to_html(indent: 2) 之类的参数,但需注意 Nokogiri 版本对缩进参数的支持差异。XML 输出前还要确认声明和编码信息是否保留,通常 to_xml 会生成 <?xml version="1.0"?> 声明。

HTML与XML解析模式的差异

HTML 模式会尽量修复错误,因此即使你只传入一段 <p> 文本,Nokogiri 也会自动补全 <html><body>。这个特性对处理真实网页非常有用,因为很多网页的标签嵌套并不规范。但对于 XML,这种自动修复并不存在,任何不匹配或未转义的实体都会导致解析异常,这正好可以用来发现上游接口产出的非法内容。

# HTML 容错示例
html = '<p>这是段落<div>嵌套内容'
doc = Nokogiri::HTML(html)
puts doc.at_css('div').text rescue nil

# XML 严格解析
begin
  xml = '<root><item>未闭合'
  Nokogiri::XML(xml)
rescue Nokogiri::XML::SyntaxError => e
  puts e.message
end

HTML 解析器对标签和属性名的大小写不太敏感,通常会统一转换为小写。XML 则严格保留大小写,因此 <Item><item> 是两个完全不同的元素。命名空间在 XML 中也必须提前声明,否则 XPath 查询无法命中。处理第三方 XML 时,建议先打印 doc.root.namespaces 查看实际命名空间映射,再构造 XPath 的哈希参数,避免拿到空结果后反复调试查询表达式。

此外,如果一个 XML 文档很大,比如包含几万条记录,直接加载为完整节点树会占用大量内存。Nokogiri 提供了 Nokogiri::XML::Reader 用于流式读取,使用游标逐条访问节点,适合做增量处理。也可以使用 SAX 解析器,在事件回调中处理特定标签,但代码会更复杂一些。

网络抓取实战与内存优化

在爬虫场景中,通常先通过 open-uri 或 HTTP 客户端获取页面内容,再把响应体交给 Nokogiri。Ruby 3 之后的 open-uri 推荐使用 URI.open。抓取结束后,最好先移除 <script><style> 节点,这样可以避免脚本内容干扰后续文本提取。下面是一个抓取标题列表的简单示例。

require 'open-uri'
require 'nokogiri'

url = 'https://bbccb.com/articles'
html = URI.open(url).read
doc = Nokogiri::HTML(html)

doc.css('h2.title').each do |h|
  puts h.text.strip
end

真实网页经常存在编码声明不准确的问题。可以先用响应头中的 charset 设置字符串的 encoding,再调用 Nokogiri::HTML。如果是压缩内容,需要先解压再解析。清洗数据时,不要直接对整个文档执行 to_text,而应该先定位到需要的主体容器,再提取段落,这样能显著减少导航、广告等无关文本的干扰。

对于需要定期同步的 XML 源,比如商品库存或 RSS,建议使用流式解析而不是一次性加载全部内容。先根据业务需求只保存需要的字段,不保留完整节点树。如果必须加载整棵树,也应该在处理完成后显式释放引用,让垃圾回收器尽快回收内存。Nokogiri 的原生扩展对象在 Ruby 侧被回收后,底层 C 结构也会相应释放,但短时间内解析大量文档时,手动置空对象或分批处理仍然是更稳妥的做法。

Ruby NokogiriHTML解析XML解析修改时间:2026-09-19 21:43:22

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。