【问题标题】:lxml.html parsing with XPath and variables使用 XPath 和变量解析 lxml.html
【发布时间】:2013-04-23 13:01:09
【问题描述】:

我有这个 HTML sn-p

<div id="dw__toc">
<h3 class="toggle">Table of Contents</h3>
<div>

<ul class="toc">
<li class="level1"><div class="li"><a href="#section">#</a></div>
<ul class="toc">
<li class="level2"><div class="li"><a href="#link1">One</a></div></li>
<li class="level2"><div class="li"><a href="#link2">Two</a></div></li>
<li class="level2"><div class="li"><a href="#link3">Three</a></div></li>

现在我想用 lxml.html 解析它。最后,我想要一个可以提供搜索项(即“one”)的函数,并且该函数应该返回

One
#link1

现在我正在尝试在 XPath 中获取一个变量。

作品:

import lxml.html
html = lxml.html.parse("www.myurl.com/slash/something")

test=html.xpath("//ul[@class='toc']/li[@class='level2']/div[@class='li']/a/text()='One'")

print test

尝试使用变量。我想将硬编码的'One' 替换为稍后可以返回到函数的变量。

不起作用:

import lxml.html
html = lxml.html.parse("www.myurl.com/slash/something")

desiredvars = ['One']
myresultset=((var, html.xpath("//ul[@class='toc']/li[@class='level2']/div[@class='li']/a[text()='%s']"%(var))[0]) for var in desiredvars)

for each in myresultset: 
        print each

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
IndexError: list index out of range

这是基于这个答案:https://stackoverflow.com/a/10688235/2320453 知道为什么它不起作用吗?这是做这样的事情的“正确方法”吗?

编辑: 总结一下: 我想在 a-Tags 中搜索并从此属性中获取文本,但我不想要一个完整的列表,而是希望能够使用变量进行搜索。 伪代码:

import lxml.html
html = lxml.html.parse("www.myurl.com/slash/something")

searchterm = 'one'

test=html.xpath("...a/text()=searchterm")

print test

预期结果

One
#link1

【问题讨论】:

    标签: python html parsing web-scraping lxml


    【解决方案1】:

    你的第一个例子是炒锅,但可能不是你想象的那样:

    test=html.xpath("//ul[@class='toc']/li[@class='level2']/div[@class='li']/a/text()='One'")
    

    返回的是一个布尔值,如果条件 ...='One' 对于 xpath 表达式左侧结果集中的任何节点为真,则该布尔值为真。这就是为什么您在第二个示例中出现错误:True[0] 无效。

    您可能希望所有与表达式匹配的节点,将'One' 作为文本。对应的表达式是:

    test=html.xpath("//ul[@class='toc']/li[@class='level2']/div[@class='li']/a[text()='One']")
    

    这将返回一个节点集作为结果,或者如果您只需要将 url 作为字符串:

    test=html.xpath("//ul[@class='toc']/li[@class='level2']/div[@class='li']/a[text()='One']/@href")
    # returns: ['#link1']
    

    【讨论】:

    • 谢谢!你是对的,我的第一个例子打印了True。您的第一个示例打印 Element at 0xc99b90。如何将其打印One 并用变量替换/a[text()='One'] 中的One?我还编辑了第一篇文章,首先弄乱了一些括号......
    • text() 选择一个文本节点,所以.../a/text() 你会返回所有锚点的所有文本内容的列表,如果这是你需要的,或者你可以使用返回的元素来访问它的属性蟒蛇。
    • 所以最好检索一个包含所有项目的列表,然后从 python 在该列表中搜索,而不是缩小 Xpath 表达式的范围以仅返回我正在搜索的一项?
    • 编辑了我的第一篇文章以澄清。
    • 如果你使用类似".../a[text()=%r]" % searchterm的东西,你会得到一个所有匹配节点的列表,如果你添加/@href你会得到href内容,或者如果你添加/text()你会得到文本内容(这将是非常有意义的,因为它是您正在搜索的术语),总是作为一个列表......最好使用什么取决于您的具体用例。
    【解决方案2】:

    我试过mata的回应,但对我来说没有用:

    div_name = 'foo'
    my_div = x.xpath(".//div[@id=%s]" %div_name)[0]
    

    我在他们的网站http://lxml.de/xpathxslt.html#the-xpath-method 上为可能遇到相同问题的人找到了这个:

    div_name = 'foo'
    my_div = x.xpath(".//div[@id=$name]", name=div_name)[0]
    

    【讨论】:

    • my_div = x.xpath(".//div[@id='%s']"%div_name)[0] 也可以正常工作
    猜你喜欢
    • 2014-03-28
    • 2012-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-09
    • 1970-01-01
    相关资源
    最近更新 更多