前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >爬虫之Selenium的等待及定位

爬虫之Selenium的等待及定位

作者头像
公众号guangcity
发布2019-09-20 14:38:59
9230
发布2019-09-20 14:38:59
举报

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-01-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 光城 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 爬虫之Selenium的等待及定位
    • 0.导语
      • 1.selenium的三种等待方式
        • 1.1 强制等待
        • 1.2 隐性等待
        • 1.3 显性等待
      • 2. selenium之定位以及切换frame
        • 2.1 切frame操作
        • 2.2 切回主文档
        • 2.3 嵌套frame的操作
        • 2.4 总结
      • 3.学习文章
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档