【发布时间】:2013-09-14 18:52:51
【问题描述】:
我正在使用 Selenium 2(2.33 版 Python 绑定,Firefox 驱动程序)编写一个通用的网络爬虫。它应该采用 任意 URL,加载页面并报告所有出站链接。由于 URL 是任意的,因此我无法对页面内容做出任何假设,因此通常的建议(等待特定元素出现)是不适用的。
我的代码应该轮询 document.readyState,直到它达到“完成”或 30 秒超时,然后继续:
def readystate_complete(d):
# AFAICT Selenium offers no better way to wait for the document to be loaded,
# if one is in ignorance of its contents.
return d.execute_script("return document.readyState") == "complete"
def load_page(driver, url):
try:
driver.get(url)
WebDriverWait(driver, 30).until(readystate_complete)
except WebDriverException:
pass
links = []
try:
for elt in driver.find_elements_by_xpath("//a[@href]"):
try: links.append(elt.get_attribute("href"))
except WebDriverException: pass
except WebDriverException: pass
return links
这种方法有效,但在大约五分之一的页面上,.until 调用永远挂起。发生这种情况时,通常浏览器实际上还没有完成页面加载(“颤动”仍在旋转),但可能会经过数十分钟并且不会触发超时。但有时页面确实似乎已经完全加载,脚本仍然没有继续。
什么给了?如何使超时可靠地工作?是否有更好的方法来请求等待页面加载(如果无法对内容做出任何假设)?
注意:WebDriverException 的强迫性捕获和忽略已被证明是必要的,以确保它从页面中提取尽可能多的链接,无论页面内的 JavaScript 是否正在使用 DOM 做有趣的事情(例如,我用于在提取 HREF 属性的循环中获取“陈旧元素”错误)。
注意:这个问题在这个网站和其他地方都有很多变化,但它们都有一个微妙但关键的区别,使得答案(如果有的话)对我,或者我已经尝试了这些建议,但它们不起作用。 请准确地回答我提出的问题。
【问题讨论】:
-
如果您使用的是
WebDriverWait,那么您使用的是 Selenium 2,而不是 Selenium RC。 -
@RossPatterson 我的印象是 Selenium 2 和 Selenium RC 是一回事,而 Selenium IDE 是旧的 QuicKeys 风格的东西。谢谢指正。
-
你最后做了什么?
-
@KnewB 我放弃了。我的代码现在设置了一个全局一分钟超时,然后执行
driver.get(url),紧接着是driver.find_elements_by_xpath("//a[@href]")。这似乎在报告链接之前等待页面加载。它仍然时不时地永远挂起,所以我还写了一个看门狗进程,如果它在五分钟内没有报告任何进展,它将杀死并重新启动整个浏览器。它经常触发,足以让人头疼,但不值得我花时间尝试进一步调试它。我还是希望有更多线索的人来这里。 -
您可以使用 pageLoadTimeOut() 方法。这需要浏览器等待页面加载的最长时间。如果页面在最大时间之前加载,则脚本继续执行。如果页面在最大时间后未加载,您可以捕获异常并关闭浏览器。希望这对您有所帮助。
标签: python webdriver selenium-webdriver