我已经解决了很长一段时间,并尝试了所有类型的命名空间解决方案。但是,我当前的脚本不打印所需的字符串,而是整个html转储。有谁知道如何解决这个问题?
from lxml.html import parse
from lxml import etree
import requests
r = requests.get('https://berlin.kauperts.de/Strassen/Aachener-Strasse-10713-Berlin.html')
tree = etree.parse(r.text)
NSMAP = {'mw':'http://www.w3.org/1999/xhtml/'}
Name2 = tree.xpath('//{http://www.w3.org/1999/xhtml}html/body/div[7]/div/div/div/table/tbody/tr/td[2]/a')
Name3 = tree.find("//html/body/div[7]/div/div/div/table/tbody/tr/td[2]/a")
print(Name2, Name3)
答案 0 :(得分:1)
命名空间是继承的。如果文档是XHTML,则默认情况下文档中的所有节点都在XHTML命名空间中。
这意味着您必须在XPath表达式的每个步骤中使用该命名空间。在第一步(html
)上使用它是不够的。
nsmap
可以帮助您保持代码的可管理性,但您也必须使用它。
from lxml.html import parse
import requests
from lxml import etree
r = requests.get('https://berlin.kauperts.de/Strassen/Aachener-Strasse-10713-Berlin.html')
tree = etree.parse(r.text)
nsmap = {'x':'http://www.w3.org/1999/xhtml/'}
path = '//x:body/x:div[7]/x:div/x:div/x:div/x:table/x:tbody/x:tr/x:td[2]/x:a'
name = tree.findall(path, nsmap)
以上是笨重而脆弱的。尝试创建一个更简单的表达式。
规则:永远不要使用自动生成的XPath。手动创建"最不具体的"表达式(即最少依赖于不相关的文档结构,如div
嵌套级别或位置),它们仍然与您需要的完全匹配。也许就是这样。
name = tree.findall('//x:table[@class="foo"]//x:td[2]/x:a', nsmap)