Python教程

python爬虫(十六)selenium页面等待

本文主要是介绍python爬虫(十六)selenium页面等待,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Selenium页面等待

Cookie操作
获取所有的cookie
根据cookie的name获取cookie
删除某个cookie
页面等待
selenium并不是为爬虫而生,但是它的所见即所爬可以方便的用来进行爬取数据,加载速度很慢,需要打开页面,加载相应的元素。如果打开网页,内部的元素慢慢进行加载,如果打开网页立即去查找元素,就会报出异常;很多网页是用Ajax加载出来的,如12306,只有选择日期,往返地,点击查询后才能加载出来数据,这就是需要页面等待的两个原因。
之前进行页面等待是用的python内置的,导入time模块,用time.sleep
()进行强制等待,不好的地方,等待时间长了浪费,时间不够页面加载不完全就会报错,不利于系统的优化。
现在的网页越来越多采用了 Ajax 技术,这样程序便不能确定何时某个元素完全加载出来了。如果实际页面等待时间过长导致某个dom元素还没出来,但是你的代码直接使用了这个WebElement,那么就会抛出NullPointer的异常。为了解决这个问题。所以 Selenium 提供了两种等待方式:一种是隐式等待、一种是显式等待。

隐式等待

隐式等待调用driver.implicitly_wait。那么在获取不可用的元素之前,会先等待10秒钟的时间,但是不会完全等待10秒,等页面加载完,定位到标签位置后立即就会执行,如果找不到,最多等待10秒后报出异常。而time模块的等待是必须等待设定的时间。

from selenium import webdriver
import time

driver = webdriver.Edge()
driver.get('https://www.baidu.com/')
# 之前time模块页面等待的方法
time.sleep(1)
driver.find_element_by_id('kw').send_keys('爬虫')

# 隐式等待
# 设定最长等待时间10秒,运行的时候并不会等待10秒,定位到输入框后就会输入数据
driver.implicitly_wait(10)
driver.find_element_by_id('kw').send_keys('爬虫')
# 如果定位的标签不存在,则会等待10秒后报错
driver.find_element_by_id('12sdf21s2d1sd').send_keys('爬虫')

比如人的行为对12306进行操作的时候,需要先输入出发点、目的地、出发时间,再点击查询,用selenium模拟人的行为的时候也会按照这个步骤进行。进入网站之后会有个弹窗,可以定位到弹窗的“确定”或者“叉号”进行操作,正常打开网页会有缓存,出发地和目的地会有之前输入的信息可以直接点击查询,而用selenium打开的话,出发地和目的地为空的,点击查询会提示让输入。
利用点击叉号关闭弹窗
在这里插入图片描述
利用点击确定关闭弹窗
在这里插入图片描述
定位并点击查询按钮。
在这里插入图片描述

显示等待

显示等待是表明某个条件成立后才执行获取元素的操作。也可以在等待的时候指定一个最大的时间,如果超过这个时间那么就抛出一个异常。显示等待应该使用selenium.webdriver.support.excepted_conditions期望的条件和selenium.webdriver.support.ui.WebDriverWait来配合完成
显示等待设置条件和最大范围,一旦满足就不再等待直接往下走,不满足就一直等待,直到时间结束报出错误。

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

driver = webdriver.Edge()
driver.get('https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc')
# 隐式等待,等待页面加载
driver.implicitly_wait(2)

# 处理弹窗
# 找到叉号,点击叉号
# driver.find_element_by_id('gb_closeDefaultWarningWindowDialog_id').click()
# 找到确定,点击确定
driver.find_element_by_id('qd_closeDefaultWarningWindowDialog_id').click()

# 显示等待,需要导入库,需要有条件,条件满足才运行
# 等待出发地的输入,fromStationText出发地的id值
# 等待用户在输入地输入长沙,如果不输入或者输入错误会一直等待
WebDriverWait(driver, 1000).until(
    EC.text_to_be_present_in_element_value((By.ID, 'fromStationText'), '长沙'))
# 等待目的地的输入,toStationText目的地的id值
# 等待用户输入目的地北京,等待时间为1000秒,超过时间就会报错
WebDriverWait(driver, 1000).until(
    EC.text_to_be_present_in_element_value((By.ID, 'toStationText'), '北京'))
# 定位按钮
que_btn = driver.find_element_by_id('query_ticket')
# 点击查询
# que_btn.click()
# 如果碰到案例点击没有反应的话,也可以用js来执行点击
# 把已经定位到的que_btn传递进去,对arguments做点击操作,0代表的是第一个参数que_btn
driver.execute_script('arguments[0].click()', que_btn)
# 显示等待有条件限制,满足条件条件才能执行,
# 用户输入出发地长沙,目的地北京以后,自动点击查询按钮,
# 任何输入错误或者其他值会停留输入界面直到时间结束,进行报错

总结:通过案例学到的内容,​隐式等待和显式等待的实现方法,两者的应用场景;如何用js实现点击操作。
一些其他的等待条件:
presence_of_element_located:某个元素已经加载完毕了。
presence_of_all_elements_located:网页中所有满足条件的元素都加载完毕了。
element_to_be_clickable:某个元素是可以点击了。

更多条件请参考:http://selenium-python.readthedocs.io/waits.html

打开多窗口和切换页面

有时候窗口中有很多子tab页面。这时候肯定是需要进行切换的。selenium提供了一个叫做switch_to_window来进行切换,具体切换到哪个页面,可以从driver.window_handles中找到。

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

driver = webdriver.Edge()
driver.get('https://www.baidu.com/')
time.sleep(2)
# driver.get('https://www.douban.com/')
# 会先打开百度,然后在同一界面替换打开豆瓣
# 用js打开多个窗口,execute_script执行js代码
# 注意单双引号的使用,外层是单引号,内层就要为双引号
driver.execute_script('window.open("https://www.douban.com/")')

# 对两个网页进行操作,默认情况下操作第一个网页

# driver.find_element_by_id('kw').send_keys('python')
# driver.close()  # 进行操作的是第一个网页

# 如果要对第二个网页进行操作,可以进行切换
# 对于人来说视角已经在第二次打开的网页了,但是对于selenium来说还是停留在第一个网页
print('切换前:', driver.current_url)  # 切换前:https://www.baidu.com/
# 把网页选项卡看成列表,-1代表最后一个,在这里也可以用1进行索引
# switch_to_window ,过时的方法也可以用
driver.switch_to.window(driver.window_handles[-1])
print('切换后:', driver.current_url)  # 切换后:https://www.douban.com/
# 此时再用close关闭的就是第二个网页
time.sleep(2)
driver.close()
time.sleep(2)
# 建议close最好不用,关闭网页再重新打开的时候还要先切换
# 把selenium的视角切换到第一个标签再执行打开操作,不然会出错
driver.switch_to.window(driver.window_handles[0])
driver.execute_script('window.open("https://www.douban.com/")')
这篇关于python爬虫(十六)selenium页面等待的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!