使用 Nokogiri 迭代 HTML 的块,无论元素类型如何?
Iterate a block of HTML, regardless of element type, with Nokogiri?
我正在尝试使用 Nokogiri 迭代 HTML 的块,无论元素类型是什么。
例如,给定此变量 html
,通过 Nokogiri 传递:
require 'nokogiri'
html = "<p>Some text</p><ol><li>List item 1</li><li>List item 2</li></ol><p>Last bit of text</p>"
parsed_html = Nokogiri::HTML(html)
我知道我可以通过以下方式遍历每个 <p>
:
parsed_html.css("p").each do |p|
puts p
end
但同样只抓取所有 <p>
标签,而不抓取 <ol>
及其子标签。
我也知道我可以通过以下方式获取 <ol>
:
parsed_html.css("p, ol").each do |p|
puts p
end
但是 我如何遍历所有元素而不用明确说明我想遍历哪些元素?
例如,给定另一个 html 块:
html = "<p>text 1</p><ol><li>item 1</li><li>item 2</li></ol><ul><li>item 1</li></ul><h2>header</h2>"
我怎样才能 return 像这样:
<p>text 1</p>
<ol><li>item 1</li><li>item 2</li></ol>
<ul><li>item 1</li></ul>
<h2>header</h2>
提前致谢。
只是回答你写的问题:
如何遍历所有元素
CSS 接受通配符,因此您可以:
Nokogiri::HTML(html).css("*").map(&:name)
# => ["html", "body", "p", "ol", "li", "li", "p"]
给定“这个html”我如何return“类似”
html = "<p>text 1</p><ol><li>item 1</li><li>item 2</li></ol><ul><li>item 1</li></ul><h2>header</h2>"
puts Nokogiri::HTML(html).css('body').inner_html
# <p>text 1</p>
# <ol>
# <li>item 1</li>
# <li>item 2</li>
# </ol>
# <ul><li>item 1</li></ul>
# <h2>header</h2>
我希望能够遍历所有一级子元素(p,ol,ul,h2)
Nokogiri::HTML(html).css('body').children.map(&:name)
# => ["p", "ol", "ul", "h2"]
parsed_html.css('body > *')
这仅选择元素的直接子元素。
irb(main):015:0> parsed_html = Nokogiri::HTML(html)
irb(main):016:0> parsed_html.css('body > *')
=> [#<Nokogiri::XML::Element:0x3c00 name="p" children=[#<Nokogiri::XML::Text:0x3bec "text 1">]>, #<Nokogiri::XML::Element:0x3c64 name="ol" children=[#<Nokogiri::XML::Element:0x3c28 name="li" children=[#<Nokogiri::XML::Text:0x3c14 "item 1">]>, #<Nokogiri::XML::Element:0x3c50 name="li" children=[#<Nokogiri::XML::Text:0x3c3c "item 2">]>]>, #<Nokogiri::XML::Element:0x3ca0 name="ul" children=[#<Nokogiri::XML::Element:0x3c8c name="li" children=[#<Nokogiri::XML::Text:0x3c78 "item 1">]>]>, #<Nokogiri::XML::Element:0x3cc8 name="h2" children=[#<Nokogiri::XML::Text:0x3cb4 "header">]>]
irb(main):017:0> parsed_html.css('body > *').map {|e| e.name }
=> ["p", "ol", "ul", "h2"]
这是可行的,因为当您使用 Nokogiri::HTML:
时,Nokogiri 会创建一个骨架
irb(main):018:0> parsed_html.to_s
=> "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body>\n<p>text 1</p>\n<ol>\n<li>item 1</li>\n<li>item 2</li>\n</ol>\n<ul><li>item 1</li></ul>\n<h2>header</h2>\n</body></html>\n"
您也可以只使用 Nokogiri::HTML.fragment 而不是 HTML()
:
frag = Nokogiri::HTML.fragment(html)
frag.children.map(&:to_html).join("\n")
我正在尝试使用 Nokogiri 迭代 HTML 的块,无论元素类型是什么。
例如,给定此变量 html
,通过 Nokogiri 传递:
require 'nokogiri'
html = "<p>Some text</p><ol><li>List item 1</li><li>List item 2</li></ol><p>Last bit of text</p>"
parsed_html = Nokogiri::HTML(html)
我知道我可以通过以下方式遍历每个 <p>
:
parsed_html.css("p").each do |p|
puts p
end
但同样只抓取所有 <p>
标签,而不抓取 <ol>
及其子标签。
我也知道我可以通过以下方式获取 <ol>
:
parsed_html.css("p, ol").each do |p|
puts p
end
但是 我如何遍历所有元素而不用明确说明我想遍历哪些元素?
例如,给定另一个 html 块:
html = "<p>text 1</p><ol><li>item 1</li><li>item 2</li></ol><ul><li>item 1</li></ul><h2>header</h2>"
我怎样才能 return 像这样:
<p>text 1</p>
<ol><li>item 1</li><li>item 2</li></ol>
<ul><li>item 1</li></ul>
<h2>header</h2>
提前致谢。
只是回答你写的问题:
如何遍历所有元素
CSS 接受通配符,因此您可以:
Nokogiri::HTML(html).css("*").map(&:name)
# => ["html", "body", "p", "ol", "li", "li", "p"]
给定“这个html”我如何return“类似”
html = "<p>text 1</p><ol><li>item 1</li><li>item 2</li></ol><ul><li>item 1</li></ul><h2>header</h2>"
puts Nokogiri::HTML(html).css('body').inner_html
# <p>text 1</p>
# <ol>
# <li>item 1</li>
# <li>item 2</li>
# </ol>
# <ul><li>item 1</li></ul>
# <h2>header</h2>
我希望能够遍历所有一级子元素(p,ol,ul,h2)
Nokogiri::HTML(html).css('body').children.map(&:name)
# => ["p", "ol", "ul", "h2"]
parsed_html.css('body > *')
这仅选择元素的直接子元素。
irb(main):015:0> parsed_html = Nokogiri::HTML(html)
irb(main):016:0> parsed_html.css('body > *')
=> [#<Nokogiri::XML::Element:0x3c00 name="p" children=[#<Nokogiri::XML::Text:0x3bec "text 1">]>, #<Nokogiri::XML::Element:0x3c64 name="ol" children=[#<Nokogiri::XML::Element:0x3c28 name="li" children=[#<Nokogiri::XML::Text:0x3c14 "item 1">]>, #<Nokogiri::XML::Element:0x3c50 name="li" children=[#<Nokogiri::XML::Text:0x3c3c "item 2">]>]>, #<Nokogiri::XML::Element:0x3ca0 name="ul" children=[#<Nokogiri::XML::Element:0x3c8c name="li" children=[#<Nokogiri::XML::Text:0x3c78 "item 1">]>]>, #<Nokogiri::XML::Element:0x3cc8 name="h2" children=[#<Nokogiri::XML::Text:0x3cb4 "header">]>]
irb(main):017:0> parsed_html.css('body > *').map {|e| e.name }
=> ["p", "ol", "ul", "h2"]
这是可行的,因为当您使用 Nokogiri::HTML:
时,Nokogiri 会创建一个骨架irb(main):018:0> parsed_html.to_s
=> "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body>\n<p>text 1</p>\n<ol>\n<li>item 1</li>\n<li>item 2</li>\n</ol>\n<ul><li>item 1</li></ul>\n<h2>header</h2>\n</body></html>\n"
您也可以只使用 Nokogiri::HTML.fragment 而不是 HTML()
:
frag = Nokogiri::HTML.fragment(html)
frag.children.map(&:to_html).join("\n")