Selenium python find_element_by_class_name() 从 v 2.2 到 2.21 停止工作——不能使用“复合类名”

Posted

技术标签:

【中文标题】Selenium python find_element_by_class_name() 从 v 2.2 到 2.21 停止工作——不能使用“复合类名”【英文标题】:Selenium python find_element_by_class_name() stopped working from v 2.2 to 2.21 -- cannot use 'Compound Class Name' 【发布时间】:2012-05-26 09:33:54 【问题描述】:

我正在使用 Selenium 的 python 库从 Firefox 的 html 页面中抓取数据。

我不得不从 Selenium 2.0 更新到 2.21,因为服务器已经更新了 Firefox。

在 v 2.21 中,对 find_element_by_class_name("grid-cell-inner grid-col-name") 的调用失败:

selenium.common.exceptions.WebDriverException: Message: u'Compound class names not permitted'

我试图访问的元素的类名是grid-cell-inner grid-col-name

find_element_by_class_name() 的调用在v 2.2 中有效,所以逻辑是正确的,并且以前可以找到数据。 v 2.21 中发生了一些变化。

所有 Selenium 示例都给出了类名称为 foo 等的简单示例,没有我需要访问的名称类型。

为什么 Selenium 不再支持查找名称为 grid-cell inner grid-col-name 的类,以及他们的解决方案是什么?

有人可以帮我找到具有“复合”类名称的元素吗?

【问题讨论】:

【参考方案1】:

WebDriver 的问题在于它仍在不断发展。很多。我个人不知道有哪个版本支持在一个命令中搜索多个类,所以它一定是一个相当古老的版本:)。

通过CSS selector 搜索应该可以,但是:

find_element_by_css_selector(".grid-cell-inner.grid-col-name");

我不建议将XPath 用于这个特定的东西,因为以下两个表达式是不同的东西:

//*[class='grid-cell-inner grid-col-name']

//*[class='grid-col-name grid-cell-inner']

【讨论】:

不是多类搜索;我无法控制的 html 中的类名中有空格。如果这是一个“复合类名”,那为什么要停止支持它呢?现在我们所有的逻辑都被打破了。 其实,没有。这是两个独立的课程,grid-cell-innergrid-col-name,我对此 100% 持肯定态度。我不知道 Selenium 不支持通过许多类名进行搜索的原因——但我想这就是 CSS 选择器的用途。如果它有效,它一定是某个 alpha 或 beta 版本,因为我在任何更新日志中都找不到任何提及。使用 CSS 选择器解决方案,应该可以。 A quick googling 说:要指定多个类,请用空格分隔类名,例如。这允许您为一个 HTML 元素组合多个 CSS 类。 是的。使用 find_element_by_css_selector() 并按照您的描述指定类名可以正常工作。我只需要更改几行代码即可支持这一点,现在我可以找到元素。非常感谢!【参考方案2】:

您需要使用格式为“.nameA.nameB.nameC”的 CssSelector,您可以拥有任意数量的 CssSelector,只需添加“.”即可

或者,您可以匹配整个属性(您也可以使用 xpath 执行此操作):“[class='exact class name here']” XPath - "//[@class='这里的确切类名']"

有一些方法可以开头或结尾或包含(在 CSS 和 xpath 中),如果类是动态生成。

【讨论】:

不应该是 "//*[@class='exact class name here']" 吗?强调 * 那么,*应该出现还是不出现?【参考方案3】:

我想Selenium 很长时间不支持复合类名了。

不用说,尝试通过 XPath 或 CSS 选择器或通过“grid-cell-inner”类名,然后过滤以查看哪些元素具有“grid-cell-inner grid-col-name”类。

【讨论】:

【参考方案4】:

也可以试试:

elements = bot.execute_script("""return document.getElementsByClassName('grid-cell-inner grid-col-name')""")

【讨论】:

【参考方案5】:

此错误消息...

selenium.common.exceptions.WebDriverException: Message: u'Compound class names not permitted'

...暗示使用Compound class names 的locator strategies 在使用Selenium 时不再有效。

可以从Selenium v2.40.0 changelist 中观察到此更改的痕迹,其中提到了为复合类名称的使用添加正确的错误代码:

针对无效的 css 选择器空类名和原子中的复合类名的情况实施了正确的错误代码。

解决方案

您也可以使用以下任一Locator Strategies:

使用CSS_SELECTOR

driver.find_element(By.CSS_SELECTOR, ".grid-cell-inner.grid-col-name")

使用XPATH

driver.find_element(By.XPATH, "//*[@class='grid-cell-inner grid-col-name']")

参考文献

您可以在以下位置找到一些相关的详细讨论:

How to locate an element with multiple classnames using Selenium and Python

【讨论】:

以上是关于Selenium python find_element_by_class_name() 从 v 2.2 到 2.21 停止工作——不能使用“复合类名”的主要内容,如果未能解决你的问题,请参考以下文章

python+selenium自动化测试——切换句柄

selenium入门14 窗口切换

selenium BY定位

使用selenium和phantomJS浏览器登陆豆瓣的小演示

如何循环每个元素

python自动化测试——基础操作