我正在开发一个应用程序,需要使用其中的表解析一个网站。由于派生用于抓取网页的XPath表达式是无聊且容易出错的工作,所以我想使用Firebug(或其他浏览器中的类似工具)的XPath提取器功能。
示例输入如下所示:
<!-- snip --> <table id="example"> <tr> <th>Example Cell</th> <th>Another one</th> </tr> <tr> <td>foobar</td> <td>42</td> </tr> </table> <!-- snip -->
我想提取第一个数据单元格(“foobar”)。 Firebug提出XPath表达式
//table[@id="example"]/tbody/tr[2]/td[1]
在任何XPath测试插件中都可以正常工作,但不是我自己的应用程序(没有找到结果)。如果我将查询裁减到// [@id],它可以再次工作。
怎么了?
解决方法
Firebug,Chrome的开发者工具,JavaScript中的XPath功能和其他功能在DOM上工作,而不是基本的HTML源代码。
HTML的DOM要求脚本标题(< aad />,< tfoot />)中不包含的所有表行都包含在表体标签< tbody />中。因此,如果浏览器在解析(X)HTML时丢失,则添加此标签。例如,Microsoft’s DOM documentation说
The
tbody
element is exposed for all tables,even if the table does not explicitly define atbody
element.
有一个in-depth explanation in another answer on stackoverflow。
另一方面,HTML does not necessarily require that tag to be used:
The
TBODY
start tag is always required except when the table contains only one table body and no table head or foot sections.
大多数XPath处理器在原始XML上工作
排除JavaScript,大多数XPath处理器可以处理原始XML,而不是DOM,因此不会添加< tbody />标签。另外像tag-soup和htmltidy这样的HTML解析器库只输出XHTML,而不是“DOM-HTML”。
这是Stackoverflow for PHP,Ruby,Python,Java,C#,Google Docs(Spreadsheets)等等的一个常见问题。 Selenium在浏览器中运行,并在DOM上运行 – 因此它不受影响!
重现问题
比较Firebug(或Chrome的开发工具)所显示的源代码,通过右键单击并选择“显示页面源”(或浏览器中的任何内容) – 或使用curl http://your.example .org在命令行。较后者可能不会包含任何< tbody />元素(它们很少使用),Firebug将始终显示它们。
检查你卡住的表是否真的不包含< tbody />元素(见最后一段)。如果是这样,你可能有另一种问题。
//table[@id="example"]/tr[2]/td[1]
这是一个相当脏的解决方案,可能会为嵌套表失败(可以跳转到内表)。在极少数情况下,我只会建议这样做。
将/ tbody轴步骤替换为后代或自身步骤:
//table[@id="example"]//tr[2]/td[1]
如果您不提前确定您的表,或者在“HTML源”和DOM上下文中使用查询,并且不希望/不能使用解决方案2中的黑客,提供替代查询(对于XPath 1.0)或使用“可选”轴步骤(XPath 2.0及更高版本)。
> XPath 1.0:// table [@ id =“example”] / tr [2] / td [1] | //表[@ ID = “例如”] / tbody的/ TR [2] / TD [1]> XPath 2.0:// table [@ id =“example”] /(tbody,。)/ tr [2] / td [1]