Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么我的XPath查询(抓取HTML表)只在Firebug中工作,而在应用程序I';我在发展?_Html_Dom_Xpath_Firebug_Google Chrome Devtools_Tag Soup_Htmltidy - Fatal编程技术网

为什么我的XPath查询(抓取HTML表)只在Firebug中工作,而在应用程序I';我在发展?

为什么我的XPath查询(抓取HTML表)只在Firebug中工作,而在应用程序I';我在发展?,html,dom,xpath,firebug,google-chrome-devtools,tag-soup,htmltidy,Html,Dom,Xpath,Firebug,Google Chrome Devtools,Tag Soup,Htmltidy,这意味着为每周出现一到两次的所有类似问题(但太过具体的问题,无法成为接近目标的候选人)提供一个规范的问答 我正在开发一个应用程序,需要解析一个包含表的网站。由于导出用于抓取网页的XPath表达式既枯燥又容易出错,因此我想使用Firebug的XPath提取器功能(或其他浏览器中的类似工具)来实现这一点 示例输入如下所示: 示例单元 另一个 福巴 42 我想提取第一个数据单元(“foobar”)。Firebug提出了XPath表达式 //表[@id=“example”]/tbody/tr[2]/

这意味着为每周出现一到两次的所有类似问题(但太过具体的问题,无法成为接近目标的候选人)提供一个规范的问答

我正在开发一个应用程序,需要解析一个包含表的网站。由于导出用于抓取网页的XPath表达式既枯燥又容易出错,因此我想使用Firebug的XPath提取器功能(或其他浏览器中的类似工具)来实现这一点

示例输入如下所示:


示例单元
另一个
福巴
42
我想提取第一个数据单元(“foobar”)。Firebug提出了XPath表达式

//表[@id=“example”]/tbody/tr[2]/td[1]
哪个可以在任何XPath测试插件中正常工作,但不是我自己的应用程序(没有找到结果)。如果我将查询缩减到
//table[@id]
,它会再次工作

出了什么问题?

问题:DOM需要
标记 Firebug、Chrome的开发工具、JavaScript中的XPath函数和其他函数在DOM上工作,而不是基本的HTML源代码

DOM for HTML要求页脚(
)的表头中不包含的所有表行都包含在表体标记中。因此,如果在解析(X)HTML时缺少该标记,浏览器会添加该标记。例如,他说

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

有一个问题

另一方面:

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

大多数XPath处理器处理原始XML 除了JavaScript,大多数XPath处理器都处理原始XML,而不是DOM,因此不添加
标记。HTML解析器库也喜欢并只输出XHTML,而不是“DOM-HTML”

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

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


解决方案1:拆下
/t车斗
轴台阶
检查您所停留的表是否真的不包含
元素(参见最后一段)。如果是的话,你可能会遇到另一种问题

现在删除
/tbody
轴步骤,这样您的查询将如下所示

//表[@id=“example”]/tr[2]/td[1]
解决方案2:跳过
标记 这是一个相当脏的解决方案,对于嵌套表来说可能会失败(可以跳转到内部表)。我只建议在极少数情况下这样做

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

//表[@id=“example”]//tr[2]/td[1]
解决方案3:允许带和不带
标记的输入 如果您事先不确定您的表或查询是否同时在“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]
  • XPath2.0
    //表[@id=“example”]/(tbody,)/tr[2]/td[1]

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

      在解析之前,将html作为字符串获取。用regex插入缺少的
      标记,然后将其加载回DOMDocument对象

      Jens Erat给出了一个很好的解释,但这里是

      解决方案4:确保HTML源代码始终具有带有regex的
      标记
      JavaScript
      var html='foobar';
      替换(/(]+)?>([^]+)(!]+)?>)/g,“$1”)。替换(/(]+)?>)(]+)?>)/g,“$1$4”);
      PHP
      $html=$dom->saveHTML();
      $html=preg_replace(数组('/(]+)?>([^]+)?)(?!]+)?>)/','/(]+)?>)(]+)?>)/'),数组('$1','$1$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
      
      将``标记与标记内的任何其他垃圾匹配,如果下一个标记不是``则将此标记与下一个标记之间的垃圾匹配,并将其与标记内的内容匹配
      /(]+)?>([^]+)?)(?!]+)?>)/
      取代
      $1
      $1引用捕获的带有内容的``标记。
      对结束标记执行相同的操作,如下所示:
      /(]+)?>)(]+)?>)/
      取代
      $1$4
      

      这样,dom将始终在必要时具有
      标记。

      也许值得一提的是,在
      标记中测试这些xpath查询不是一个好主意,这些标记插入
      后面,因为它将失败(元素还没有出现)。今天,我还进行了一些讨论,因为这不是表,而是与浏览器Xpath相关的:Firefox似乎接受大写元素和属性名。DOMDocument xpath需要那些小写字母(不是这个参考问题中的问题,但我想把它交叉连接起来,因为我第一次看到它,这是一个伟大的倡议!)。除了上面所说的,对于这些场景,我的刮板,我有一个“skipFirstRow”的标志,它实际上非常有效(对于我正在刮板的页面).我已经搜索了4个小时的解决方案,因为我想从一个站点获取数据
      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