学习笔记- Selenium[səˈliːniəm] -WebDriver API
笔记目录:https://blog.csdn.net/weixin_42717928/article/details/114343085
昨天下了雨,今天刮了风,明天太阳就出来了
一:元素等待
WebDriver提供了显式和隐式等待。
(1)显式等待:等条件成立则执行,达到最大等待时间抛出超时异常(TimeoutException)
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
# 通过as关键字将expected_conditions重命名为EC
from selenium.webdriver.support import expected_conditions as EC
# WebDriverWait:浏览器驱动、最长超时时间(s)、检测时间间隔(默认0.5s)、超时异常(默认None)
# until:直到返回值为True、until_not:直到返回值为False
element = WebDriverWait(driver, 5, 0.5).until(
# 判断元素是否存在
EC.visibility_of_element_located((By.ID, "kw"))
)
(2)is_displayed
# 也可以通过is_displayed()方法自己实现元素等待
from time import ctime
print(ctime())
for i in range(5):
try:
el = driver.find_element(By.ID, "bcz")
if el.is_displayed():
break
except:
pass
(3)隐式等待
# 不影响脚本执行速度,它会等待页面上的全部元素,当元素存在,继续执行,如果定位不到元素,则轮询,直到10秒后没有定位到则抛出异常
driver.implicitly_wait(10)
二:定位一组元素
和前面元素定位的区别是多了个s
driver.find_elements()
driver.find_elements_by_XX()
# 定位一组元素
texts = driver.find_elements_by_name("ka")
# 计算匹配的个数
print(len(texts))
# 循环遍历
for t in texts:
pass
三:多表单切换
WebDriver只能在一个页面上对元素识别和定位,无法直接定位frame/iframe表单内嵌页面上的元素。可以使用switch_to.frame()将当前定位的主体切换为frame/iframe表单的内嵌页面
# id中x-URS-iframe后的数字是随机的,可以通过^=匹配id属性以x-URS-iframe开头的元素
login_frame = driver.find_element_by_css_selector('iframe[id^="x-URS-iframe"]')
# 可以直接对表单的id或者name属性传参
driver.switch_to.frame(login_frame)
driver.find_element_by_name("email").send_keys("username")
# 回到最外层页面
driver.switch_to.default_content()
四:多窗口切换
在页面点击,有时候会打开新的窗口。可以使用switch_to.window()方法实现不同窗口间的切换。
# 获得搜索窗口句柄
search_windows = driver.current_window_handle
driver.find_element_by_link_text("登录").click()
time.sleep(2)
driver.find_element_by_link_text("立即注册").click()
# 获得当前所有打开的窗口句柄
all_handles = driver.window_handles
# 进入注册窗口
for handle in all_handles:
if handle != search_windows:
driver.switch_to.window(handle)
print(driver.title)
time.sleep(2)
driver.find_element_by_name("userName").send_keys("userName")
time.sleep(2)
# 关闭当前窗口
driver.close()
# 切换到搜索窗口
driver.switch_to.window(search_windows)
五:警告框处理
可以使用switch_to.alert()方法定位,然后使用accept等方法操作
driver.find_element_by_id("s-usersetting-top").click()
driver.find_element_by_link_text("搜索设置").click()
time.sleep(2)
driver.find_element_by_class_name("prefpanelgo").click()
# 获得当前页面上的警告框
alert = driver.switch_to.alert
# 获取警告框的提示信息
alert_text = alert.text
# 点击接受操作
alert.accept()
# 解散现有的警告框
alert.dismiss()
备注:在这里我在第一个点击操作下面给了sleep操作,会导致元素找不到
六:下拉框操作
WebDriver提供了Select类来处理下拉框,用于定位
from selenium.webdriver.support.select import Select
sel = driver.find_element_by_xpath("//select[@id='nr']")
# 通过value值定位
Select(sel).select_by_value('20')
# 通过text值定位
七:上传文件
WebDriver没有提供用于上传的方法,也无法操作Windows控件
(1)普通上传:将本地文件路径作为一个值放在input标签中,通过from表单将这个值交给服务器
# 如果能找到上传文件的控件
import os
file_path = os.path.abspath('./files/')
upload_page = 'file:///'+file_path+'\\upfile.html'
# 定位上传按钮,添加本地文件
driver.find_element_by_id("file").send_keys(file_path+'\\test.txt')
# 备注:测试文件upfile.html和上传的文件位于当前程序同目录的files/目录下
(2)插件上传
使用AutoIt即可
八:下载文件
WebDriver允许我们设置默认的文件下载路径,文件会自动下载并且存放到设置的目录中,不同浏览器设置方式不同。
火狐浏览器下载:
fp = webdriver.FirefoxProfile()
# 设置为0,表示文件会下载到浏览器默认的下载路径
# 设置为2,表示文件会下载到指定目录
fp.set_preference("browser.download.folderList", 2)
# 指定下载文件的目录,这里通过os.getcwd()获取当前文件所在位置作为下载文件保存的目录
fp.set_preference("browser.download.dir", os.getcwd())
# 指定下载文件类型,这里指定二进制文件,其他参考:http://tool.oschina.net/commons
fp.set_preference("browser.helperApps.neverAsk.saveToDisk", "binary/octed-stream")
# 将设置传给浏览器
driver = webdriver.Firefox(firefox_profile=fp)
driver.get("http://pypi.org/project/selenium/#files")
time.sleep(10)
driver.find_element_by_link_text("selenium-3.141.0.tar.gz").click()
备注:测试使用
driver.get("http://www.sxcce.com/lxwm/xjxz/")
driver.find_element(By.CSS_SELECTOR, "div.download>ul>li:nth-child(1)>a").click()
点击下载弹出这个弹窗,然后就没下载了,后续看看怎么处理
谷歌浏览器下载:
# Chrome浏览器在下载时默认不会弹出下载窗口
options = webdriver.ChromeOptions()
# 设置为0,表示禁止弹出下载窗口
prefs = {'profile.default_content_settings.popups': 0,
'download.default_directory': os.getcwd()}
options.add_experimental_option('prefs', prefs)
driver = webdriver.Chrome(chrome_options=options)
driver.get("http://pypi.org/project/selenium/#files")
time.sleep(10)
driver.find_element_by_link_text("selenium-3.141.0.tar.gz").click()
九:操作Cookie
# 获得所有Cookie信息(字典形式存储)
cookie = driver.get_cookies()
# 添加Cookie信息
driver.add_cookie({'name': 'haha', 'value': 'hehe'})
# 删除指定的Cookie(name值)
driver.delete_cookie('haha')
# 删除浏览器中所有Cookies
driver.delete_all_cookies()
# 遍历指定的Cookies
for cookie in driver.get_cookies():
print("%s -> %s" % (cookie['name'], cookie['value']))
十:调用JavaScript
有些页面操作不能靠WebDriver提供的API实现,如浏览器滚动条拖动,这时候可以使用JavaScript脚本,WebDriver提供了execute_script()来调用JavaScript代码。
(1)调整浏览器滚动条位置
# 设置水平左边距、垂直上边距
js = "window.scrollTo(100,450)"
driver.execute_script(js)
(2)在文本框中输入信息
# 在textarea文本框输入内容
# 可以通过id定位元素,但无法通过send_keys()在文本框中输入文本
text = "input text"
js = "document.getElementById('id').value='" + text + "';"
driver.execute_script(js)
十一:处理HTML5视频播放
try:
driver = webdriver.Chrome()
driver.get("http://videojs.com/")
video = driver.find_element(By.ID, "vjs_video_3_html5_api")
# 播放文件地址(如果未设置音频/视频,返回空字符串)
url = driver.execute_script("return arguments[0].currentSrc;", video)
print(url)
# 播放视频
print("start")
driver.execute_script("return arguments[0].play()", video)
# 播放5s
sleep(5)
# 暂停播放
print("stop")
driver.execute_script("return arguments[0].pause()", video)
# 暂停5s
sleep(5)
except BaseException as msg:
print(msg)
finally:
driver.quit()
# 控制视频加载
# load()
在火狐运行报错:Message: NotAllowedError: The play method is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.,意思是在当前上下文中,用户代理或平台不允许播放方法,可能是因为用户拒绝了权限。
在谷歌运行报错:Message: javascript error: play() failed because the user didn't interact with the document first.,原因和上面一样:Chrome的autoplay政策在2018年4月做了更改,在页面没有产生用户交互时时不能进行自动播放的
有缘用到再看下怎么解决
十二:滑动解锁
(1)在火狐浏览器运行没问题,但在谷歌运行就一直无法到达解锁的那个状态,后续看看怎么解决
driver = webdriver.Chrome()
driver.maximize_window()
driver.get("https://www.jq22.com/yanshi17192")
hd = driver.find_element(By.ID, "iframe")
driver.switch_to.frame(hd)
sleep(2)
# 定位滑动块
slider = driver.find_element(By.CSS_SELECTOR, ".inner")
# 调用ActionChains类,把浏览器驱动作为参数传入
action = ActionChains(driver)
# 单击并按下鼠标左键,执行
action.click_and_hold(slider).perform()
for index in range(200):
try:
# 移动鼠标(X轴坐标,Y轴坐标)
action.move_by_offset(20, 0).perform()
except UnexpectedAlertPresentException:
break
# 重置action
action.reset_actions()
sleep(0.1)
(2)滑动选择日历
ActionChains类可以实现,TouchActions类也可以
这段代码滑动有点问题,后续再看看
driver = webdriver.Chrome()
driver.maximize_window()
driver.get("https://www.jq22.com/yanshi4976")
sleep(2)
driver.switch_to.frame("iframe")
driver.find_element(By.ID, "appDate").click()
# 定位要滑动的年月日
# 这里我报了个错:'WebElement' object does not support indexing,原因是我find_element少了个s
dwwos = driver.find_elements(By.CLASS_NAME, "dwwo")
year = dwwos[0]
mouth = dwwos[1]
day = dwwos[2]
action = webdriver.TouchActions(driver)
# scroll_from_element:滑动元素、X轴坐标距离、Y轴坐标距离
action.scroll_from_element(year, 0, 2).perform()
action.scroll_from_element(mouth, 0, 2).perform()
action.scroll_from_element(day, 0, 2).perform()
十三:窗口截图
WebDriver提供了截图函数save_screenshot()用来截取当前窗口
# 指定截图保存位置
driver.save_screenshot("./img/cs.png")
十四:关闭窗口
# 退出相关的驱动程序和关闭所有窗口
quit()
# 关闭当前窗口
close()