一. windows弹出框的处理
1. 真实案例
有时候,我们会在页面中遇到windows弹出框,和页面弹出框不同,windows弹出框不能用F12查看html源码来定位元素,对于这种弹出框应该作何处理呢?
例如:博客园中点击退出按钮,会弹出一个确认是否退出的弹出框,此时按F12是没有作用的
2. 解决办法
1) 确认浏览器弹出框存在
2) 使用switch_to方法切换到windows弹出框,driver.switch_to.alert
3) Alert类提供了一系列的操作方法。利用Alert的方法,选择接受(accept)或者拒绝(dismiss)
-
accept():是
-
dismiss():否
-
text():获取弹出框的内容
总结:
一. 用显性等待,等待alert弹出框出现 alert_is_present()
二. 切换alert switch_to.alert
三. 操作它,选择接受或者拒绝,还可以获取弹出框文本内容
3. 实例
假设python脚本的同级目录下存在一个test_alert.html的文件,代码和效果如下:
#在python脚本的同级目录下有一个test_alert.html文件 <html> <head> <meta charset="utf-8"> <title>html表单作业-2</title> <script type="text/javascript"> function myFunc(){ var username = document.getElementById("username").value; alert("用户名为:" + username); } </script> </head> <body> <form> 用户名:<input type="text" id="username" name="username" /> <br /> 密码:<input type="password" id="passwd" name="passwd" /> <br /> <input type="button" value="登录" onclick="myFunc()" /> <input type="reset" value="重置" /> </form> </body> </html>
点击登录按钮,会弹出一个windows弹出框
现在虽然无法通过F12定位这个弹出框,但可以通过switch_to.alert切换到这个弹出框,再利用Alert类提供的方法,来点击确定按钮
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 import os #确认浏览器弹出框存在 #切换到弹出框 #选择yes或者no, 关闭弹出框 driver = webdriver.Chrome() driver.get(os.getcwd() + "/test_alert.html") driver.maximize_window() #点击登录,让windows弹出框出现 driver.find_element_by_xpath("//input[@value='登录']").click() #等待弹出框出现 WebDriverWait(driver, 10, 0.5).until(EC.alert_is_present()) #切换到弹出框 alert = driver.switch_to.alert #打印弹出框文本内容 print(alert.text) #点击确定,接受弹出框 alert.accept()
python脚本的运行结果也打印了弹出框的文本内容
二. 鼠标操作
由selenium的ActionChains来完成模拟鼠标操作
引入ActionChains类
from selenium.webdriver.common.action_chains import ActionChains AC.方法名1().context_click().perform()
主要操作流程:
1. 实例化鼠标类
2. 存储鼠标操作(用列表的形式按先后顺序来存储)
3. perform()来执行鼠标操作
支持的操作如下:
double_click 双击操作
context_click 右键操作
drag_and_drop 拖拽操作。左键按住拖动某一个元素到另外一个区域,然后释放按键
#定位元素的原位置 element = driver.find_element_by_name("source") #定位元素要移动到的目标位置 target = driver.find_element_by_name("target") #执行元素的移动操作 ActionChains(driver).drag_and_drop(element, target).perform()
move_to_element()--鼠标悬停。以后会经常遇到
实例:
比如想让鼠标悬停在百度首页的菜单栏的设置上
代码如下:
from selenium.webdriver.common.action_chains import ActionChains from selenium import webdriver driver = webdriver.Chrome() driver.get("http://www.baidu.com") #定位设置 setting_xpath = "//*[@id='u1']//a[@class='pf']" setting_element = driver.find_element_by_xpath(setting_xpath) #鼠标悬浮 #1.实例化鼠标类 2.调用各种鼠标行为 3.调用perfrom()方法去执行鼠标操作 ActionChains(driver).move_to_element(setting_element).perform()
三. 下拉列表操作
观察下拉框页面元素,是select/option还是ul/li
1. 菜单栏—点击其中的某个链接跳转
2. 在下拉列表中选择一个值
思路:
1. 等待下拉列表和下拉列表中值存在
2. 对下拉列表中的元素进行操作
两种方式:
一. 获取所有的下拉列表值,然后用循环取匹配相同的值
二. 通过text的内容来找到下拉列表的某个值
比如现在要去百度首页的设置里,点开设置是个下拉列表,在这个列表中选择高级搜索并点击
注意:高级搜索定位时,需要先点击设置,在高级搜索出现后,再按ctrl + shift + C快捷键来获取高级搜索的定位
方法一:根据文本内容来获取对应的元素
from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains #初始化chromedriver driver = webdriver.Chrome() #隐性等待30s driver.implicitly_wait(30) #打开百度首页 driver.get("http://www.baidu.com") #窗口最大化 driver.maximize_window() #设置的元素表达式 setting_xpath = "//div[@id='u1']//a[@name='tj_settingicon']" #定位到设置 setting_element = driver.find_element_by_xpath(setting_xpath) #鼠标悬浮 ActionChains(driver).move_to_element(setting_element).perform() #选择下拉列表当中高级搜索选项 #1.等待下拉列表,你要选择的元素在页面可见 #2.再去下拉列表当中选择它 advance_search_xpath = "//div[@class='bdpfmenu']//a[text()='高级搜索']" driver.find_element_by_xpath(advance_search_xpath).click()
方法二:获取整个下拉列表中的所有元素,然后再去选择一个
from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains #初始化chromedriver driver = webdriver.Chrome() #隐性等待30s driver.implicitly_wait(30) #打开百度首页 driver.get("http://www.baidu.com") #窗口最大化 driver.maximize_window() #设置的元素表达式 setting_xpath = "//div[@id='u1']//a[@name='tj_settingicon']" #定位到设置 setting_element = driver.find_element_by_xpath(setting_xpath) #鼠标悬浮 ActionChains(driver).move_to_element(setting_element).perform() #获得设置里所有的列表元素对象 all_element = driver.find_elements_by_xpath("//div[@class='bdnuarrow']//following-sibling::a") #对于元素对象列表,如果其元素对象的文本内容是高级搜索,则点击它 for i in all_element: if i.text == "高级搜索": i.click()
Select类—下拉框操作
selenium提供了Select类来处理select/option
引入类:
from selenium.webdriver.support.ui import Select
选择下拉列表值:
1. 通过下标选择:select_by_index(index) 从0开始
2. 通过value属性:select_by_value(value值)
3. 通过文本内容:select_by_visible_text(文本内容)
实例:打开百度首页——设置——高级搜索,并在文档格式里选择其中三项
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 from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.support.ui import Select import time #初始化chromedriver driver = webdriver.Chrome() #打开百度首页 driver.get("http://www.baidu.com") #窗口最大化 driver.maximize_window() #百度首页设置的元素表达式 setting_xpath = "//div[@id='u1']//a[@name='tj_settingicon']" #设置显性等待,等待设置可见 WebDriverWait(driver, 3, 0.3).until(EC.visibility_of_element_located((By.XPATH, setting_xpath))) #定位到设置 setting_element = driver.find_element_by_xpath(setting_xpath) #鼠标悬浮 ActionChains(driver).move_to_element(setting_element).perform() #高级搜索的元素表达式 advance_serach_xpath = "//a[text()='高级搜索']" #设置显性等待,等待高级搜索可见 WebDriverWait(driver, 3, 0.3).until(EC.visibility_of_element_located((By.XPATH, advance_serach_xpath))) #定位到高级搜索并点击 driver.find_element_by_xpath(advance_serach_xpath).click() #select下拉框的元素表达式 select_name = "ft" #设置显性等待,等待select下拉框可见 WebDriverWait(driver, 3, 0.3).until(EC.visibility_of_element_located((By.NAME, select_name))) #定位到select下拉框 select_element = driver.find_element_by_name(select_name) #通过下标选择:选择下标为2的选项——微软 Word (.doc) Select(select_element).select_by_index(2) #等待2s time.sleep(2) #通过value属性选择:选择value值为“rtf”的选项——RTF 文件 (.rtf) Select(select_element).select_by_value("rtf") #等待2s time.sleep(2) #通过文本内容选择:选择文本内容为所有格式的选项 Select(select_element).select_by_visible_text("所有格式") #等待3s time.sleep(3) #断开连接 driver.quit()
四. 窗口切换
在页面中点击某个链接之后,就会打开一个新的窗口
如何切换到新窗口?
若新窗口操作之后,需要切换回原来的窗口?
1. 获取当前所有的窗口
windows = diver.window_handles
2. 切换到指定的窗口
注意:switch_to.window()和switch_to_window()都可以,但后者将淘汰,建议用前者
chrome.switch_to.window(windows[-1]) #最新打开的窗口
3. 切回原来的窗口
chrome.switch_to.window(windows[0]) #切换到第一个窗口
4. 获取当前窗口的句柄
chrome.current_window_handle
实例
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 #初始化chromedriver driver = webdriver.Chrome() #隐性等待30s driver.implicitly_wait(30) #打开百度首页 driver.get("http://www.baidu.com") #窗口最大化 driver.maximize_window() #定位到输入框,并输入内容selenium driver.find_element_by_id("kw").send_keys("selenium") #定位到百度一下按钮并点击 driver.find_element_by_id("su").click() #获取当前浏览器打开的所有窗口 handlers = driver.window_handles #打印当前浏览器打开的窗口数 print(len(handlers)) #定位selenium官网链接 selenium_officer_xpath = "//a[contains(text(), 'Web Browser Automation')]" driver.find_element_by_xpath(selenium_officer_xpath).click() #等待新的窗口出现 WebDriverWait(driver, 30, 1).until(EC.new_window_is_opened(handlers)) #获取到当前浏览器打开的所有窗口 handlers = driver.window_handles #打印当前浏览器打开的窗口数 print(len(handlers)) #切换到新的窗口,进行新页面的操作 driver.switch_to.window(handlers[-1]) #定位到Projects并点击 driver.find_element_by_xpath("//li[@id='menu_projects']//a").click() #切换回原来的窗口 driver.switch_to.window(handlers[0]) #获取当前窗口的句柄并打印 current_handler = driver.current_window_handle print(current_handler)
五. 上传操作
有两种情况:
1. 如果是input,可以直接输入路径的,那么直接调send_keys输入路径
2. 非input标签的上传,则需要借助第三方工具
2.1 AutoIt 我们去调用其生成的au3或exe文件(需要了解)
2.2 SendKeys第三方库(目前只支持到2.7版本) 网址:https://pypi.org/project/SendKeys
2.3 Python pywin32库,识别对话框句柄,进而操作
工具:
pywin32和spy++
下载安装:
pywin32
下载地址:https://sourceforge.net/projects/pywin32
安装方法:https://jingyan.baidu.com/article/bad08e1ed173d409c85121f8.html
WinSpy
下载地址:https://sourceforge.net/projects/winspyex
安装方法:下载为压缩包,解压后即可
例:百度网盘—上传窗口,利用winSpy可以看到从顶层到文件路径输入区域总共有4层
上传操作代码:
#以chrome浏览器为例
import win32gui import win32con dialog = win32gui.FindWindow("#32770", "打开") #一级窗口 #找到窗口 ComboBoxEx32 = win32gui.FindWindowEx(dialog, 0, "ComboBoxEx32", None) #二级
button = win32gui.FindWindowEx(dialog, 0, "Button", None) #二级
comboBox = win32gui.FindWindowEx(ComboBoxEx32, 0, "ComboBox", None) #三级 edit = win32gui.FindWindowEx(comboBox, 0, "Edit", None) #四级 #操作 win32gui.SendMessage(edit, win32con.WM_SETTEXT, None, "D:\apk.txt") #发送文件路径 win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1, button) #点击打开按钮
详细说明:
win32gui.FindWindow(IpClassName, IpWindowName)
自顶层窗口开始寻找匹配条件的窗口,并返回这个窗口的句柄
IpClassName:类名,在Spy++里能够看到
IpWindowName:窗口名,标题栏上能看到的名字
win32gui.FindWindowEx(hwndParent=0, hwndChildAfter=0, IpszClass=None, IpszWindow=None)
搜索类名和窗体名匹配的窗体,并返回这个窗体的句柄。找不到就返回0
hwndParent:若不为0,则搜索句柄为hwndParent窗体的子窗体
hwndChildAfter:若不为0,则按照z-index的顺序从hwndChildAfter向后开始搜索子窗体,否则从第一个子窗体开始搜索
IpClassName:字符型,是窗体的类名,这个可以在Spy++里找到
IpWindowName:字符型,是窗口名,也就是标题栏你能看到的那个标题
win32gui.SendMessage(hWnd, Msg, wParam, IParam)
hWnd:整型,接收消息的窗体句柄
Msg:整型,要发送的消息,这些消息都是windows预先定义好的
wParam:整型,消息的wParam参数
IParam:整型,消息的Param参数
WinSpy图解:
一级窗口
一级窗口下的子窗口,可以看到有打开按钮,还有ComboBoxEx32
二级窗口ComboBoxEx32
二级窗口打开(&0)
三级窗口ComboBox
四级窗口Edit,它是没有Text的
代码运行后,上传成功:
注意:需要上传的文件不能为空文件,否则会上传失败