XPath在lxml etree元素上执行返回意外结果的问题排查
问题原因与解决方案:XPath在节点上使用//的误区
嘿,我一眼就看出问题出在哪了——你用的XPath语法//title其实不是从当前<item>节点开始搜索的!
核心原因
XPath里的//是从整个XML文档的根节点开始匹配所有后代节点,不管你是在哪个子节点上调用这个表达式。所以当你在first_item上执行//title时,它会遍历整个XML,第一个找到的就是<channel>标签下的那个标题,自然不符合你的预期。
解决方法
要在当前节点的范围内搜索,你需要用以下两种写法之一:
.//title:从当前节点开始,匹配所有后代里的<title>元素(适合title可能嵌套在子节点里的情况)./title或者直接写title:匹配当前节点的直接子节点里的<title>(因为你的<title>是<item>的直接子节点,这种写法更简洁)
修改后的代码如下:
from urllib.request import urlopen from lxml import etree url = 'https://www.sec.gov/Archives/edgar/monthly/xbrlrss-2018-02.xml' data = urlopen(url) xml = data.read() parser = etree.XMLParser(remove_blank_text=True, huge_tree=True) root = etree.XML(xml, parser=parser) items = root.xpath("//item") first_item = items[0] # 写法1:匹配当前节点下所有后代title title = first_item.xpath(".//title")[0].text # 写法2:匹配当前节点的直接子节点title(更适合你的场景) # title = first_item.xpath("title")[0].text print(title) # 现在会输出'DST SYSTEMS INC (0000714603) (Filer)'
额外验证小技巧
你可以打印两个表达式的结果长度,就能直观看到差异:
print(len(first_item.xpath("//title"))) # 会返回所有title的数量(包括channel和所有item的) print(len(first_item.xpath(".//title"))) # 只返回当前item下的title数量(这里是1)
内容的提问来源于stack exchange,提问作者PiperWarrior
相关产品推荐
相关产品推荐

