我正在尝试使用nokogiri来解析以下段
<tr>
<th>Total Weight</th>
<td>< 1 g</td>
<td style="text-align: right">0 %</td>
</tr>
<tr><td class="skinny_black_bar" colspan="3"></td></tr>
然而,我认为“&lt;”登录“&lt; 1 g”导致Nokogiri问题。有谁知道任何变通方法?有没有办法逃脱“&lt;”标志?或者也许我可以调用一个函数来获取普通的html片段?
答案 0 :(得分:4)
作为一个快速修复,我想出了这个方法,使用reqular表达式来识别未闭合的标签:
def fix_irregular_html(html)
regexp = /<([^<>]*)(<|$)/
#we need to do this multiple time as regex are overlapping
while (fixed_html = html.gsub(regexp, "<\\1\\2")) && fixed_html != html
html = fixed_html
end
fixed_html
end
查看完整代码,包括此处的测试: https://gist.github.com/796571
对我来说效果很好,我感谢任何反馈和改进
答案 1 :(得分:2)
“小于”(&lt;)isn't legal HTML,但浏览器有很多代码用于确定HTML的含义而不仅仅是显示错误。这就是为什么您的无效HTML示例会以您希望的方式显示在浏览器中。
所以诀窍是确保Nokogiri做同样的工作来弥补糟糕的HTML。确保将文件解析为HTML而不是XML:
f = File.open("table.html")
doc = Nokogiri::HTML(f)
这样可以很好地解析您的文件,但会丢弃< 1 g
文本。看看如何解析前两个TD元素的内容:
doc.xpath('(//td)[1]/text()').to_s
=> "\n "
doc.xpath('(//td)[2]/text()').to_s
=> "0 %"
Nokogiri抛弃了你的无效文本,但不断解析周围的结构。你甚至可以看到Nokogiri的错误信息:
doc.errors
=> [#<Nokogiri::XML::SyntaxError: htmlParseStartTag: invalid element name>]
doc.errors[0].line
=> 3
是的,第3行很糟糕。
因此,似乎Nokogiri对解析无效HTML的支持程度与浏览器不同。我建议使用其他一些库来预处理您的文件。我尝试在您的示例文件上运行TagSoup并修改<
,将其更改为<
,如下所示:
% java -jar tagsoup-1.1.3.jar foo.html | xmllint --format -
src: foo.html
<?xml version="1.0" standalone="yes"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<table>
<tbody>
<tr>
<th colspan="1" rowspan="1">Total Weight</th>
<td colspan="1" rowspan="1"><1 g</td>
<td colspan="1" rowspan="1" style="text-align: right">0 %</td>
</tr>
<tr>
<td colspan="3" rowspan="1" class="skinny_black_bar"/>
</tr>
</tbody>
</table>
</body>
</html>