【问题标题】:Get xpath for nodes that form a string in HTML document获取在 HTML 文档中形成字符串的节点的 xpath
【发布时间】:2015-06-29 05:50:24
【问题描述】:

问题:我想在 HTML 文档中找到构成文本字符串的节点的 xpath。使用的语言是python(lxml来解析文档)

为了说明这个想法,请考虑文档:

<HTML>

<HEAD>
  <TITLE>sample document</TITLE>
</HEAD>

<BODY BGCOLOR="FFFFFF">
  <HR>
  <a href="http://google.com">Goog</a>
  <H1>This is one header</H1>
  <H2>This is a another Header</H2>
  <P>Travel from
    <P>
      <B>SFO to JFK</B>
      <BR>
      <B><I>on May 2, 2015 at 2:00 pm. For details go to confirm.com </I></B>
      <HR>
      <div style="color:#0000FF">
        <h3>Traveler <b> name </b> is
        <p> John Doe </p>
      </div>
.....

现在,给定字符串“SFO to JFK on May 2, 2015”和“Traveler name is John Doe”,我如何获取构成该字符串的节点集中第一个节点的 Xpath。 (如果这很困难,即使是一组节点也可以)

示例输出:

"SFO to JFK on May 2, 2015" -> /html/body/p/p/b
"Traveler name is John Doe" -> /html/body/p/p/div/h3

作为后续,如果我们有一个正则表达式,而不是上面的字符串,解决问题的方法是什么?

注意:在 python 实现方面,我正在处理下面的 sn-p 中的问题

import lxml.html as lh
from StringIO import StringIO
from lxml import etree

elem_tree = lh.parse(StringIO(html_document))
xpath = etree.XPath(_the_xpath_here)
list_of_nodes = xpath(elem_tree)

【问题讨论】:

  • xpath 不会只是“//B”,因为这是您要搜索的唯一 html 元素,它应该为您提供页面上所有 B 元素的数组。您也可以使用 $x("xpath"); 在 chrome 控制台中运行 xpaths
  • 好吧,对不起,我应该澄清一下。文件不固定。正如问题应该是,如果我有任何 HTML 和一组字符串,我将如何获得 xpath?

标签: python html regex xml xpath


【解决方案1】:

你可以试试这个方法:

import lxml.html as lh
from lxml import etree

elem_tree = lh.parse("Q12.html")
input_string = ["SFO to JFK on May 2, 2015", "Traveler name is John Doe"]

for i in input_string:
    xpath = "//*[contains(normalize-space(.), '{0}') and not(.//*[contains(normalize-space(.), '{0}')])]/*"
    node = elem_tree.xpath(xpath.format(i))[0]

    print '{0} -> {1}'.format(i, elem_tree.getpath(node))

    #Output:
    #SFO to JFK on May 2, 2015 -> /html/body/p[2]/b[1]
    #Traveler name is John Doe -> /html/body/div/h3

简要说明:

  • contains(normalize-space(.), '{0}'):过滤包含文本的节点input_string之一)

  • not(.//*[contains(normalize-space(.), '{0}')]) :如果它的任何后代不包含文本,则选择该节点。换句话说,选择包含文本的最里面的节点。

  • getpath():“返回一个结构化的、绝对的 XPath 表达式来查找元素。

更新:

xpath 变量字符串中的尾随/* 替换为:

/descendant-or-self::*[contains('{0}', text()) or contains(text(), '{0}')]

适用于有问题的 HTML 结构以及您在下面的评论中链接的结构。但是,解决具有两个示例 HTML 所展示的不同特征的一般情况超出了此答案中 xpath 查询的范围。

【讨论】:

  • 很好的答案和解释,但它不适用于我的所有字符串。 (例如,gist.github.com/anonymous/3d4b059464773ebd2d2f 的 html 和我试图查找路径的字符串是“电话:1-213-484-7000”,但上面的“xpath”未能找到相同的任何节点)。
  • @Ark 检查 UPDATE 部分,这也适用于您链接的要点中的 HTML。但是,我并不是要解决您提出的全部要求。似乎太多了:p
  • 感谢您的更新!是的,通用解决方案会很困难,因为可能存在微妙的情况。但是,我认为您的回答提供了一个很好的起点。 :)
猜你喜欢
  • 1970-01-01
  • 2016-01-09
  • 1970-01-01
  • 2011-07-08
  • 1970-01-01
  • 1970-01-01
  • 2011-08-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多