Selenium有一个方便的机制,可以在一次快速往返中相当有效地从DOM中提取数十个或数百个元素:
buttons = driver.find_elements_by_css_selector('button')
Run Code Online (Sandbox Code Playgroud)
结果buttons可以是几十个或几百个元素的列表而没有任何问题.
但是如果你想使用is_displayed()(或者像Java那样调用它isElementDisplayed)来过滤元素,那么事情就会慢慢爬行,因为对方法的每次调用都需要往返浏览器.即使在我最快的开发机器上,每个这样的调用大约需要0.1秒,这意味着100个元素的后续过滤需要10秒(!):
[b.is_displayed() for b in buttons]
Run Code Online (Sandbox Code Playgroud)
如果您想查找具有特定文本的按钮,则会出现同样的问题,因为.text事实上每次查找属性都会调用一个属性,并将其自己的往返返回到浏览器:
[('Subscribe' in b.text) for b in buttons]
Run Code Online (Sandbox Code Playgroud)
这使得编写强大的Selenium测试变得很困难,这些测试注意到关于DOM真正面向用户的两件事:元素是否可见,以及它包含哪些文本.虽然完全远离可见性和文本内容(例如,对于唯一ID或类或文档位置的组合)的转动会使我们的测试运行得更快,但它会在我们的Selenium测试和它正在寻找的按钮之间创建一个不可见的链接,而是让我们的测试关注用户体验以及用户可以在屏幕上看到和阅读的内容.
我的问题:
在初始获取元素期间,有没有办法在浏览器上应用is_displayed()或text测试元素?
或者有没有办法进行批量is_displayed()调用,询问大量元素而不只是一个?
或者从Firefox测试到Firefox下的Selenium的0.1s往返时间完全不合理,并且对其他人来说运行速度更快,这就是为什么这些常见操作的明显批处理版本不存在的原因?
我原以为我可以转向execute_script()从Python 运行(Java名称:),executeScript()并从我的JavaScript代码内部以某种方式执行Selenium的逻辑,这个逻辑背后是"这个元素可见"的复杂概念.遗憾的是,executeScript()似乎没有让脚本访问Selenium本身认为必不可少的任何util函数,因此要访问is-visible函数,我们必须将jQuery或随机Selenium代码片段拉入缺少它们的页面中,干扰测试的整个概念:它只是为了运行我们的测试而在不改变其JS配置文件的情况下测试页面.
谢谢你的任何想法!令我感到惊讶的是,Selenium期望呼叫者executeScript()能够重建这样的功能is_displayed(),正如代码所示,这是Selenium的一个主要特征,看起来需要做很多工作才能获得正确的,并且需要从所有可能的代码,以避免重新发明这样一个重要的轮子.
使用Python,Selenium和PhantomJS获取多个元素的相同属性的最有效方法是什么?我的解决方案使用find_elements_by_css_selector哪个定位我需要的所有元素,这需要不到一秒钟,然后我循环遍历列表以获取我需要的属性.我的循环花费了大约2500个元素的一分钟,考虑到所有元素都是用find_elements_by_css_selector方法映射的,这对我来说似乎很多.是get_attribute方法真的那么贵还是我做错了什么?
from selenium import webdriver
driver = webdriver.PhantomJS(executable_path=r'mypath\phantomjs.exe')
driver.set_window_size(1120, 550)
driver.get("https://www.something.com")
table = []
elements = driver.find_elements_by_css_selector("tr[id*='bet-']") # takes under 1 second
for element in elements:
table.append(element.get_attribute('data-info')) # takes over 60 seconds (2000 elements)
driver.close
Run Code Online (Sandbox Code Playgroud)