爬虫之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 强制等待
代码语言:javascript复制# -*- 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是当某元素消失或什么条件不成立则继续执行,参数也相同,不再赘述。
调用方法
代码语言:javascript复制WebDriverWait(driver, 超时时长, 调用频率, 忽略异常).until(可执行方法, 超时时返回的信息)
这里需要特别注意的是until或until_not中的可执行方法method参数,很多人传入了WebElement对象,如下:
代码语言:javascript复制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的操作
代码语言:javascript复制<html>
<iframe id="frame1">
<iframe id="frame2" / >
</iframe>
</html>
从主文档切到frame2,一层层切进去
代码语言:javascript复制driver.switch_to.frame("frame1")
driver.switch_to.frame("frame2")
从frame2再切回frame1
代码语言:javascript复制driver.switch_to.parent_frame() # 如果当前已是主文档,则无效果
2.4 总结
代码语言:javascript复制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)