爬虫之Selenium的等待及定位
- 2019 年 10 月 5 日
- 筆記
爬虫之Selenium的等待及定位
0.导语
1.selenium的三种等待方式
1.1 强制等待
1.2 隐性等待
1.3 显性等待
2. selenium之定位以及切换frame
2.1 切frame操作
2.2 切回主文档
2.3 嵌套frame的操作
2.4 总结
3.学习文章
0.导语
关于昨天的机器学习文章,希望能够亲自码一下,将会学到很多东西,如果觉得很好,欢迎转发,谢谢! 有关翻译贡献,可点击公众号右下角联系我,备注:翻译,或者昨日文章的阅读原文,pr到仓库中来! 关于今天的爬虫文章,则是一篇之前练习爬虫碰到的问题解决策略,希望可以帮助大家,下面一起来看吧,欢迎留言与转发!
1.selenium的三种等待方式
Selenium自动化处理时,这个下拉框定位不到、那个弹出框定位不到…各种定位不到,其实大多数情况下就是两种问题:1 有frame,2 没有加等待。浏览器的加载速度太慢。代码速度太快。这就造成了定位不准确的问题。
1.1 强制等待
# -*- coding: utf-8 -*- from selenium import webdriver from time import sleep driver = webdriver.Chrome() driver.get('https://light-city.me') sleep(3) # 强制等待3秒再执行下一步 print driver.current_url driver.quit()
这种叫强制等待,不管浏览器是否加载完毕,程序都得等待3秒。3秒后,程序继续执行。
1.2 隐性等待
第二种办法叫隐形等待,implicitly_wait(xx)
,隐形等待表示代码给浏览器等待设定一个最长时间,不管代码速度多块,都要等浏览器xx秒,如果浏览器这段时间内来了,则两个同步运行,否则,如果浏览器在规定时间内没到,则代码继续运行,接着抛出异常。
# -*- coding: utf-8 -*- from selenium import webdriver driver = webdriver.Chrome() driver.implicitly_wait(30) # 隐性等待,最长等30秒 driver.get('https://light-city.me') print driver.current_url driver.quit()
隐形等待是设置了一个最长等待时间,如果在规定时间内网页加载完成,则执行下一步,否则一直等到时间截至,然后执行下一步。弊端:程序会一直等待整个页面加载完成,也就是一般情况下看到的浏览器标签栏小圈不转,才执行下一步。如果想等到我要的元素出来直接进入下一步,就需要用显示等待了。
隐性等待对整个driver的周期都起作用,所以只要设置一次即可,整个跟sleep不一样,不能多次使用。
1.3 显性等待
第三种办法就是显性等待,WebDriverWait
,配合该类的until()
和until_not()
方法。显性等待表示程序每隔xx秒看一眼,如果条件成立了,则执行下一步,否则继续等待,直到超过了设置的最长时间,然后抛出TimeoutException。
# -*- coding: utf-8 -*- from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By driver = webdriver.Chrome() driver.implicitly_wait(10) # 隐性等待和显性等待可以同时用,但要注意:等待的最长时间取两者之中的大者 driver.get('https://xxxx.com') locator = (By.LINK_TEXT, 'xxx') # 用By类定位 try: WebDriverWait(driver, 20, 0.5).until(EC.presence_of_element_located(locator)) print driver.find_element_by_link_text('xxx').get_attribute('href') finally: driver.close()
selenium.webdriver.common.by.By
支持的定位器分类
CLASS_NAME = 'class name' CSS_SELECTOR = 'css selector' ID = 'id' LINK_TEXT = 'link text' NAME = 'name' PARTIAL_LINK_TEXT = 'partial link text' TAG_NAME = 'tag name' XPATH = 'xpath'
expected_conditions
selenium.webdriver.support.expected_conditions(模块)
WebDriverWait
参数与方法
selenium.webdriver.support.wait.WebDriverWait(类) __init__ driver: 传入WebDriver实例,即我们上例中的driver timeout: 超时时间,等待的最长时间(同时要考虑隐性等待时间) poll_frequency: 调用until或until_not中的方法的间隔时间,默认是0.5秒 ignored_exceptions: 忽略的异常,如果在调用until或until_not的过程中抛出这个元组中的异常, 则不中断代码,继续等待,如果抛出的是这个元组外的异常,则中断代码,抛出异常。默认只有NoSuchElementException。 until method: 在等待期间,每隔一段时间调用这个传入的方法,直到返回值不是False message: 如果超时,抛出TimeoutException,将message传入异常 until_not 与until相反,until是当某元素出现或什么条件成立则继续执行,until_not是当某元素消失或什么条件不成立则继续执行,参数也相同,不再赘述。
调用方法
WebDriverWait(driver, 超时时长, 调用频率, 忽略异常).until(可执行方法, 超时时返回的信息)
这里需要特别注意的是until或until_not中的可执行方法method参数,很多人传入了WebElement对象,如下:
WebDriverWait(driver, 10).until(driver.find_element_by_id('kw')) # 错误
在这里,可以用selenium提供的 expected_conditions
模块中的各种条件,也可以用WebElement的 is_displayed()
、is_enabled()
、is_selected()
方法,或者用自己封装的方法都可以。
2. selenium之定位以及切换frame
frameset不用切,frame需层层切!
frame标签有frameset、frame、iframe三种,frameset跟其他普通标签没有区别,不会影响到正常的定位,而frame与iframe对selenium定位而言是一样的,selenium有一组方法对frame进行操作。
2.1 切frame操作
switch_to.frame()
from selenium import webdriver driver = webdriver.Firefox() driver.switch_to.frame(0) # 1.用frame的index来定位,第一个是0 # driver.switch_to.frame("frame1") # 2.用id来定位 # driver.switch_to.frame("myframe") # 3.用name来定位 # driver.switch_to.frame(driver.find_element_by_tag_name("iframe")) # 4.用WebElement对象来定位
2.2 切回主文档
switch_to.default_content()
如果想继续操作主文档的元素,则需要切回主文档。
driver.switch_to.default_content()
2.3 嵌套frame的操作
<html> <iframe id="frame1"> <iframe id="frame2" / > </iframe> </html>
从主文档切到frame2,一层层切进去
driver.switch_to.frame("frame1") driver.switch_to.frame("frame2")
从frame2再切回frame1
driver.switch_to.parent_frame() # 如果当前已是主文档,则无效果
2.4 总结
driver.switch_to.frame(reference) driver.switch_to.parent_frame() driver.switch_to.default_content()
3.学习文章
(1)Python selenium —— 一定要会用selenium的等待,三种等待方式解读
https://huilansame.github.io/huilansame.github.io/archivers/sleep-implicitlywait-wait
(2)selenium之 定位以及切换frame(iframe)
(https://blog.csdn.net/huilan_same/article/details/52200586)