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