【问题标题】:splinter: faster way to find elements?splinter:找到元素的更快方法?
【发布时间】:2023-03-07 22:20:01
【问题描述】:

所以我使用python splinter library 来测试一个网络应用程序,当我检查一个元素是否存在并且我手动查找每个元素来操作它时,我遇到了一个问题。

问题在于,当输入列表大于 4 个或更多项目并且遇到元素不存在的情况时,需要 12 秒以上才能完成。

我也试过设置wait_time=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

【问题讨论】:

  • 只是为了澄清:所有输入是否同时出现?另外,你能分享一下链接以便我们测试吗?谢谢。
  • @alexcxe 是的,输入可用。它基本上是一个 xpath 列表。我正在此页面上对其进行测试,它需要很长时间才能获取目录列表中的所有文本。如果我在 javascript 中执行此操作,它会做得非常快,但使用 splinter,似乎每次找不到东西时它都会等待并且它加起来。 bit.ly/1p8dLrg
  • 感谢您提供的信息。但是你也可以显示你到目前为止的代码吗?这肯定会帮助您解决问题。
  • @alecxe 我添加了一些代码
  • 你的 xpath 是什么?

标签: python splinter


【解决方案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 返回一个ElementList

ElementList 有一个方法 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 年 6 月 20 日更新:

进入兔子洞。 Splinter 正在调用 selenium wedriver……self.find_by(self.driver.find_elements_by_xpath, … 这是另一个级别的初始。我不确定他们为什么决定这样做,而不是一开始就直接调用 selenium。

仅出于测试目的,您应该首先尝试使用代码的这个特定部分直接使用 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 的实现,如果你正在使用的话。

2014 年 6 月 20 日更新 2:

还请注意,特别是对于 XPath,它实际上取决于所使用的驱动程序。硒documentation about this specific search:

在高层次上,WebDriver 尽可能使用浏览器的原生 XPath 功能。在那些不支持原生 XPath 的浏览器上,我们提供了自己的实现。除非您意识到各种 xpath 引擎的差异,否则这可能会导致一些意外行为。

【讨论】:

  • 我将对此进行测试并在明天报告。
  • 这并没有做任何改进。麻烦的是,当它遇到缺少的元素时,它会等待几秒钟。我认为解决这个问题的唯一方法是使用 javascript
  • 你的 xpath 列表是什么?您是否尝试过仅包含 1 个项目的 xpath 列表。
  • @KJW 你的意思是“当它不匹配任何元素时”因为“遇到缺失的元素”似乎具有误导性?如果您可以添加到原始帖子中,那将是很好的。您尝试获得的减少标记和 xpath。
  • Emptiness 定义了 ElementList 的布尔值。 element_list.is_empty() 可以改写为not element_list
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-02
  • 2019-12-14
  • 2014-03-15
  • 2016-01-14
  • 1970-01-01
相关资源
最近更新 更多