【问题标题】:Nokogiri not parsing exported bookmark html from Delicious correctlyNokogiri 没有正确解析从 Delicious 导出的书签 html
【发布时间】:2016-09-13 03:36:16
【问题描述】:

我似乎不明白为什么 Nokogori 没有正确解析这个 html 文件。这个 html 文件是从 Delicious 导出的书签。它有 400 个链接,但总是只解析出 254 个链接。我还有其他 Delicious html 导出文件,它们也只找到 254 个链接(具有不同的链接数量)和一个正确解析链接的链接(超过 2000 个链接),所以似乎可能有特定链接导致问题,但是我真的不确定。我在这里链接到 html,因为 html 使这篇文章的正文超过了字符限制。这是一个html的例子(实际的html有400多个标签):

<!DOCTYPE NETSCAPE-Bookmark-file-1>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
<!-- This is an automatically generated file.
It will be read and overwritten.
Do Not Edit! -->
<TITLE>Bookmarks</TITLE>
<H1>Bookmarks</H1>
<DL><p>
<DT><A HREF="http://www.lecartelclothing.com/" ADD_DATE="1459226337" PRIVATE="1" TAGS="montreal,art,design">Le Cartel | Le Cartel Clothing Inc.</A>
<DT><A HREF="http://parkdaleprojectread.org/" ADD_DATE="1459226204" PRIVATE="1" TAGS="ngo">Parkdale Project Read</A>
<DT><A HREF="http://darkmp3.ru/" ADD_DATE="1458608207" PRIVATE="1" TAGS="music,blogs,music_blog,download">Dark mp3</A>
<DT><A HREF="http://www.sbs.com.au/programs/the-family-law/article/family-law-episode-guide" ADD_DATE="1458603937" PRIVATE="1" TAGS="asian,china,cinema">The Family Law: Watch the series | Programs</A>
<DT><A HREF="http://asiansdoingeverything.tumblr.com/" ADD_DATE="1458602744" PRIVATE="1" TAGS="asian,blogs,china">Asians Doing Everything</A>
</DL></p>

我正在使用 Carrierwave gem 上传 html 文件并对其进行解析。我一直在使用的这段代码是(其中 html_upload 是使用 Carrierwave 的模型实例):

doc = Nokogiri::HTML.parse html_upload.file.read
puts doc.css('a').count

【问题讨论】:

  • 欢迎来到 Stack Overflow。请阅读“minimal reproducible example”。您需要问题本身中的最小输入 (HTML) 以及预期输出。不要指望我们到场外为您追踪或减少该信息;相反,请帮助我们帮助您。链接腐烂然后断开,当他们这样做时,您的问题对我们或其他寻求类似解决方案的人没有任何意义。
  • 我试过了,但达到了字符限制,当时我认为 html 的长度与答案有关。
  • 既然您知道这不是真的,最好解决这个问题,使其符合准则。

标签: html ruby nokogiri


【解决方案1】:

当 Nokogiri 未按预期解析文档时,请始终检查 doc.errors

这是我尝试从您的要点解析原始内容时得到的结果:

require 'nokogiri'
doc = Nokogiri.HTML(DATA.read)
puts doc.errors.last
#=> Excessive depth in document: 256 use XML_PARSE_HUGE option

这里的问题是 HTML 文件有大量未闭合的标签(主要是 &lt;DT&gt;,Nokogiri(或者更确切地说是 libxml2)试图将它们嵌套在另一个标签中。图解:

doc = Nokogiri.XML(html,&:noblanks)
puts doc.to_xhtml(indent:2)
#=> <TITLE>Bookmarks</TITLE>
#=> <H1>Bookmarks</H1>
#=> <DL>
#=>   <p>
#=>     <DT>
#=>       <A HREF="http://boomjacak.com/" ...>BOOM JACAK</A>
#=>       <DT>
#=>         <A HREF="http://tropicaliainfursnyc.com/" ...>Tropicalia in Furs Baby!</A>
#=>         <DT>
#=>           <A HREF="https://uptimerobot.com/" ...>Uptime Robot</A>
#=>           <DT>
#=>             <A HREF="http://yagphotovoice.tumblr.com/" ...>EYE SPY</A>
#=>             <DT>
#=>               <A HREF="http://glitterbeat.com/" ...>Glitterbeat &#x2013; Vibrant Global Sounds</A>
#=>               <DT>
#=>                 <A HREF="http://www.puzz.com/stickelsframegames.html" ...>Stickels Frame Games</A>
#=>                 <DT>
#=>                   <A HREF="http://silentdiscosquad.com/" ...>Silent Disco Squad</A>
#=>                   <DT>
#=>                     <A HREF="http://innerfire.ca/" ...>None</A>
#=>                     <DT>
#=>                       <A HREF="http://lidopepper.tumblr.com/" ...>Lido Pimienta - La Papessa</A>
#=>                       <DT>
#=>                         <A HREF="http://cabaretdiaspora.wordpress.com/" ...>Radio Cabaret Diaspora | Musiques urbaines</A>
#=>                         <DT>

你可以告诉 Nokogiri 继续使用'huge' config option

doc = Nokogiri.HTML( myhtml, &:huge )

我个人只是使​​用gsub 稍微修复有问题的 HTML:

html = DATA.read
html.gsub! /<DT>.+?<\/A>$/, '\\0</DT>'
doc = Nokogiri.HTML(html)
p doc.css('a').length
#=> 399

(我查了一下:文件里只有399个链接,不是400个。)

【讨论】:

  • 谢谢!这是一个很好的线索。我最终使用了 'huge' 解析选项: doc = Nokogiri::HTML(data) do |config| config.huge end 这个答案也很有帮助:stackoverflow.com/questions/37542491/…
  • 很高兴您找到了答案。我会把它放在这里,以便其他人更容易找到。请注意,您可以通过更少的输入来做到这一点:doc = Nokogiri.HTML( myhtml, &amp;:huge )
  • 是的,计划选择就是答案和支持。最后一条评论是,问题实际上不在于有太多未闭合的标签(每个书签导出都出于某种原因使用未闭合的
    标签),而是它看起来在一个标签中有太多嵌套标签(限制似乎是 256)。
  • @TenJack 对,但它们是一回事。对于代码&lt;DT&gt;...&lt;DT&gt;...&lt;DT&gt;...&lt;DT&gt;...,XML 解析器的解释是第二个 DT 是第一个 DT 的子代,第三个是第二个的子代,依此类推。在仅添加子级的 256 级之后,默认情况下 libxml2 会退出,因为它假设有问题。通过不关闭标签,它们是嵌套的(从 XML 的角度来看)。
  • 不修复 HTML 并期望解析器解释标记,即使它可以加载文件也是在询问问题。解析器会尝试添加结束标记,但通常不会正确执行,从而导致 DOM 错位,很难导航,因为根据您对标记应该在哪里的想法,它不会匹配您的选择器。依靠huge 会让你陷入困境,而修复标记会让事情变得正确。正如@Phrogz 所说,使用gsub! 来解决问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-30
  • 1970-01-01
  • 1970-01-01
  • 2013-08-29
  • 1970-01-01
  • 2015-05-17
  • 1970-01-01
相关资源
最近更新 更多