Python中使用lxml分析HTML时,如何正确应用XPath语法解决问题?

有如下代码:
(随便写的,不要在乎 script 节点的意义,做位置参照而已)

import lxml.html
import lxml.etree

text = ‘’’ <html> <body> <div> <p>我不是你需要的文本</p> </div> <div> <script type=“text/javascript”> console.log(“Hello world”) </script> <p>我是你需要的文本</p> </div> </body> </html> ‘’’

doc = lxml.html.fromstring(text) body = doc.xpath("/html/body")[0] divs = body.xpath(“div”) for div in divs: scripts = div.xpath(“script[@type=“text/javascript”]”) if scripts is not None: ps = div.xpath(“p”) p = ps[0] print(p.text)

本意是通过 scripts is not None 匹配到第二个 div 节点,但意外的是两个 div 均匹配成功
如果输出 scripts,还都会得到 script 节点


Python中使用lxml分析HTML时,如何正确应用XPath语法解决问题?

9 回复

script 前面加个./


用lxml配合XPath解析HTML,核心就两点:正确构造解析器和写准XPath表达式。

首先确保安装lxml:pip install lxml。解析时建议用html.fromstring(),它能自动修正残缺标签,比etree.parse()处理网页源码更稳。

from lxml import html

# 假设这是你要解析的HTML
html_content = """
<html>
<body>
<div class="content">
    <ul id="list">
        <li class="item">第一项</li>
        <li class="item">第二项</li>
        <li class="item">第三项</li>
    </ul>
    <a href="/next">链接</a>
</div>
</body>
</html>
"""

# 解析HTML
tree = html.fromstring(html_content)

# 示例1:获取所有li的文本
items = tree.xpath('//li[@class="item"]/text()')
print("所有项目:", items)  # 输出: ['第一项', '第二项', '第三项']

# 示例2:获取特定属性
link = tree.xpath('//a/@href')[0]
print("链接地址:", link)  # 输出: /next

# 示例3:结合条件查找
second_item = tree.xpath('//ul[@id="list"]/li[2]/text()')[0]
print("第二项:", second_item)  # 输出: 第二项

几个关键点:

  1. // 表示从任意深度查找节点,/ 表示直接子节点。
  2. @ 用来取属性,比如 @href@class
  3. 谓语(方括号)用于过滤,li[1] 是第一个li(XPath下标从1开始),[@class="item"] 是属性匹配。
  4. text()获取节点文本,@attr获取属性值。

浏览器开发者工具可以直接复制XPath,但通常需要微调。遇到复杂结构时,可以先用 tree.xpath('//some-tag') 看看返回的节点列表,再逐步细化路径。

总结:多练常用路径写法,用浏览器工具辅助定位。

[] != None

所以两个 p 都被选取到了

可以试试 xpath helper 插件


多谢
忘了 not found 返回的是[]
有个方法 not found 返回 None,结果记混淆了


谢谢两位
最终代码:
<br>if td.xpath(".//script[type=\"text/javascript\"]"):<br> pass<br>

把最外面两个双引号改成单引号,可以不用写转义符号了

习惯了

回到顶部