Python 3.x XPath找到的结果数不正确

Python 3.x XPath找到的结果数不正确,python-3.x,loops,xpath,lxml,urllib,Python 3.x,Loops,Xpath,Lxml,Urllib,事实上,情况要复杂一点 我试图从以下示例html中获取数据: <li itemprop="itemListElement"> <h4> <a href="/one" title="page one">one</a> </h4> </li> <li itemprop="itemListElement"> <h4> <a href="/two

事实上,情况要复杂一点

我试图从以下示例html中获取数据:

<li itemprop="itemListElement">
    <h4>
        <a href="/one" title="page one">one</a>
    </h4>
</li>

<li itemprop="itemListElement">
    <h4>
        <a href="/two" title="page two">two</a>
    </h4>
</li>

<li itemprop="itemListElement">
    <h4>
        <a href="/three" title="page three">three</a>
    </h4>
</li>

<li itemprop="itemListElement">
    <h4>
        <a href="/four" title="page four">four</a>
    </h4>
</li>
如您所见,第一步是提取4个
li
元素并将它们附加到列表中,然后扫描每个
li
元素以查找
a
元素,但问题是
scan
中的每个
li
元素实际上都是这四个元素

……或者我是这么想的

通过快速调试,我发现
scan
列表正确地包含了四个
li
元素,因此我得出了一个可能的结论:上面提到的
for
循环有问题

for list_item in scan:
    # This is supposed to print '1' since there's only one match
    # Yet, this actually prints '4' (This is wrong)
    print(len(list_item.xpath("//h4/a")))

    # Something is wrong here...
唯一真正的问题是我不能准确地找出错误。是什么原因造成的

PS:我知道,有一种更简单的方法可以从列表中获取
a
元素,但这只是一个示例html,真正的html包含更多。。。事情

print(len(list_item.xpath(".//h4/a")))
/
表示
/后代或self::node()
它以
/
开头,因此它将从文档的根节点进行搜索


使用
指出当前上下文节点是
列表项
,而不是整个文档

在您的示例中,当XPath以
/
开头时,它将从文档的根开始搜索(这就是它匹配所有四个锚元素的原因)。如果要相对于
li
元素进行搜索,则可以省略前面的斜杠:

for item in page.xpath("//li[@itemprop='itemListElement']"):
    scan.append(item)

for list_item in scan:
    print(len(list_item.xpath("h4/a")))
当然,您也可以将
//
替换为
/
,以便搜索也是相对的:

for item in page.xpath("//li[@itemprop='itemListElement']"):
    scan.append(item)

for list_item in scan:
    print(len(list_item.xpath(".//h4/a")))
以下是规范中的相关引用:

/
/genderant或self::node()/
的缩写。例如,
//para
/genderant或self::node()/child::para
的缩写,因此将选择文档中的任何
para
元素(即使是作为文档元素的
para
元素也将由
//para
选择,因为文档元素节点是根节点的子节点)
div//para
div/genderant或self::node()/child::para
的缩写,因此将选择div子代的所有
para
子代


/
解决了问题,谢谢您的回答。但为什么会这样呢?首先,我们加载一个页面并获取其html,然后提取
li
标记并将每个标记放入列表中。为什么使用
/
会有所不同?由于在第二个
for
循环中,我们迭代了
li
标记中的每一个,因此应该只有一个
h4
,因此
a
标记。编辑:是不是即使在提取了
li
标记之后,我们仍然拥有整个html?这可能是真正的罪魁祸首。@Eekan-正确,即使提取了
li
标记,XPath查询仍然可以访问整个HTML。在您的示例中,
list\u item
是对
li
元素的引用。我认为这样做的原因是XPath允许遍历树并选择父元素。这意味着
li
必须是一个引用,这样树上的其他元素仍然可以用于更复杂的查询。谢谢,伙计。我想我更好地掌握了XPath。
for item in page.xpath("//li[@itemprop='itemListElement']"):
    scan.append(item)

for list_item in scan:
    print(len(list_item.xpath(".//h4/a")))