在元素和属性中搜索字符串

Search both elements and attributes for string

我正在尝试查询一些 HTML 以查找以某种方式包含单词 "download" 的链接。所以可以在

  1. id
  2. class
  3. href
  4. 正文
  5. a 标签内的任何 html。

所以使用 Python lxml library 它应该找到测试中的所有 7 个链接-html:

html = """
<html>
<head></head>
<body>
1 <a href="/test1" id="download">test 1</a>
2 <a href="/test2" class="download">test 2</a>
3 <a href="/download">test 3</a>
4 <a href="/test4">DoWnLoAd</a>
5 <a href="/test5">ascascDoWnLoAdsacsa</a>
6 <a href="/test6"><div id="test6">download</div></a>
7 <a href="/test7"><div id="download">test7</div></a>
</body>
</html>
"""

from lxml import etree

tree = etree.fromstring(html, etree.HTMLParser())
downloadElementConditions = "//a[(@id|@class|@href|text())[contains(translate(.,'DOWNLOAD','download'), 'download')]]"
elements = tree.xpath(downloadElementConditions)

print 'FOUND ELEMENTS:', len(elements)
for i in elements:
    print i.get('href'), i.text

但是,如果这是 运行,它只会找到前五个元素。这意味着如果文本不包含进一步的 html,则 xpath 只能在文本中找到 "download"。

有没有办法将 a 标记的内容视为常规字符串,并查看其中是否包含 "download"?欢迎所有提示!

[编辑]

使用下面 heinst 的回答中的提示,我编辑了下面的代码。这现在有效,但不是很优雅。有人知道纯 xpath 的解决方案吗?

from lxml import etree
tree = etree.fromstring(html, etree.HTMLParser())
downloadElementConditions = "//*[(@id|@class|@href|text())[contains(translate(.,'DOWNLOAD','download'), 'download')]]"
elements = tree.xpath(downloadElementConditions)

print 'FOUND ELEMENTS:', len(elements)
for el in elements:
    href = el.get('href')
    if href:
        print el.get('href'), el.text
    else:
        elparent = el
        for _ in range(10):  # loop over 10 parents
            elparent = elparent.getparent()
            href = elparent.get('href')
            if href:
                print elparent.get('href'), elparent.text
                break

Xpath select 从严格匹配 a 标签更改为通配符应该可以解决问题: "//*[(@id|@class|@href|text())[contains(translate(.,'DOWNLOAD','download'), 'download')]]"

纯 XPath 解决方案

text() 更改为 . 并在 descendent-or-self 轴上搜索属性:

//a[(.|.//@id|.//@class|.//@href)[contains(translate(.,'DOWNLOAD','download'),'download')]]

解释:

  • text() vs .:这里 text() 将匹配 a 的直接文本节点子节点; . 将匹配 a 元素的字符串值。在 为了捕获 a 的子元素的情况 包含目标文本,你想匹配的字符串值 a.
  • descendant-or-self:为了匹配 a 及其任何后代的属性,descendant-or-self 轴(.//) 被使用。

有关 XPath 中字符串值的更多详细信息,请参阅