爬虫 + 自动化利器 selenium 之自学成才篇(二)_爬虫可以加自动化吗(1)


设置元素等待

很多页面都使用 ajax 技术,页面的元素不是同时被加载出来的,为了防止定位这些尚在加载的元素报错,可以设置元素等来增加脚本的稳定性。webdriver 中的等待分为 显式等待 和 隐式等待。

显式等待

显式等待:设置一个超时时间,每个一段时间就去检测一次该元素是否存在,如果存在则执行后续内容,如果超过最大时间(超时时间)则抛出超时异常(TimeoutException)。显示等待需要使用 WebDriverWait,同时配合 untilnot until 。下面详细讲解一下。

WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)

  • driver:浏览器驱动
  • timeout:超时时间,单位秒
  • poll_frequency:每次检测的间隔时间,默认为0.5秒
  • ignored_exceptions:指定忽略的异常,如果在调用 untiluntil_not 的过程中抛出指定忽略的异常,则不中断代码,默认忽略的只有 NoSuchElementException

until(method, message=’ ‘)
until_not(method, message=’ ')

  • method:指定预期条件的判断方法,在等待期间,每隔一段时间调用该方法,判断元素是否存在,直到元素出现。until_not 正好相反,当元素消失或指定条件不成立,则继续执行后续代码
  • message: 如果超时,抛出 TimeoutException ,并显示 message 中的内容

method 中的预期条件判断方法是由 expected_conditions 提供,下面列举常用方法。

先定义一个定位器

from selenium.webdriver.common.by import By
from selenium import webdriver

driver = webdriver.Chrome()
locator = (By.ID, 'kw')
element = driver.find_element_by_id('kw')

方法描述
title_is(‘百度一下’)判断当前页面的 title 是否等于预期
title_contains(‘百度’)判断当前页面的 title 是否包含预期字符串
presence_of_element_located(locator)判断元素是否被加到了 dom 树里,并不代表该元素一定可见
visibility_of_element_located(locator)判断元素是否可见,可见代表元素非隐藏,并且元素的宽和高都不等于0
visibility_of(element)跟上一个方法作用相同,但传入参数为 element
text_to_be_present_in_element(locator , ‘百度’)判断元素中的 text 是否包含了预期的字符串
text_to_be_present_in_element_value(locator , ‘某值’)判断元素中的 value 属性是否包含了预期的字符串
frame_to_be_available_and_switch_to_it(locator)判断该 frame 是否可以 switch 进去,True 则 switch 进去,反之 False
invisibility_of_element_located(locator)判断元素中是否不存在于 dom 树或不可见
element_to_be_clickable(locator)判断元素中是否可见并且是可点击的
staleness_of(element)等待元素从 dom 树中移除
element_to_be_selected(element)判断元素是否被选中,一般用在下拉列表
element_selection_state_to_be(element, True)判断元素的选中状态是否符合预期,参数 element,第二个参数为 True/False
element_located_selection_state_to_be(locator, True)跟上一个方法作用相同,但传入参数为 locator
alert_is_present()判断页面上是否存在 alert

下面写一个简单的例子,这里定位一个页面不存在的元素,抛出的异常信息正是我们指定的内容。

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
element = WebDriverWait(driver, 5, 0.5).until(
            EC.presence_of_element_located((By.ID, 'kw')),
                                           message='超时啦!')

在这里插入图片描述

隐式等待

隐式等待也是指定一个超时时间,如果超出这个时间指定元素还没有被加载出来,就会抛出 NoSuchElementException 异常。
除了抛出的异常不同外,还有一点,隐式等待是全局性的,即运行过程中,如果元素可以定位到,它不会影响代码运行,但如果定位不到,则它会以轮询的方式不断地访问元素直到元素被找到,若超过指定时间,则抛出异常。

使用 implicitly_wait() 来实现隐式等待,使用难度相对于显式等待要简单很多。
示例:打开个人主页,设置一个隐式等待时间 5s,通过 id 定位一个不存在的元素,最后打印 抛出的异常 与 运行时间。

from selenium import webdriver
from time import time

driver = webdriver.Chrome()
driver.get('https://blog.csdn.net/qq\_43965708')

start = time()
driver.implicitly_wait(5)
try:
    driver.find_element_by_id('kw')
except Exception as e:
    print(e)
    print(f'耗时:{time()-start}')

在这里插入图片描述
代码运行到 driver.find_element_by_id('kw') 这句之后触发隐式等待,在轮询检查 5s 后仍然没有定位到元素,抛出异常。

强制等待

使用 time.sleep() 强制等待,设置固定的休眠时间,对于代码的运行效率会有影响。以上面的例子作为参照,将 隐式等待 改为 强制等待。

from selenium import webdriver
from time import time, sleep

driver = webdriver.Chrome()
driver.get('https://blog.csdn.net/qq\_43965708')

start = time()
sleep(5)
try:
    driver.find_element_by_id('kw')
except Exception as e:
    print(e)
    print(f'耗时:{time()-start}')

在这里插入图片描述
值得一提的是,对于定位不到元素的时候,从耗时方面隐式等待和强制等待没什么区别。但如果元素经过 2s 后被加载出来,这时隐式等待就会继续执行下面的代码,但 sleep还要继续等待 3s。

定位一组元素

上篇讲述了定位一个元素的 8 种方法,定位一组元素使用的方法只需要将 element 改为 elements 即可,它的使用场景一般是为了批量操作元素。

  • find_elements_by_id()
  • find_elements_by_name()
  • find_elements_by_class_name()
  • find_elements_by_tag_name()
  • find_elements_by_xpath()
  • find_elements_by_css_selector()
  • find_elements_by_link_text()
  • find_elements_by_partial_link_text()

这里以 CSDN 首页的一个 博客专家栏 为例。
在这里插入图片描述
下面使用 find_elements_by_xpath 来定位三位专家的名称。
在这里插入图片描述
这是专家名称部分的页面代码,不知各位有没有想到如何通过 xpath 定位这一组专家的名称呢?

from selenium import webdriver

# 设置无头浏览器
option = webdriver.ChromeOptions()
option.add_argument('--headless')

driver = webdriver.Chrome(options=option)
driver.get('https://blog.csdn.net/')

p_list = driver.find_elements_by_xpath("//p[@class='name']")
name = [p.text for p in p_list]
name

切换操作

窗口切换

selenium 操作页面的时候,可能会因为点击某个链接而跳转到一个新的页面(打开了一个新标签页),这时候 selenium 实际还是处于上一个页面的,需要我们进行切换才能够定位最新页面上的元素。

窗口切换需要使用 switch_to.windows() 方法。

首先我们先看看下面的代码。

代码流程:先进入 【CSDN首页】,保存当前页面的句柄,然后再点击左侧 【CSDN官方博客】跳转进入新的标签页,再次保存页面的句柄,我们验证一下 selenium 会不会自动定位到新打开的窗口。

from selenium import webdriver

handles = []
driver = webdriver.Chrome()
driver.get('https://blog.csdn.net/')
# 设置隐式等待
driver.implicitly_wait(3)
# 获取当前窗口的句柄
handles.append(driver.current_window_handle)
# 点击 python,进入分类页面
driver.find_element_by_xpath('//\*[@id="mainContent"]/aside/div[1]/div').click()
# 获取当前窗口的句柄
handles.append(driver.current_window_handle)

print(handles)
# 获取当前所有窗口的句柄
print(driver.window_handles)

在这里插入图片描述
可以看到第一个列表 handle 是相同的,说明 selenium 实际操作的还是 CSDN首页 ,并未切换到新页面。
下面使用 switch_to.windows() 进行切换。

from selenium import webdriver

handles = []
driver = webdriver.Chrome()
driver.get('https://blog.csdn.net/')
# 设置隐式等待
driver.implicitly_wait(3)
# 获取当前窗口的句柄
handles.append(driver.current_window_handle)
# 点击 python,进入分类页面
driver.find_element_by_xpath('//\*[@id="mainContent"]/aside/div[1]/div').click()
# 切换窗口
driver.switch_to.window(driver.window_handles[-1])
# 获取当前窗口的句柄
handles.append(driver.current_window_handle)

print(handles)
print(driver.window_handles)

在这里插入图片描述
上面代码在点击跳转后,使用 switch_to 切换窗口,window_handles 返回的 handle 列表是按照页面出现时间进行排序的,最新打开的页面肯定是最后一个,这样用 driver.window_handles[-1] + switch_to 即可跳转到最新打开的页面了。

那如果打开的窗口有多个,如何跳转到之前打开的窗口,如果确实有这个需求,那么打开窗口是就需要记录每一个窗口的 key(别名) 与 value(handle),保存到字典中,后续根据 key 来取 handle

表单切换

很多页面也会用带 frame/iframe 表单嵌套,对于这种内嵌的页面 selenium 是无法直接定位的,需要使用 switch_to.frame() 方法将当前操作的对象切换成 frame/iframe 内嵌的页面。

switch_to.frame() 默认可以用的 idname 属性直接定位,但如果 iframe 没有 idname ,这时就需要使用 xpath 进行定位。下面先写一个包含 iframe 的页面做测试用。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
 div p {
 color: #red;
 animation: change 2s infinite;
 }
 @keyframes change {
 from {
 color: red;
 }
 to {
 color: blue;
 }
 }
 </style>
</head>

<body>
    <div>
        <p>公众号:Python新视野</p>
        <p>CSDN:Dream丶Killer</p>
        <p>微信:python-sun</p>
    </div>
    <iframe src="https://blog.csdn.net/qq\_43965708" width="400" height="200"></iframe>
<!-- <iframe id="CSDN\_info" name="Dream丶Killer" src="https://blog.csdn.net/qq\_43965708" width="400" height="200"></iframe> -->
</body>
</html>

在这里插入图片描述

现在我们定位红框中的 CSDN 按钮,可以跳转到 CSDN 首页。

from selenium import webdriver
from pathlib import Path
文末有福利领取哦~
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

👉**一、Python所有方向的学习路线**

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。![img](https://img-blog.csdnimg.cn/c67c0f87cf9343879a1278dfb067f802.png)

👉**二、Python必备开发工具**

![img](https://img-blog.csdnimg.cn/757ca3f717df4825b7d90a11cad93bc7.png)  
👉**三、Python视频合集**

观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。  
![img](https://img-blog.csdnimg.cn/31066dd7f1d245159f21623d9efafa68.png)

👉 **四、实战案例**

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。**(文末领读者福利)**  
![img](https://img-blog.csdnimg.cn/e78afb3dcb8e4da3bae5b6ffb9c07ec7.png)

👉**五、Python练习题**

检查学习结果。  
![img](https://img-blog.csdnimg.cn/280da06969e54cf180f4904270636b8e.png)

👉**六、面试资料**

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。  
![img](https://img-blog.csdnimg.cn/a9d7c35e6919437a988883d84dcc5e58.png)

![img](https://img-blog.csdnimg.cn/5db8141418d544d3a8e9da4805b1a3f9.png)

👉因篇幅有限,仅展示部分资料,这份完整版的Python全套学习资料已经上传




**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化学习资料的朋友,可以戳这里无偿获取](https://bbs.csdn.net/topics/618317507)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值