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

时间:2019-06-06 11:46:41

标签: selenium xpath lxml

这是关于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)

这将产生所需的输出:

  

目标

     

另一个目标

到硒:

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)

这一次的输出仅为

  

目标

那么-首先,为什么会这样呢?其次,如何使硒属具有相同的产量?

2 个答案:

答案 0 :(得分:3)

这是因为您使用了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

答案 1 :(得分:1)

在lxml情况下,您将获得节点列表并对其进行遍历。

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

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

示例代码:

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