当前位置: 首页 > 知识库问答 >
问题:

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

唐高朗
2023-03-14

这是为了提供一个规范的Q

我正在开发一个应用程序,需要解析一个网站中的表。由于导出用于抓取网页的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测试插件中都可以正常工作,但在我自己的应用程序中却不行(没有找到结果)。如果我将查询缩减到//table[@id],它会再次工作。

出什么问题了?

共有2个答案

东方嘉木
2023-03-14

只是遇到了同样的问题。我几乎编写了一个递归函数来检查每个tbody标记是否存在,并以这种方式遍历dom,然后我记得我知道regex:)

在解析之前,将html作为字符串获取。插入缺少的

延斯·埃拉特给出了一个很好的解释,但是这里是

JavaScript
    var html = '<html><table><tr><td>foo</td><td>bar</td></tr></table></html>';
    html.replace(/(<table([^>]+)?>([^<>]+)?)(?!<tbody([^>]+)?>)/g,"$1<tbody>").replace(/(<(?!(\/tbody))([^>]+)?>)(<\/table([^>]+)?>)/g,"$1</tbody>$4");

PHP
    $html = $dom->saveHTML();
    $html = preg_replace(array('/(<table([^>]+)?>([^<>]+)?)(?!<tbody([^>]+)?>)/','/(<(?!(\/tbody))([^>]+)?>)(<\/table([^>]+)?>)/'),array('$1<tbody>','$1</tbody>$4'),$html);
    $dom->loadHTML($html);

只有正则表达式:

matches `<table>` tag with whatever else junk inside the tag and between this and the next tag if the next tag is NOT `<tbody>` also with stuff inside the tag

    /(<table([^>]+)?>([^<>]+)?)(?!<tbody([^>]+)?>)/

replace with

    $1<tbody>

the $1 referencing the captured `<table>` tag with contents.
Do the same for the closing tag like this:

    /(<(?!(\/tbody))([^>]+)?>)(<\/table([^>]+)?>)/

replace with

    $1</tbody>$4

这样,dom将始终具有

班安平
2023-03-14

Firebug是Chrome的开发工具,JavaScript中的XPath函数和其他函数在DOM上工作,而不是基本的HTML源代码。

超文本标记语言的DOM要求所有表行不包含在页脚(

tbody元素对于所有表都是公开的,即使该表没有明确定义tbody元素。

关于stackoverflow的另一个答案中有一个深入的解释。

另一方面,超文本标记语言不一定需要使用该标记:

除非桌子只包含一个桌子主体且没有桌子头或脚部分,否则始终需要t桌子主体开始标签。

除了JavaScript之外,大多数XPath处理器都处理原始XML,而不是DOM,因此不会添加

这是在Stackoverflow上发布的PHP、Ruby、Python、Java、C#、GoogleDocs(电子表格)和其他许多应用程序的常见问题。Selenium在浏览器内部运行,在DOM上工作——因此它不受影响!

将Firebug(或Chrome的开发工具)显示的源代码与通过右键单击并选择“显示页面源代码”(或浏览器中的任何名称)或使用curl获得的源代码进行比较http://your.example.org在命令行上。后者可能不包含任何

检查你卡住的表是否真的不包含

现在删除/tbody轴步骤,这样您的查询将看起来像

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

这是一个相当脏的解决方案,对于嵌套表可能会失败(可以跳转到内部表)。我只会在非常罕见的情况下建议这样做。

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

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

如果您事先不确定您的表或查询是否同时在“HTML源代码”和DOM上下文中使用;并且不想/不能使用解决方案2中的hack,提供一个替代查询(针对XPath 1.0)或使用“可选”axis步骤(XPath 2.0及更高版本)。

  • XPath 1.0:
    //表[@id=“example”]/tr[2]/td[1]|//表[@id=“example”]/tbody/tr[2]/td[1]
  • XPath 2.0://表[@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