【问题标题】:Finding an element by xpath - lxml and Selenium result in different outputs for the same expression通过 xpath 查找元素 - lxml 和 Selenium 导致相同表达式的不同输出
【发布时间】:2019-10-21 22:24:45
【问题描述】:

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

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

这是字符串:

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)

这会产生所需的输出:

一个目标

另一个目标

转到 Selenium:

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)

这次的输出只有

一个目标

那么 - 首先,为什么会这样?第二,如何使 Selenium 产生相同的输出?

【问题讨论】:

    标签: selenium xpath lxml


    【解决方案1】:

    这是因为您使用了find_element_by_xpath,它将返回单个元素和找到的第一个项目。

    你需要使用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
    

    【讨论】:

    • 哇!那就是问题所在?在这里,我在想我偶然发现了一个深刻的结构性问题,这完全是因为s 被丢弃了!我一定(要)失明了......谢谢!
    【解决方案2】:

    在 lxml 案例中,您将获取节点列表并遍历它们。

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

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

    示例代码:

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

    【讨论】:

      猜你喜欢
      • 2015-02-03
      • 2020-08-08
      • 1970-01-01
      • 2016-03-12
      • 1970-01-01
      • 1970-01-01
      • 2016-04-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多