爬虫之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)