python selenium

弹出框处理的实现

弹出框有两种:页面弹出框(可定位元素能操作)、Windows弹出框(不能直接定位)

一、页面弹出框

等待弹出框出现之后,定位弹出框,操作其中元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
driver.maximize_window()
#点击百度登录按钮
driver.find_element_by_xpath('//*[@id="u1"]//a[@name="tj_login"]').click()

#等待百度登录弹出框中 要出现的元素可见
ele_id = "TANGRAM__PSP_10__footerULoginBtn"
param = (By.ID,ele_id)
#元素可见时,再进行后续操作
WebDriverWait(driver,10).until(EC.visibility_of_element_located(param))

driver.find_element_by_id(ele_id).click()
time.sleep(5)
driver.quit()

二、Windows弹出框

使用 driver.switch_to.alert 切换到Windows弹出框

Alert类提供了一系列操作方法:

  • accept() 确定
  • dismiss() 取消
  • text() 获取弹出框里面的内容
  • send_keys(keysToSend) 输入字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#1:定位alert弹出框
#点击页面元素,触发alert弹出框
driver.find_element_by_xpath('//*[@id="alert"]').click()
time.sleep(3)
#等待alert弹出框可见
WebDriverWait(driver,20).until(EC.alert_is_present())

#从html页面切换到alert弹框
alert = driver.switch_to.alert
#获取alert的文本内容
print(alert.text)
#接受--选择“确定”
alert.accept()

#2:定位confirm弹出框
driver.find_element_by_xpath('//*[@id="confirm"]').click()
time.sleep(3)
WebDriverWait(driver,20).until(EC.alert_is_present())
alert =driver.switch_to.alert
print(alert.text)
# 接受--选择“取消”
alert.dismiss()


#3:定位prompt弹出框
driver.find_element_by_id("prompt").click()
time.sleep(3)
WebDriverWait(driver,20).until(EC.alert_is_present())
alert =driver.switch_to.alert
alert.send_keys("jaja")
time.sleep(5)
print(alert.text)
# alert.dismiss()
alert.accept()

文件上传

input标签(type=file)

1
driver.find_element('name','file').send_keys('./bq.png')

非input型上传

autoit

AutoIt Windows Info 用于识别Windows控件信息
Compile Script to.exe 用于将AutoIt生成 exe 执行文件
Run Script 用于执行AutoIt脚本
SciTE Script Editor 用于编写AutoIt脚本

1.识别元素,主要是文件名输入框和打开按钮,使用AutoIt Windows Info完成,记录结果如下:
文件名输入框的class 为“Edit”,Instance为“1”
打开按钮的class 为“Button”,Instance为“1”
2.编写脚本,使用SciTE Script Editor,内容如下:

1
2
3
4
5
6
ControlFocus("文件上传", "","Edit1")
WinWait("[CLASS:#32770]","",10)
ControlSetText("文件上传", "", "Edit1","D:bq.jpg")
Sleep(2000)
ControlClick("文件上传", "","Button1");
#注意“文件上传”字样是你点击上传按钮之后弹出的对话框的title

3、验证脚本
保证页面的上传对话框打开,然后运行脚本tools>go
4、打开Compile Script to.exe工具,将其生成为exe可执行文件
5、python脚本中调用

1
2
3
4
up=self.driver.find_element('class name','avatar-uploader-trigger')
up.find_element('class name','ant-btn').click()
os.system('D:\python_workspace\QiangSEAuto\upload.exe')
time.sleep(20)
win32gui

示例网址:http://www.sahitest.com/demo/php/fileUpload.htm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# -*- coding: utf-8 -*-
from selenium import webdriver
import win32gui
import win32con
import time

dr = webdriver.Firefox()
dr.get('http://sahitest.com/demo/php/fileUpload.htm')
upload = dr.find_element_by_id('file')
upload.click()
time.sleep(1)

# win32gui
dialog = win32gui.FindWindow('#32770', u'文件上传') # 对话框
ComboBoxEx32 = win32gui.FindWindowEx(dialog, 0, 'ComboBoxEx32', None)
ComboBox = win32gui.FindWindowEx(ComboBoxEx32, 0, 'ComboBox', None)
Edit = win32gui.FindWindowEx(ComboBox, 0, 'Edit', None) # 上面三句依次寻找对象,直到找到输入框Edit对象的句柄
button = win32gui.FindWindowEx(dialog, 0, 'Button', None) # 确定按钮Button

win32gui.SendMessage(Edit, win32con.WM_SETTEXT, None, 'd:\\baidu.py') # 往输入框输入绝对地址
win32gui.SendMessage(dialog, win32con.WM_COMMAND, 1, button) # 按button

print upload.get_attribute('value')
dr.quit()

需要windows窗口、消息查看分析器:小工具:Spy++,也可以用autoIT自带的工具

相关API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
win32gui.FindWindow(lpClassName=None, lpWindowName=None):
#自顶层窗口开始寻找匹配条件的窗口,并返回这个窗口的句柄。
#lpClassName:类名,在Spy++里能够看到
#lpWindowName:窗口名,标题栏上能看到的名字
#代码示例里我们用来寻找上传窗口,你可以只用其中的一个,用classname定位容易被其他东西干扰,用windowname定位不稳定,不同的上传对话框可能window_name不同,怎么定位取决于你的情况。
win32gui.FindWindowEx(hwndParent=0, hwndChildAfter=0, lpszClass=None, lpszWindow=None)
#搜索类名和窗体名匹配的窗体,并返回这个窗体的句柄。找不到就返回0。
#hwndParent:若不为0,则搜索句柄为hwndParent窗体的子窗体。
#hwndChildAfter:若不为0,则按照z-index的顺序从hwndChildAfter向后开始搜索子窗体,否则从第一个子窗体开始搜索。
#lpClassName:字符型,是窗体的类名,这个可以在Spy++里找到。
#lpWindowName:字符型,是窗口名,也就是标题栏上你能看见的那个标题。
#代码示例里我们用来层层寻找输入框和寻找确定按钮
win32gui.SendMessage(hWnd, Msg, wParam, lParam)
#hWnd:整型,接收消息的窗体句柄
#Msg:整型,要发送的消息,这些消息都是windows预先定义好的,可以参见系统定义消息(System-Defined Messages)
#wParam:整型,消息的wParam参数
#lParam:整型,消息的lParam参数
#代码示例里我们用来向输入框输入文件地址以及点击确定按钮
SendKeys
1
pip install SendKeys 

通过SendKeys库可以直接向焦点里输入信息,不过要注意在打开窗口是略微加一点等待时间,否则容易第一个字母send不进去(或者你可以在地址之前加一个无用字符,不推荐)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# -*- coding: utf-8 -*-
from selenium import webdriver
import win32gui
import win32con
import time

dr = webdriver.Firefox()
dr.get('http://sahitest.com/demo/php/fileUpload.htm')
upload = dr.find_element_by_id('file')
upload.click()
time.sleep(1)

# SendKeys
SendKeys.SendKeys('D:\\baidu.py') # 发送文件地址
SendKeys.SendKeys("{ENTER}") # 发送回车键

print upload.get_attribute('value')
dr.quit()
keybd_event

win32api提供了一个keybd_event()方法模拟按键

多文件

多文件上传就是在文件路径框里用引号括起单个路径,然后用逗号隔开多个路径,例如:“D:\a.txt” “D:\b.txt”
注意:只有多个文件在同一路径下,才能这样用,否则是会失败的

切换iframe

1.有id,并且唯一,直接写id

1
driver.switch_to_frame("x-URS-iframe")

2.有name,并且唯一,直接写name

1
driver.switch_to_frame("xxxx")

3.无id,无name,先定位iframe元素

1
2
3
iframe = driver.find_elements_by_tag_name("iframe")[0]
driver.switch_to_frame(iframe)
driver.switch_to.frame(driver.find_element_by_xpath("//iframe[contains(@src,'myframe')]"))

5.从frame中切回主文档(switch_to.default_content())

1
driver.switch_to.default_content()

6.嵌套frame的操作(switch_to.parent_frame())

1
2
3
4
5
<html>
<iframe id="frame1">
<iframe id="frame2" / >
</iframe>
</html>
1
2
3
4
5
#从主文档切到frame2,一层层切进去
driver.switch_to.frame("frame1")
driver.switch_to.frame("frame2")
#从frame2再切回frame1,这里selenium给我们提供了一个方法能够从子frame切回到父frame,而不用切回主文档再切进来。
driver.switch_to.parent_frame() # 如果当前已是主文档,则无效果