通过 xpath 查找元素 - lxml 和 Selenium 导致相同表达式的不同输出

Finding an element by xpath - lxml and Selenium result in different outputs for the same expression

这是关于 lxml 和 Selenium 处理 xpath 表达式的不同方式的几个问题中的第一个。 (虽然有点相似,但我相信,)。

所以让我们从更简单的问题开始。

这是字符串:

my_str = """
<div class="container">

   <div class="24">
        <div class="25">forget me</div>
        <div class="26">a target </div>
   </div>
    <div class="27">very desired
        <div class="28">whatever</div>
        <div class="29">another target</div>
    </div>
    <div class="30">go home
         <div class="31">Nothing here</div>
         <div class="32">somewhat desired</div>
    </div>
 </div>
"""

这是 xpath 表达式:

simple_expression = "//*[contains(text(), 'target')]"

现在让我们看看 lxml 是如何处理的:

import lxml.html
root = lxml.html.fromstring(my_str)

e = root.xpath(simple_expression)
for entry in e:
    print(entry.text)

这会产生所需的输出:

a target

another target

转到硒:

from selenium.webdriver import Chrome
driver = Chrome()
driver.get("data:text/html;charset=utf-8,{html_content}".format(html_content=my_str))

e2 = driver.find_element_by_xpath(simple_expression)
print(e2.text)

这次的输出只有

a target

所以 - 首先,为什么会这样?二、如何让Selenium generae的输出相同?

这是因为您使用了 find_element_by_xpath,它会 return 找到单个元素和第一个项目。

您需要使用driver.find_elements_by_xpath获取所有元素。

driver.find_elements_by_xpath(simple_expression)

这是您的完整代码。

from selenium.webdriver import Chrome
my_str = """
<div class="container">

   <div class="24">
        <div class="25">forget me</div>
        <div class="26">a target </div>
   </div>
    <div class="27">very desired
        <div class="28">whatever</div>
        <div class="29">another target</div>
    </div>
    <div class="30">go home
         <div class="31">Nothing here</div>
         <div class="32">somewhat desired</div>
    </div>
 </div>
"""

simple_expression = "//*[contains(text(), 'target')]"
driver = Chrome()
driver.get("data:text/html;charset=utf-8,{html_content}".format(html_content=my_str))

e2 = driver.find_elements_by_xpath(simple_expression)
for e in e2:
 print(e.text)

输出:

a target
another target

在 lxml 的情况下,您将获得一个节点列表并遍历它们。

e = root.xpath(simple_expression)
for entry in e:
    print(entry.text)

在 selenium 中,您使用的是 find_element,它将 return 第一个匹配元素。这就是为什么你只得到一个节点。尝试将其更改为 find_elements 并按照您在 lxml 中所做的相同方式进行迭代。

示例代码:

e2 = driver.find_elements_by_xpath(simple_expression)
for e in e2:
 print(e.text)