splinter:更快的查找元素的方法?
我正在使用python splinter库来测试一个网页应用,但我遇到了一个问题,就是在检查某个元素是否存在时,我需要手动找到每一个元素来进行操作。
问题是,当输入列表的项目超过4个时,如果遇到某个元素不存在的情况,整个过程会花费超过12秒才能完成。
我也尝试过设置等待时间为1秒,但如果输入列表超过10个,如果页面上根本没有这个元素,整个过程会花费10倍的时间。
for i in inputs:
if browser.element_exists():
elm = browser.find_element():
elm.text()
我需要找到一种方法来加快这个检查元素的速度,让它们可以同时进行,而不是一个一个地检查。我唯一能想到的就是执行JavaScript,但我不太喜欢这样(我希望能全部用Python来完成)。
def get_columns(current_depth,step,element):
columns = []
for xpath in xpaths:
what = parse_xpath(row[2])
if browser.is_element_present_by_xpath(xpath,wait_time=1):
element = browser.find_by_xpath(xpath)
columns.append(element.text)
else:
columns.append('none')
return columns
1 个回答
is_element_present_by_xpath
这段代码是
def is_element_present_by_xpath(self, xpath, wait_time=None):
return self.is_element_present(self.find_by_xpath, xpath, wait_time)
使用
def is_element_present(self, finder, selector, wait_time=None):
wait_time = wait_time or self.wait_time
end_time = time.time() + wait_time
while time.time() < end_time:
if finder(selector):
return True
return False
和
def find_by_xpath(self, xpath, original_find=None, original_query=None):
original_find = original_find or "xpath"
original_query = original_query or xpath
return self.find_by(self.driver.find_elements_by_xpath,
xpath,
original_find=original_find,
original_query=original_query)
你的代码基本上是用同一个函数调用了两次。第一次你在列表中查找元素是否存在,使用了 find_by_xpath
,然后第二次再查找这个元素。
find_by_xpath
会返回一个 元素列表。
这个元素列表有一个方法 is_empty()
,如果列表是空的,也就是没有找到匹配的元素,它会返回 True。
那么关于这个(我没有测试过,但这是我随便想的)
def get_columns(current_depth,step,element):
columns = []
for xpath in xpaths:
what = parse_xpath(row[2])
element_list = browser.find_by_xpath(xpath)
# You might want to check that your element_list has only 1 element.
if element_list.is_empty():
columns.append('none')
else:
columns.append(element_list[0].text)
return columns
这样可以避免重复遍历列表两次。
更新 2014-06-20:
深入了解一下。Splinter 是在调用 selenium 的 webdriver… self.find_by(self.driver.find_elements_by_xpath, …
这又是一个更深层次的调用。我不太明白他们为什么不直接调用 selenium。
为了测试,你可以尝试直接使用 selenium 来处理这部分代码,看看性能上有没有明显的差别。这样可以判断性能问题是出在 splinter 还是 selenium。
在 selenium/webdriver/remote/webdriver.py 中
```def find_elements_by_xpath(self, xpath): """ 通过 xpath 查找多个元素。
:Args:
- xpath - The xpath locator of the elements to be found.
:Usage:
driver.find_elements_by_xpath("//div[contains(@class, 'foo')]")
"""
return self.find_elements(by=By.XPATH, value=xpath)
```
这个方法使用了:
``` def find_elements(self, by=By.ID, value=None): """ 被 find_elements_by_* 方法使用的“私有”方法。
:Usage:
Use the corresponding find_elements_by_* instead of this.
:rtype: list of WebElement
"""
if not By.is_valid(by) or not isinstance(value, str):
raise InvalidSelectorException("Invalid locator values passed in")
return self.execute(Command.FIND_ELEMENTS,
{'using': by, 'value': value})['value']
```
最后这个方法是通过 JsonWireProtocol 直接调用 API。这里的性能很大程度上取决于你系统上 Selenium 的实现和/或你使用的浏览器。
更新 2 2014-06-20:
另外要注意的是,特别是对于 XPath,性能真的取决于使用的驱动程序。Selenium 的 关于这种特定搜索的文档:
从高层次来看,WebDriver 尽可能使用浏览器的原生 XPath 功能。在那些没有原生 XPath 支持的浏览器上,我们提供了自己的实现。这可能会导致一些意想不到的行为,除非你了解不同 XPath 引擎之间的差异。