【问题标题】:How to find web element with Selenium Python while iterating through URLs如何在遍历 URL 时使用 Selenium Python 查找 Web 元素
【发布时间】:2019-11-13 16:46:26
【问题描述】:

我需要循环并从一百万个网页中抓取一个元素(所有页面的类名相同)。我以以下(简化)方式设置了代码:

driver = webdriver.Firefox()
wait = WebDriverWait(driver, 10)
detail_dict = {}
for i in range(1000000):
    url = f'http://www.cnappc.it/risultato.aspx?IDAssociato={i}&tipo=1#edit'
    driver.get(url)
    elem_detail = wait.until(expected_conditions
                             .presence_of_element_located((By.CLASS_NAME, 'content')))
    detail_dict[i] = elem_detail.text

代码运行得相当顺利,当我中断内核进行检查时,我注意到iurl 每次迭代都会增加。但是,驱动程序网页“卡”在第一个 URL 上,即http://www.cnappc.it/risultato.aspx?IDAssociato=0&tipo=1#edit,因此elem_detail.text 一遍又一遍地返回相同的字符串。似乎驱动程序网页无法跟上driver.get(url) 方法,尽管.get() 等待页面完全加载。

来自Selenium-Python/Getting Started

driver.get 方法将导航到 URL 给出的页面。 WebDriver 将等待页面完全加载(即“onload”事件已触发),然后再将控制权返回给您的测试或脚本。

我为elem_detail 插入了预期条件,但无济于事。在driver.get(url) 之后设置time.sleep(2) 允许驱动程序网页更改和显示不同的内容,但是我将面临严重的减速。即使这样,页面也会不时卡住,字典值条目最终会不系统地重复。

您能否推荐一种不涉及time.sleep() 的稳健方法?


仅供参考:我将 selenium 与 geckodriver 一起使用。

【问题讨论】:

  • 您已将超时设置为 10,尝试使用带有异常的 try catch 块,类似这样的尝试: # 等待所需的时间,或最多等待 10 秒以显示警报 WebDriverWait(driver, 10).until(cond.alert_is_present()) obj = driver.switch_to.alert except (NoAlertPresentException, TimeoutException) as py_ex: print("Alert not present") print (py_ex) print (py_ex.args) finally: driver.quit () ,这将帮助我们在每次迭代中找出问题所在。
  • 感谢您的建议@redhatvicky。参考我发布的代码,我应该在driver.get(url) 命令之后插入你建议的try/except/finally 吗?
  • 每个代码都应该在 try 块内,这样预期的异常就会被捕获,我们可以看到在什么迭代中发生了什么,要么发生超时问题,要么发生任何其他异常跨度>
  • 感谢@redhatvicky,我按照您的指示进行操作,结果如下:警报不存在\n 消息:\n ('', None, None)。我从来没有在网页上遇到过警报,并且我的代码运行时没有错误(除了每隔一段时间会出现一些 TimeoutException [通常在我遇到这样的错误之前发生数百次迭代])。

标签: python selenium-webdriver web-scraping webdriverwait expected-condition


【解决方案1】:

试试这个语法,你的代码对我不起作用(python 2.7)

for i in range(1000000):
    url = "http://www.cnappc.it/risultato.aspx?IDAssociato=%s&tipo=1#edit" %i
    print("Get url >> %s" %url) #Just for debug and get output
    driver.get(url)

    wait = WebDriverWait(driver, 10)
    elem_detail = ....

【讨论】:

  • 感谢您的回复旺卡!我的问题仍然存在:即使使用您的语法,elem_detail.text 也会返回我传递给 driver.get(url) 方法的第一个 url 的字符串,并且每次迭代都不会改变。
  • 使用硒,每次交互后总是设置睡眠时间,尝试新的编辑
  • 另外,我又查了一遍,每次循环声明等待
  • 另一个建议,detail_dict[i] 用于循环变量!在最后一次运行时,您将访问一个包含 1000000-1 个项目的列表。我无法访问网站,但这看起来很糟糕。使用 i 来迭代 url(在硬编码从 1 到 1000000 迭代的方式上是个坏主意……)
  • 谢谢旺卡。我同意你的观点,睡眠时间有效(我在问题中提到了我自己),但我试图将等待时间限制在绝对必要的范围内,所以我希望有一个不强加睡眠时间的解决方案(也在问题)。至于您的最后一句话,我发布的代码已简化。实际上,我强加了一个条件,即我的字典应该只收集大约 250k 个键。不过谢谢你的想法。
【解决方案2】:

我设法解决了切换到webdriver.Chrome() 的问题。 webdriver实际上等待每个页面加载,搜索类元素并移动到下一页,而不指定任何time.sleep()

【讨论】:

    猜你喜欢
    • 2019-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-12
    相关资源
    最近更新 更多