当前位置: 首页 > 面试题库 >

为什么我的XPath查询(抓取HTML表)只能在Firebug中工作,而不能在我正在开发的应用程序中工作?

夏经武
2023-03-14
问题内容

这旨在对每周出现一次或两次的所有类似问题(但过于具体的问题,不能成为接近的目标候选人)提供规范的问答。

我正在开发一个应用程序,该应用程序需要解析带有表的网站。由于派生用于抓取网页的XPath表达式很无聊且容易出错,因此我想为此使用 FirebugXPath提取器功能 (或其他浏览器中的类似工具)。

输入示例如下所示:

<!-- 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测试器插件中正常工作,但不能在我自己的应用程序中工作(未找到结果)
。如果我将查询缩减为//table[@id],它将再次起作用。

怎么了


问题答案:

问题:DOM需要<tbody/>标签

Firebug,Chrome的开发人员工具,JavaScript中的XPath函数以及其他功能都可以在 DOM上运行 ,而不是基本的
HTML源代码

HTML的DOM要求表主体标签中包含页脚(<thead/><tfoot/>)的表头中未包含的所有表行<tbody/>。因此,如果解析(X)HTML时缺少该标记,浏览器将添加该标记。

tbody即使表未显式定义tbody元素,该元素也会显示给所有表。

另一方面,HTML不一定要求使用该标记:

TBODY开始标签总是需要当表包含只有一个表的身体和没有表头或脚的部分除外。

大多数XPath处理器都可以在原始XML上运行

除JavaScript外,大多数XPath处理器都在原始XML(而不是DOM)上工作,因此不添加<tbody/>标签。另外,HTML解析器库(例如tag-soup”显示标记为“ tag-soup”的问题”)和htmltidy仅输出XHTML,而不输出“ DOM-HTML”。

这是在Stackoverflow上发布的常见问题,适用于PHP,Ruby,Python,Java,C#,GoogleDocs(电子表格)以及许多其他问题。
Selenium在浏览器中运行并在DOM上运行-因此不受影响!

重现问题

将Firebug(或Chrome的开发工具)显示的源与通过右键单击并选择“显示页面源”(或在浏览器中调用的名称)或curl http://your.example.org在命令行上使用的源进行比较。后期可能不会包含任何<tbody/>元素(很少使用),Firebug将始终显示它们。

解决方案1:删除/tbody轴步

检查您所停留的表是否确实不包含<tbody/>元素(请参阅最后一段)。如果是这样,您可能还会遇到另一种问题。

现在删除/tbody轴步,这样您的查询将类似于

//table[@id="example"]/tr[2]/td[1]

解决方案2:跳过<tbody/>标签

这是一个很脏的解决方案,对于嵌套表可能会失败(可以跳入内部表)。我只会在极少数情况下建议这样做。

/tbody后代或自身步骤替换轴步骤:

//table[@id="example"]//tr[2]/td[1]

解决方案3:允许输入带<tbody/>标签和不带标签

如果您不确定事先确定您的表或在“HTML源”和DOM上下文中都使用查询,请执行以下操作:并且不希望/不能使用解决方案2中的技巧,请提供替代查询(针对XPath1.0)或使用“可选的”轴步(XPath 2.0及更高版本)。

  • XPath 1.0
    //table[@id="example"]/tr[2]/td[1] | //table[@id="example"]/tbody/tr[2]/td[1]

  • XPath 2.0//table[@id="example"]/(tbody, .)/tr[2]/td[1]



 类似资料:
  • 问题内容: 这旨在对每周出现一次或两次的所有类似问题(但过于具体的问题,不能成为接近的目标候选人)提供规范的问答。 我正在开发一个应用程序,该应用程序需要解析带有表的网站。由于派生用于抓取网页的XPath表达式很无聊且容易出错,因此我想为此使用 Firebug 的XPath提取器功能 (或其他浏览器中的类似工具)。 输入示例如下所示: 我想提取第一个数据单元格(“ foobar”)。Firebug

  • 我想知道为什么我的Java程序在控制台工作,当我做: javac Main.java Java美因河 ...而不是在Eclipse中,因为我有这个错误: 线程“main”java.lang.NullPointerException在codepin.main.main(main.java:48)-->char passwordarray[]=console.readpassword(“enter p

  • 在我的项目中,电影和演员、电影和类别之间有着多对多的关系。当我尝试创建一部电影,然后尝试使用Select2添加演员和类别时,它不会列出可用的选项(输入字段看起来是灰色的,好像它们被锁定了)。我查看脚本是否正在加载,它们是否正在加载。这是我的密码。

  • 问题是,我试图使用findViewById()全局初始化TextView对象,但它在运行时抛出一个错误,然后,如果我在onCreate()或任何其他方法中使用它,初始化工作就会很好。 我正在为API级别22及以上开发

  • 我有一个主活动MainActivity,它是我的android应用程序的入口点。它通过发射器正确发射。然而,当我尝试执行startActivity时,我看到活动试图启动的一些调试,一些代码正确启动,但MainActivity从未启动。 我认为这可能与意图有关: 对吗? 从内部活动来看,我有 我甚至看到 10-11 22:23:46.026:INFO/ActivityManager(472):从pi

  • 我试图隐藏Actionbar并改用工具栏,但如果我更改Theme.appcompat.light.NoActionBar,它确实会隐藏,但应用程序在行setContentView(r.layout.activity_main)处崩溃; 尽管它确实使用getSupportActionBar()隐藏。hide();但我不能用这个代码 Toolbar Toolbar=(Toolbar)findViewB