我有一些python 2.7脚本使用selenium从网站上抓取数据。我想要备份'元素,所以如果找不到第一个元素,它将转到下一个并尝试那个元素。这样一来,如果网站上的一件事情发生了变化,它就不会弄乱我的整个剧本。以下是我现在使用的内容,但是我有很多元素,想要知道是否有更高效,更短的方法来做到这一点而不会引发异常。
locators = [
(By.NAME, "email"),
(By.CSS_SELECTOR, "[name='email']"),
(By.XPATH, '//*body/div/div[2]/div/'),
(By.TAG_NAME, 'label')
]
for by, value in locators:
try:
elem = driver.find_element(by, value)
break
except NoSuchElementException:
pass
elem.send_keys('emailaddress@email.com')
答案 0 :(得分:1)
这是一个值得思考的问题,需要进行性能测量以了解不同方法的速度。
将定位器组合成单个表达式
如您所知,每次find_element()
次调用都会导致通过"FIND_ELEMENT"发送的Json Wire protocol selenium HTTP命令。这会带来很多开销,特别是如果你需要连续进行,直到找到所需的元素。
为了减少HTTP请求/响应的数量,我们可以将所有定位器组合成一个XPath表达式,如:
expression = "(//*[@name = 'email']|//*body/div/div[2]/div/|//label)"
elem = driver.find_element_by_xpath(expression)
当然,对于初学者来说,严重会降低可读性(但是,您可能会想出一个辅助函数,它会从不同定位器的列表中生成单个表达式)。并且,涉及多个DOM“扫描”会使表达速度变慢 - 尽管如此,我希望这比当前的方法更快,尤其是locators
的数量越来越多。
使用HTML解析器
您也可以将“页面来源”(driver.page_source
)传递给 HTML解析器,例如BeautifulSoup
或lxml
,以确定哪个定位器对你的元素有效。
您可能还会想到其他一些优化:
find_element*()
实例上调用driver
,您可以在父容器元素上调用它,您希望找到所需的元素 - 这可以是body
元素,或者它可以是带有div
的{{1}}元素,具体取决于您的目标网站布局class="container"
软件包和浏览器版本请注意,您可能会在不同的浏览器中获得不同的效果结果 - 实验和衡量。