【问题标题】:Python Selenium ChromeDriver not waiting for pages to loadPython Selenium ChromeDriver 不等待页面加载
【发布时间】:2017-12-19 06:35:09
【问题描述】:

我有一组 Web 抓取工具,旨在使用 Selenium ChromeDriver 在 Python 3.6 中运行。它们都运行得非常完美。

本周我将 Selenium 更新到 v2.8,将 ChromeDriver 更新到 v2.34。

立即,刮板无法正常工作并在爬行的早期崩溃。

我有一个sys.stdout 的小实现,它同时输出到 .txt 和控制台,所以我开始注意到错误是这样的:

Message: no such frame
(Session info: chrome=63.0.3239.108)
(Driver info: chromedriver=2.34.522940 
(1a76f96f66e3ca7b8e57d503b4dd3bccfba87af1),platform=Windows NT 10.0.15063 x86_64)

Message: no such element: Unable to locate element: 
{"method":"name","selector":"txtClave"}
(Session info: chrome=63.0.3239.108)
(Driver info: chromedriver=2.34.522940 
(1a76f96f66e3ca7b8e57d503b4dd3bccfba87af1),platform=Windows NT 10.0.15063 x86_64)

Message: no such element: Unable to locate element: 
{"method":"xpath","selector":"//*[@id="ctl00_cp_wz_ddlTarjetas"]/option[2]"}
(Session info: chrome=63.0.3239.108)
(Driver info: chromedriver=2.34.522940 
(1a76f96f66e3ca7b8e57d503b4dd3bccfba87af1),platform=Windows NT 10.0.15063 x86_64)

Message: no such element: Unable to locate element: 
{"method":"xpath","selector":"//*[@id="ctl00_cp_wz_ddlTarjetas"]/option[3]"}
(Session info: chrome=63.0.3239.108)
(Driver info: chromedriver=2.34.522940 
(1a76f96f66e3ca7b8e57d503b4dd3bccfba87af1),platform=Windows NT 10.0.15063 x86_64)

Message: no such element: Unable to locate element: 
{"method":"xpath","selector":"//*[@id="ctl00_cp_wz_ddlTarjetas"]/option[4]"}
(Session info: chrome=63.0.3239.108)
(Driver info: chromedriver=2.34.522940 
(1a76f96f66e3ca7b8e57d503b4dd3bccfba87af1),platform=Windows NT 10.0.15063 x86_64)

之后通常会出现以前从未出现过的 ChromeDriver 崩溃 Windows 消息:chromedriver.exe has stopped working

在查看 Chrome 窗口时,通过调试,我怀疑错误是在应该让蜘蛛等待页面加载的行引起的,但它没有等待,所以它无法找到元素

导致错误的行示例:

self.driver.find_element_by_name('txtUsuario').send_keys(user + Keys.RETURN)
self.driver.find_element_by_name('txtClave').send_keys(passwd + Keys.RETURN)

...

self.driver.switch_to.default_content()
self.driver.switch_to_frame('Fmenu')
self.driver.find_element_by_xpath(XPATH_POSICIONGLOBAL).click()

发现它太难过(基本上是投降)而无法通过向每个要交互的​​元素添加显式等待来故障转移(可能是因为我有超过一百个?)。

我希望有人能帮助我找出可能导致整个工作蜘蛛无法在这些新版本的 ChromeDriver / Selenium 中爬行的原因,并解决此问题的代码优雅且易于实施的解决方案。

例如,我尝试将 implicitly_wait 附加到 WebDriver 会话,但它根本不起作用。

def __init__(self):
    self.driver = webdriver.Chrome(PATH_WEBDRIVER)
    self.driver.implicitly_wait(10)

最后,我使用 IDLE 一次运行了两个失败的蜘蛛 1 行,它可以工作!那么......为什么它不能在常规的 Spider 执行中工作?????

非常感谢提前

【问题讨论】:

  • 将等待时间增加到100
  • 您的 Chrome 是什么版本?
  • 我使用的是最新的 Chrome 版本。此外,我怀疑implicitly_wait 失败了,因为它在 10 秒或 100 秒内根本什么都不做。我现在不在家,我会在一段时间内发布它给出的错误

标签: python selenium web-crawler selenium-chromedriver


【解决方案1】:

让我尝试一一解决您的错误:

  • 消息:没有这样的框架:如果您尝试在框架可用之前切换到该框架,则可能会出现此错误。在这种情况下,您需要使用匹配的expected_conditions 来诱导WebDriverWait,以便<iframe> 可用于切换。

您可以在How can I select a html element no matter what frame it is in in selenium?找到详细讨论

  • 消息:没有这样的元素:无法定位元素:如果您尝试与之交互的 WebElement 不是 ,则可能会出现此错误呈现可见可点击可交互。在这种情况下,您需要用匹配的expected_conditions 诱导WebDriverWait。以下是广泛使用的方法列表:

    class selenium.webdriver.support.expected_conditions.presence_of_element_located(locator)        
    class selenium.webdriver.support.expected_conditions.visibility_of_element_located(locator)
    class selenium.webdriver.support.expected_conditions.element_to_be_clickable(locator)
    
  • chromedriver.exe 已停止工作:如果您的系统 JDK 版本、Selenium 版本、@987654328,则会出现此错误@版本和版本不兼容,不同步。

  • self.driver.find_element_by_name('txtUsuario').send_keys(user + Keys.RETURN) : 尝试分两步分解线路:

    self.driver.find_element_by_name('txtUsuario').send_keys(user)
    self.driver.find_element_by_name('txtUsuario').send_keys(Keys.RETURN)
    
  • self.driver.implicitly_wait(10):尝试摆脱Implicit Wait。为了使领先的WebDriver 实例与尾随的Web 客户端 保持同步,我们必须使用WebDriverWait,即ExplicitWait。但是你不应该混淆Implicit WaitExplicitWait。请参阅下面的注释:

注意Selenium Documentation 明确提到 - WARNING: Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times. For example setting an implicit wait of 10 seconds and an explicit wait of 15 seconds, could cause a timeout to occur after 20 seconds.


结论

如果要求只是抓取/抓取网页,请使用 BeautifulSoup 抓取/抓取并仅使用 Selenium 浏览页面。

【讨论】:

  • 这绝对是一个非常令人失望的问题,我遇到了一个运行如此顺利的东西 :( 在 WebDriver 源代码中挖掘了很多东西,并怀疑它是一个 ChromeDriver 错误。我开始应用显式等待方法重新开始工作,但是有太多蜘蛛要修改每个 +10 find_elements,我正在考虑编写一个可以附加到驱动程序的自定义服务员(每个蜘蛛定义一次),而不是为每个失败的 find_element 编写 WebDriverWaits
  • 仅初始化一次 WebDriverWait 并尝试在每个 expected_conditions 上重用 WebDriverWait 实例。同样,由于您只是在爬行,您可以缩小到单个 expected_conditions,即 presence_of_element_located。所以一个小众想法是写一个function() 并传递相关的WebElement 以返回为scrapable / crawlable。希望这会有所帮助。
  • 是的。在我的蜘蛛中实现了 2 个非常相似的功能:def custom_find(self, by, selector): return WebDriverWait(self.driver, 30).until(EC.visibility_of_element_located((by, selector))) ...和 ​​... def custom_frame_switch(self, locator): WebDriverWait(self.driver, 30).until(EC.frame_to_be_available_and_switch_to_it(locator))。这样,我可以根据需要多次重用 WebDriverWait 实例,而无需在我的 Notepadd++ 中执行许多复杂的替换执行。
  • 最后,决定回滚到 Chrome 62,因为它完全修复了所有错误。
  • @Jesus21282 虽然没有最佳实践,但降级不应该是解决方案。尝试使用最新版本,我们将一一解决。
猜你喜欢
  • 2017-03-27
  • 1970-01-01
  • 2018-03-20
  • 2018-11-26
  • 1970-01-01
  • 2018-03-01
  • 1970-01-01
  • 2017-11-10
  • 2011-08-17
相关资源
最近更新 更多