Selenium 如何使用';通过xpath查找元素;在for循环中
我对以下几点有些(或非常)困惑:Selenium 如何使用';通过xpath查找元素;在for循环中,selenium,xpath,beautifulsoup,Selenium,Xpath,Beautifulsoup,我对以下几点有些(或非常)困惑: from selenium.webdriver import Chrome driver = Chrome() html_content = """ <html> <head></head> <body> <div class='first'> Text 1 </div> <div c
from selenium.webdriver import Chrome
driver = Chrome()
html_content = """
<html>
<head></head>
<body>
<div class='first'>
Text 1
</div>
<div class="second">
Text 2
<span class='third'> Text 3
</span>
</div>
<div class='first'>
Text 4
</div>
<my_tag class="second">
Text 5
<span class='third'> Text 6
</span>
</my_tag>
</body>
</html>
"""
driver.get("data:text/html;charset=utf-8,{html_content}".format(html_content=html_content))
我可以这样得到span
的文本:
el = driver.find_elements_by_xpath("*//span")
for i in el:
print(i.text)
其输出为:
Text 3
Text 6
但是,当我尝试使用以下命令获取父级(并且仅获取父级)文本时:
elp = driver.find_elements_by_xpath("*//span/..")
for i in elp:
print(i.text)
输出为:
Text 2 Text 3
Text 5 Text 6
xpath表达式*//span/.
和//span/./text()
通常(但并非总是,取决于使用的xpath测试站点)计算结果为:
Text 2
Text 5
这就是我的for
循环所需要的
因此产生了混乱。所以我想我要找的是一个for
循环,它在伪代码中看起来像:
el = driver.find_elements_by_xpath("*//span")
for i in el:
print(i.text)
print(i.parent.text) #trying this in real life raises an error....
i、 text将不起作用,在java中我曾经写过类似这样的东西
ele.get(i).findElement("here path to parent may be parent::div ").getText();
可能有几种方法可以做到这一点。这里有一条路
elp = driver.find_elements_by_css_selector("span.third")
for i in elp:
print(i.text)
s = i.find_element_by_xpath("./..").get_attribute("innerHTML")
print(s.split('<')[0].strip())
下面是将仅从父节点检索文本的python方法
def get_text_exclude_children(element):
return driver.execute_script(
"""
var parent = arguments[0];
var child = parent.firstChild;
var textValue = "";
while(child) {
if (child.nodeType === Node.TEXT_NODE)
textValue += child.textContent;
child = child.nextSibling;
}
return textValue;""",
element).strip()
以下是如何在您的案例中使用该方法:
elements = driver.find_elements_by_css_selector("span.third")
for eleNum in range(len(elements)):
print(driver.find_element_by_xpath("(//span[@class='third'])[" + str(eleNum+1) +"]").text)
print(get_text_exclude_children(driver.find_element_by_xpath("(//span[@class='third'])[" + str(eleNum+1) +"]/parent::*")))
以下是输出:
我知道我已经接受了@JeffC的答案,但在研究这个问题的过程中,我发生了一些事情。这很可能是过火了,但这是一个有趣的方法,为了后代,我想我也可以把它贴在这里 这个想法涉及到使用BeautifulSoup。原因是BS有两种从树中删除节点的方法。其中一个在这里很有用(据我所知,Selenium没有相应的方法)是
decompose()
(.我们可以使用decompose())
通过删除标记及其内容,禁止打印父级文本的第二部分,该部分包含在span
标记中。因此,我们导入BS并从@JeffC的答案开始:
from bs4 import BeautifulSoup
elp = driver.find_elements_by_css_selector("span.third")
for i in elp:
print(i.text)
s = i.find_element_by_xpath("./..").get_attribute("innerHTML")
在这里切换到bs4
content = BeautifulSoup(s, 'html.parser')
content.find('span').decompose()
print(content.text)
没有字符串操作、正则表达式之类的输出是…:
Text 3
Text 2
Text 6
Text 5
这个问题是针对python的。Sugest是一个代码转换编辑,selenium适用于几乎每种语言,因此逻辑是相同的,如果答案在任何方面都有用,就不需要对其进行否决。@Valga不,meta上已经详细讨论过了。不要用另一种语言回答问题。如果答案如此简单,回答者应该花费更多的时间是时候将其转换为所需的语言了。@JeffC Selenium支持52种语言绑定。用52种语言存储每一个问题都会浪费空间、时间和多余的精力。正如Valga提到的,底层逻辑很重要。但是没有关于这一点的规范性元讨论。请停止捏造东西你自己做,不要误导新的贡献者。@DebanjanB还说,支持的语言只有6种。有些语言有不止一个框架,但只有6种语言。我不知道你从哪里得到了52种。即使你把所有的框架都算进去,也只有14种。这看起来很有希望,但似乎“向上导航”“一个级别”不起作用,因为输出与elp=driver完全相同。通过\u xpath(“*//span/”)查找\u元素
问题中的陈述:文本3,文本2,文本3,文本6,文本5,文本6
。我们需要找到一种方法来禁止打印的文本的第二部分。
。是的。你是对的。我忘了父元素也包含子元素。你有什么原因不想抓取父元素并拆分子元素吗e 2由newline完成?这会容易得多。当然,我们可以在这里进行字符串操作,但到现在(考虑到我给出的所有问题),这已成为一个原则问题(事实上)为了找到一个更有机的方法来实现这一点,如果存在的话。我修复了答案。尝试一下。我解析了父对象的innerHTML以分离出子对象。我在本地对其进行了测试,但您需要在实际系统上对其进行测试以确保其正常工作。好的,它确实有效!谢谢。我刚刚想到-有没有方法使用unwrap()
到达那里?有趣的方法,但是返回self.driver.execute\u script
引发的NameError:name'self'没有定义
。我的错,忘了删除self
。更新了答案,只删除了self。所以你现在应该可以很好地执行该方法了。现在我遇到了这个奇怪的错误(以前从未见过):StaleElementReferenceException:Message:stale element reference:element未附加到页面文档
。我刷新了所有内容并重试,但错误依然存在。嗯,更新了代码以使用索引而不是元素来指向父级。希望您能很好地进行此更改:-)至少这次的错误更容易识别:)NoSuchElementException:Message:没有这样的元素:无法定位元素:{“方法”:“xpath”,“选择器”:“(//span[@class='third']]][0]”}
。用于正确作业的正确工具。。。很多时候,不止一种工具可用。有时知道使用哪一个是最难弄清楚的。
content = BeautifulSoup(s, 'html.parser')
content.find('span').decompose()
print(content.text)
Text 3
Text 2
Text 6
Text 5