python模块详解 | selenium
关于Selenium
Selenium是⼀个⽤于测试⽹站的⾃动化测试⼯具,⽀持各种浏览器包括Chrome、Firefox、Safari等主流界⾯浏览器,同时也⽀持phantomJS⽆界⾯浏览器。另外,selenium用来爬虫也是杠杠的,可以应对大多数的反爬。
配置selenium环境
-
安装Selenium -
pip install selenium
-
配置chromedriver
Selenium3.x调⽤浏览器必须有⼀个webdriver驱动⽂件
驱动下载 👉 selenium各浏览器驱动下载地址
- Windows - 将下载的exe驱动文件,移动到python安装目录下的Scripts文件夹下
- MacOS - 打开「访达」按下快捷键shift+command+G(或前往文件夹),输入
open /usr/local/bin
回车。在新打开的文件夹中,把浏览器驱动复制进去即可
更多配置方法 👉 参考浏览器驱动环境配置
⼊门参考⽂献 👉 Selenium⼊门
IE环境配置 👉 http://t.zoukankan.com/ppppying-p-6143658.html
配置浏览器参数
options = webdriver.ChromeOptions()
driver = webdriver.Chrome(options=options)
-
静默模式 -
options.add_argument('--headless')
-
忽略提示语 -
options.add_argument('disable-infobars')
-
谷歌文档提到需要加上这个属性来规避bug -
options.add_argument('--disable-gpu')
-
隐藏滚动条 -
options.add_argument('--disable-gpu')
-
解决DevToolsActivePort文件不存在的报错 -
options.add_argument('--no-sandbox')
-
指定浏览器分辨率 -
options.add_argument('window-size=1600x900')
-
开启管理者模式
options.add_experimental_option('excludeSwitches', ['enable-automation'])
-
不加载图片
options.add_argument('blink-settings=imagesEnabled=false')
-
禁止图片和css加载
prefs = {"profile.managed_default_content_settings.images": 2, 'permissions.default.stylesheet': 2} options.add_experimental_option("prefs", prefs)
-
指定下载文件目录
save_path = "C:\" prefs = {"download.default_directory": save_path} option.add_experimental_option("prefs", prefs)
-
允许多文件下载弹窗
prefs = {"download.prompt_for_download": False} option.add_experimental_option("prefs", prefs)
-
禁止弹出“您的连接不是私密连接”
options.add_argument('ignore-certificate-errors')
-
设置代理
from selenium import webdriver proxy = "https://127.0.0.1:8080" options = webdriver.ChromeOptions() options.add_argument(f"--proxy-server={proxy}") driver = webdriver.Chrome(options=options) driver.get("")
-
使用用户配置文件
options.add_argument('--user-data-dir=/Users/billie/Library/Application Support/Google/Chrome/default')
定位元素
8种常规定位方法:id,name,class_name,tag_name,link_text,partial_link_text,xpath,css_selector
参考官网 👉 selenium元素定位
定位⼀个元素 | 定位多个元素(返回一个列表) | 含义 |
---|---|---|
find_element_by_id | find_elements_by_id | id |
find_element_by_name | find_elements_by_name | name |
find_element_by_xpath | find_elements_by_xpath | xpath表达式 |
find_element_by_link_text | find_elements_by_link_text | 完整超链接文本 |
find_element_by_partial_link_text | find_elements_by_partial_link_text | 部分超链接文本 |
find_element_by_tag_name | find_elements_by_tag_name | 标签名 |
find_element_by_class_name | find_elements_by_class_name | 类名 |
find_element_by_css_selector | find_elements_by_css_selector | css选择器 |
ps:除了上面的公共方法,也有两个在页面对象定位器的私有方法: find_element、find_elements
-
xpath定位的N种写法
- driver.find_element_by_xpath("//*[@id=‘kw’]")
- driver.find_element_by_xpath("//*[@name=‘wd’]")
- driver.find_element_by_xpath("//input[@class=’s_ipt’]")
- driver.find_element_by_xpath("/html/body/form/span/input")
- driver.find_element_by_xpath("//span[@class=‘soutu-btn’]/input")
- driver.find_element_by_xpath("//form[@id=‘form’]/span/input")
- driver.find_element_by_xpath("//input[@id=‘kw’ and @name=‘wd’]")
-
css定位的N种写法
- driver.find_element_by_css_selector("#kw")
- driver.find_element_by_css_selector("[name=wd]")
- driver.find_element_by_css_selector(".s_ipt")
- driver.find_element_by_css_selector(“html > body > form > span > input”)
- driver.find_element_by_css_selector(“span.soutu-btn> input#kw”)
- driver.find_element_by_css_selector(“form#form > span > input”)
-
link_text定位的写法(实例)
假如⻚⾯上有⼀组⽂本链接(link_text)
<a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻</a> <a class="mnav" href="http://www.hao123.com" name="tj_trhao123">hao123</a>
通过link_text定位:
- driver.find_element_by_link_text(“新闻”)
- driver.find_element_by_link_text(“hao123”)
通过partial_link_text定位:
- driver.find_element_by_partial_link_text(“新”)
- driver.find_element_by_partial_link_text(“hao”)
- driver.find_element_by_partial_link_text(“123”)
元素操作
- size # 获取元素的尺寸,返回一个字典:{‘x’: 000, ‘y’: 000}
- text # 获取元素的文本
- location # 获取元素坐标,先找到要获取的元素,再调用该方法,返回一个字典:{‘height’: 000, ‘width’: 000}
- tag_name # 返回元素的tagName
- clear() # 清除元素的内容
- send_keys() # 模拟按键输入
- click() # 点击元素
- submit() # 提交表单
- get_attribute(name) # 获取属性值
- is_displayed() # 设置该元素是否可见
- is_enabled() # 判断元素是否被使用
- is_selected() # 判断元素是否被选中
ps:如果需要输入中文,防止编码错误使用send_keys(u"中文用户名")。
浏览器操作
- title # 返回页面标题
- page_source # 返回页面源码
- current_url # 获取当前页面的URL
- refresh() # 刷新浏览器
- set_window_size() # 设置浏览器的大小
- set_window_position() # 设置浏览器的坐标
- set_window_rect() # 设置浏览器的矢量
- maximize_window() # 最大化窗口
- minimize_window() # 最小化窗口
- close() # 关闭页面
- quit() # 关闭窗口
鼠标事件
-
ActionChains(driver) # 构造ActionChains对象
-
click(on_element) # 左击
-
context_click(on_element) # 右键,另存为等行为
-
double_click(on_element) # 左键双击,地图web可实现放大功能
-
drag_and_drop(source,target) # 左键拖动,源元素按下左键移动至目标元素释放
-
drag_and_drop_by_offset(source, xoffset, yoffset) # 拖拽到某个坐标然后松开
-
key_down(value, element=None) # 按下某个键盘上的键
-
key_up(value, element=None) # 松开某个键
-
move_by_offset(xoffset, yoffset) # 鼠标从当前位置移动到某个坐标
-
move_to_element(on_element) # 鼠标悬停
-
move_to_element_with_offset(to_element, xoffset, yoffset) # 移动到距某个元素(左上角坐标)多少距离的位置
-
click_and_hold(on_element) #左键点击不松开
-
perform() # 在通过调用该函数执行ActionChains中存储行为
-
例:
from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains #引⼊ ActionChains 类 driver = webdriver.Firefox() driver.get("https://www.baidu.com") element= driver.find_element_by_link_text("设置") #定位元素 ActionChains(driver).move_to_element(element).perform() #对定位到的元素执⾏⿏标悬停操作
键盘事件
参考:http://selenium-python.readthedocs.org/api.html
提供键盘按键操作的类:webdriver.common.keys
from selenium.webdriver.common.keys import Keys
- send_keys(Keys.ENTER) # 按下回车键
- send_keys(Keys.TAB) # 按下Tab制表键
- send_keys(Keys.SPACE) # 按下空格键space
- send_keys(Kyes.ESCAPE) # 按下回退键Esc
- send_keys(Keys.BACK_SPACE) # 按下删除键BackSpace
- send_keys(Keys.SHIFT) # 按下shift键
- send_keys(Keys.CONTROL) # 按下Ctrl键
- send_keys(Keys.ARROW_DOWN) # 按下鼠标光标向下按键
- send_keys(Keys.CONTROL,‘a’) # 组合键全选Ctrl+A
- send_keys(Keys.CONTROL,‘c’) # 组合键复制Ctrl+C
- send_keys(Keys.CONTROL,‘x’) # 组合键剪切Ctrl+X
- send_keys(Keys.F1…Fn) # 键盘 F1…Fn
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()
driver.get('XXXX')
ele = driver.find_element_by.......
ele.send_keys(Keys.ENTER)
设置元素等待
-
隐式等待
driver.implicity_wait(10)
为浏览器对象设定一个等待时间,得不到某个元素就等待一段时间
-
显式等待
ele = WebDriverWait(driver, timeout).until(method,message)
明确地等到某个元素出现或某个元素的可点击等条件,等不到,就一直等,在规定的时间内没有找到,则抛出异常
#显式等待 from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC #显式等待的函数 def explicit_wait(driver, way, path): try: ele = WebDriverWait(driver, 150).until( EC.presence_of_element_located((way, path)), message='' ) return ele except Exception as e: print('元素寻找失败: ' + str(e)) return False ele = explicit_wait(driver, By.XPATH, '//div[@class="pagination_index"]')#显式等待在DOM中找到目标元素
until()
方法de源码def until(self, method, message=''): """Calls the method provided with the driver as an argument until the \ return value is not False.""" screen = None stacktrace = None end_time = time.time() + self._timeout while True: try: value = method(self._driver) if value: return value except self._ignored_exceptions as exc: screen = getattr(exc, 'screen', None) stacktrace = getattr(exc, 'stacktrace', None) time.sleep(self._poll) if time.time() > end_time: break raise TimeoutException(message, screen, stacktrace)
EC
title_is
- 判断当前页面的title是否完全等于(==)预期字符串,返回布尔值title_contains
- 判断当前页面的title是否包含预期字符串,返回布尔值presence_of_element_located
- 判断某个元素是否被加到了dom树里,并不代表该元素一定可见visibility_of_element_located
- 判断某个元素是否可见. 可见代表元素非隐藏,并且元素的宽和高都不等于0visibility_of
- 跟上面的方法做一样的事情,只是上面的方法要传入locator,这个方法直接传定位到的element就好了presence_of_all_elements_located
- 判断是否至少有1个元素存在于dom树中。举个例子,如果页面上有n个元素的class都是‘column-md-3‘,那么只要有1个元素存在,这个方法就返回Truetext_to_be_present_in_element
- 判断某个元素中的text是否 包含 了预期的字符串text_to_be_present_in_element_value
- 判断某个元素中的value属性是否 包含 了预期的字符串frame_to_be_available_and_switch_to_it
- 判断该frame是否可以switch进去,如果可以的话,返回True并且switch进去,否则返回Falseinvisibility_of_element_located
- 判断某个元素中是否不存在于dom树或不可见element_to_be_clickable
- 判断某个元素中是否可见并且是enable的,这样的话才叫clickablestaleness_of
- 等某个元素从dom树中移除,注意,这个方法也是返回True或Falseelement_to_be_selected
- 判断某个元素是否被选中了,一般用在下拉列表element_selection_state_to_be
- 判断某个元素的选中状态是否符合预期element_located_selection_state_to_be
- 跟上面的方法作用一样,只是上面的方法传入定位到的element,而这个方法传入locatoralert_is_present
- 判断页面上是否存在alert
多表单切换
在Web应⽤中经常会遇到frame/iframe
表单嵌套⻚⾯的应⽤,WebDriver只能在⼀个⻚⾯上对元素识别与定位,对于frame/iframe表单内嵌⻚⾯上的元素⽆法直接定位。这时就需要通过switch_to.frame()
⽅法将当前定位的主体切换为frame/iframe表单的内嵌⻚⾯中。
- switch_to.frame() / switch_to_frame()
将当前定位的主体切换为frame/iframe表单的内嵌⻚⾯,默认可以直接取表单的 id 或name属性。如果iframe没有可⽤的id和name属性,则可以通过查找iframe标签,进⾏定位。
- switch_to.default_content() / switch_to_default_content()
跳回最外层的⻚⾯
-
例
# 先通过 xpath 定位到 iframe ele_iframe = driver.find_element_by_xpath('//*[@class="if"]') # 再将定位对象传给 switch_to_frame()方法 driver.switch_to.frame(ele_iframe) driver.switch_to_default_content()
多窗⼝切换
在⻚⾯操作过程中有时候点击某个链接会弹出新的窗⼝,这时就需要主机切换到新打开的窗⼝上进⾏操作。WebDriver提供了switch_to.window()⽅法,可以实现在不同的窗⼝之间切换。
-
current_window_handle #返回当前窗⼝的句柄
-
window_handles #返回所有窗⼝的句柄,一个列表
-
switch_to.window() #⽤于切换到相应的窗⼝,与上⼀节的switch_to.frame()类似,前者⽤于不同窗⼝的切换,后者⽤于不同表单之间的切换
-
例:
c_win = driver.current_window_handle driver.switch_to_window(c_win)
对话框操作
在WebDriver中处理JavaScript所⽣成的alert、confirm以及prompt⼗分简单,具体做法是使⽤ switch_to.alert
或switch_to_alert()
⽅法定位到 alert/confirm/prompt,然后使⽤text/accept/dismiss/send_keys 等⽅法进⾏操作。
-
switch_to_alert() / switch_to.alert # 切入到警告框
-
text # 返回 alert/confirm/prompt 中的⽂字信息
-
accept() # 接受现有警告框
-
dismiss() # 解散现有警告框
-
send_keys(keysToSend) # 发送⽂本⾄警告框。keysToSend:发送⾄警告框的⽂本。
-
例:
al = driver.switch_to_alert() al.accept() al.text
复选框操作
- is_selected() #返回布尔值,判断是否被选中
1、单选框(radio)
2、复选框(checkbox)
3、下拉框(select)
导⼊选择下拉框Select类,使⽤该类处理下拉框操作:
from selenium.webdriver.support.ui import Select
<select>类型的下拉框
- 选择下拉框选项的⽅法
- select_by_value(“选择值”) # 相当于我们使⽤⿏标选择下拉框的值
- select_by_index(“索引值”) # 以传入的index值来查找匹配的元素并选择对应选项(索引从0开始计数)
- select_by_visible_text(“文本”) # 选择所有文本显示的option元素,
- 返回options信息的方法
- options # 返回所有的选项的列表,其中选项都是WebElement元素
- all_selecetd_options # 返回所有被选中的选项的列表,其中选项均为WebElement元素,输出所有被选中的选项,适合于能多选的下拉框
- first_selected_option # 返回第一个被选中的选项
- 取消下拉框选择的方法
- deselect_by_index() #以传入的索引值来查找匹配的元素并取消选择
- deselect_by_value() #以传入的value属性值来查找匹配的元素并取消选择
- deselect_by_visible_text() #以传入的文本内容来查找匹配的元素并取消选择
- deselect_all() #将所有的选项清除
ps:上述方法仅用于多选下拉框,即设置了multiple=“multiple”属性的「select标签」,这种下拉框可以多选。
from selenium.webdriver.support.ui import Select
ele = driver.find_element_by_...
all_options = Select(ele).options
Select(ele).select_by_value('选项A') # 按值xu,无返回值
文件上传
selenium没有提供直接的文件上传功能,目前主要有以下几种解决方案:
- send_keys()
- AutoIT
- python pywin32 模块
1、send_keys()
对于通过input标签实现的上传功能,可以将其看作是⼀个输⼊框,定位到用于上传的input标签,接着通过send_keys()指定本地⽂件路径的⽅式,实现⽂件上传。 例:
from selenium import webdriver
import os
driver = webdriver.Firefox()
file_path = 'file:///' + os.path.abspath('upfile.html')
driver.get(file_path)
# 定位上传按钮,添加本地⽂件
driver.find_element_by_name("file").send_keys('D:\\upload_file.txt')
driver.quit()
2、AutoIT
AutoIT通过操作Windows窗口控件来实现自动化任务。selenium通过AutoIT来操作Windows窗口,实质是通过python代码来调用AutoIT生成的脚本.exe文件,即利用AutoIT编写适合的脚本,然后将脚本编译成可执行文件,在自动化测试实现时,直接调用此脚本实现文件上传。
ps:编写脚本和编译需要借助AutoIT提供的工具,但是脚本编译成可执行文件后,可直接使用,不需要安装AutiIT。
- AutoIT下载:https://www.autoitscript.com/site/
- AutoIT的使用:
- 探测控件(AutoIt Window Info工具)
- 编写脚本(Autoit Window Info编辑器)
- 验证脚本(Autoit Window Info 👉 Tool 👉 go)
- 编译成可执行文件(Compile Script to.exe)
- 调用可执行文件
- 参数化(在python程序中向可执行文件传入参数)
- 多个参数化(实现多文件上传)
3、pywin32
pywin32式用于访问Windows系统API的python模块,最核心的方法是:
- win32api #用python对win32的本地API库进行封装
- win32con #win32的常量定义
- win32gui #
文件下载
文件下载(另存为),跟文件上传类似,可以使用AutoIt、win32api解决
1、win32api
-
例:下载搜狗图片
import win32api,win32con driver.get(sg_url) ActionChains(driver).move_to_element(driver.find_element_by_link_text('图片')).click().perform()#点击跳转到图片 time.sleep(1) ActionChains(driver).move_to_element(driver.find_element_by_xpath('//*[@id="feed_list"]/div[1]/ul/li[1]/a/img')).context_click().perform() win32api.keybd_event(40,0,0,0)#40对应的是向下键,由于’另存为‘在菜单的顺序为7,所以需操作7次 time.sleep(1) win32api.keybd_event(40,0,0,0) time.sleep(1) win32api.keybd_event(40,0,0,0) time.sleep(1) win32api.keybd_event(40,0,0,0) time.sleep(1) win32api.keybd_event(40,0,0,0) time.sleep(1) win32api.keybd_event(40,0,0,0) time.sleep(1) win32api.keybd_event(40,0,0,0) time.sleep(1) win32api.keybd_event(13,0,0,0) time.sleep(1) win32api.keybd_event(13,0,0,0)
cookie操作
有时候我们需要验证浏览器中cookie是否正确,因为基于真实cookie的测试是⽆法通过⽩盒和集成测试进⾏的。WebDriver提供了操作Cookie的相关⽅法,可以读取、添加和删除cookie信息。
WebDriver操作cookie的⽅法:
-
get_cookies() #获得所有cookie信息
-
get_cookie(name) #返回字典的key为“name”的cookie信息
-
add_cookie(cookie_dict) #添加cookie。
“cookie_dict”指字典对象,必须有‘name’和‘value’两个key,可选的key是‘path’,‘domin’,‘secure’,‘expiry’,‘httponly‘
-name:cookie的名称
-value:cookie对应的值,动态生成
-domain:服务器域名
-expiry:cookie有效终止日期
-path:path属性定义了web服务器上哪些路径下的页面可获取服务器设置的cookie-httpOnly:防脚本攻击
-secure:在cookies中标记该变量,表明只有当浏览器和web server之间的通信协议为加密认证协议时
-
delete_cookie(name,optionsString) #删除cookie信息
“name”是要删除的cookie的名称,“optionsString”是该cookie的选项,⽬前⽀持的选项包括“路径”,“域”
-
delete_all_cookies() #删除所有cookie信息
-
例:
from selenium import webdriver
import time
browser = webdriver.Chrome("F:\Chrome\ChromeDriver\chromedriver")
browser.get("http://www.youdao.com")
#1.打印cookie信息
print('=====================================')
print("打印cookie信息为:")
print(browser.get_cookies)
#2.添加cookie信息
dict={'name':"name",'value':'Kaina'}
browser.add_cookie(dict)
print('=====================================')
print('添加cookie信息为:')
#3.遍历打印cookie信息
for cookie in browser.get_cookies():
print('%s----%s\n' %(cookie['name'],cookie['value']))
#4.删除⼀个cookie
browser.delete_cookie('name')
print('=====================================')
print('删除⼀个cookie')
for cookie in browser.get_cookies():
print('%s----%s\n' %(cookie['name'],cookie['value']))
print('=====================================')
print('删除所有cookie后:')
#5.删除所有cookie,⽆需传递参数
browser.delete_all_cookies()
for cookie in browser.get_cookies():
print('%s----%s\n' %(cookie['name'],cookie['value']))
time.sleep(3)
browser.close()
登录操作
在实际的web应用中,用户登录时通常要求用户输入验证码,验证码大多分为四类:识图验证码、计算验证码、滑块验证码以及语音验证码,这里介绍识图验证码。
两种解决方案:
1、通过cookies绕过登录
- 原理:先通过一次手动的登录,登录成功后可以获取到对应的cookies,之后,在下一次的访问中,只需要向driver对象添加cookies,即可绕过登录和验证码过程,直接登录。
- 实例:selenium自动化 | 通过获取cookies登录
- 更多关于cookies的操作:十三、cookie操作
2、借助识别工具识别验证码
百度AI开放平台:http://ai.baidu.com/
- 操作方法简介
- 使用百度账号登录百度AI开放平台,进入控制台,选择文字识别,点击创建应用
- 点击管理应用,获取访问百度服务所需的验证信息AppID、API Key、Secret Key
- 安装使用python SDK:pip install baidu-aip
- 识别过程简介
- 截取当前显式验证码的网页图片
- 裁剪网页图片得到验证码大图
- 调用百度AI平台识别验证码
- 实例:selenium自动化 | 借助百度AI开放平台识别验证码登录职教云
JavaScript操作
虽然WebDriver提供了操作浏览器的前进和后退⽅法,但对于浏览器滚动条并没有提供相应的操作⽅法。在这种情况下,就可以借助JavaScript来控制浏览器的滚动条。
WebDriver提供了此方法执⾏JavaScript代码:
execute_script()
js代码的相关操作:
-
输入操作
document.getElementById(' ').value=' ';
$("id").val("");
-
单击操作
document.getElementById(' ').click();
-
焦点操作
e = driver.find_element_by_id("su")
driver.execute_script("arguments[0].blur();" , e)
# 移除焦点操作driver.execute_script("arguments[0].blur();" , e)
# 赋予焦点操作
-
浏览器操作
window.open(url);
# 打开网页地址return document.documentElement.scrollWidth;
# 获取网页宽度return document.documentElement.scrollHeight;
# 获取网页长度window.resizeTo(width,height);
# 绝对方法,设置浏览器窗口的实际大小,即“变化到多少”window.resizeBy(width,height);
# 相对方法,在当前大小上增加所指定的参数值,即“变化了多少”window.moveTo(width,height);
# 绝对方法,设置窗口新的绝对位置window.moveBy(width,height);
# 相对方法,在当前位置上增加所指定的参数值history.forward();
# 控制浏览器前进history.back();
# 控制浏览器后退history.go(number | url);
- 参数可以是数字number,即要访问的url在history的url列表中的相对位置。(-1表示上一个页面,1表示前进一个页面,0则是刷新页面)
- 参数可以是一个字符串,字符串必须是局部或完整的url,该函数会去匹配包含字符串的第一个url
history.go(0);
,location.reload();
,location=location;
,location.assign(location);
,location.replace(location);
# 刷新浏览器window.close();
# 关闭浏览器
-
鼠标操作
-
创建事件
document.createEvent('MouseEvents');
-
初始化返回的的时间对象
event.initMouseEvent(type,canBuble,cancelable,view,detail,screenX,screenY,clientY,ctrlKey,altKey,metaKey,button,relatedTarget);
- type:click(单击),dbclick(双击),mouseover(鼠标悬停)
-
触发事件
arguments[0].dispatchEvent()
-
例:
e = driver.find_element_by_name("name") js = """ var event = document.createEvent('MouseEvents'); event.initMouseEvent('click',true,true,document.defaultView,0,0,0,0,0,false,false,false,false,0,null); arguments[0].dispatchEvent(event); """ driver.execute_script(js, e)
-
-
滚动条操作
- 水平滚动
document.documentElement.scrollLeft = 100
# scrollLeft的初始值为0,最初显示页面最左边的内容,随数值变大,向右滑动
- 垂直滚动
document.documentElement.scrollTop = 100
# scrollTop的初始值为0,随数值变大,向下滑动
- 滚动到指定坐标
window.scrollTo(x,y)
document.documentElement.scrollTo(x,y)
driver.execute_script("arguments[0].scrollIntoView()", driver.find_element...)
- 滚动到指定的像素数
window.scrollBy(x,y)
document.documentElement.scrollBy(x,y)
- 滚动页面元素到可视区域
documents[0].scrollIntoView()
- 水平滚动
-
HTML视频操作
-
加载
- driver.execute_script(“return arguments[0].load()",video)
-
播放
- driver.execute_script(“return arguments[0].play()",video)
-
暂停
- driver.execute_script(“return arguments[0].pause()",video)
-
例:
driver.get('https://www.w3school.com.cn/tiy/t.asp?f=html_video') driver.switch_to_frame('iframeResult') video=driver.find_element_by_xpath('/html/body/video') video.click() driver.execute_script('return arguments[0].load()',video) driver.execute_script('return arguments[0].play()',video) driver.execute_script('return arguments[0].pause()',video)
-
窗⼝截图
⾃动化⽤例是由程序去执⾏的,因此有时候打印的错误信息并不⼗分明确。如果在脚本执⾏出错的时候能对当前窗⼝截图保存,那么通过图⽚就可以⾮常直观地看出出错的原因。selenium提供了截图函数get_screenshot_as_file()
来截取当前窗⼝:
set_window_size()
- 设置窗口分辨率get_screenshot_as_file()
- 截取当前窗⼝,保存至本地
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('http://www.baidu.com')
# 设置窗口分辨率
width = driver.execute_script("return document.documentElement.scrollWidth")
height = driver.execute_script("return document.documentElement.scrollHeight")
driver.set_window_size(width, height)
# 截取当前窗⼝,并指定截图图⽚的保存位置
driver.get_screenshot_as_file("D:\\baidu_img.jpg")
driver.quit()
下面是一些常见状况的解决方案:
反屏蔽
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'
})
from selenium import webdriver
from selenium.webdriver import ChromeOptions
option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
option.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(options=option)
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'
})
driver.get('https://antispider1.scrape.center/')
页面加载超时
-
方法1:
driver.set_page_load_timeout()
+driver.set_script_timeout()
from selenium import webdriver from selenium.common.exceptions import TimeoutException driver = webdriver.Chrome() driver.set_page_load_timeout(10) # driver.set_script_timeout(10) # try: driver.get('https://static4.scrape.center/') except TimeoutException: driver.execute_script('window.stop()') print('页面加载超时')
-
方法2:配置浏览器参数
from selenium import webdriver from selenium.webdriver.common.desired_capabilities import DesiredCapabilities #get直接返回,不再等待界面加载完成 desired_capabilities = DesiredCapabilities.CHROME desired_capabilities["pageLoadStrategy"] = "none" driver = webdriver.Chrome() driver.get()
填写表单的几种姿势
-
send_keys()
ele = driver.find_element_by_xpath('//*') ele.send_keys('')
-
execute_script()
js = '$("#kssj").val("");' # 将id为kssj的元素设置为空 js = 'document.getElementsByClassName("el-input_inner")[7].value="";' # 通过class name定位元素,设置其值 driver.execute_script(js)
页面元素点击的几种姿势
-
click()
ele = driver.find_element_by_xpath('//*') ele.click()
-
send_keys()
from selenium.webdriver.common.keys import Keys ele = driver.find_element_by_xpath('//*') ele.send_keys(Keys.ENTER)
-
显式等待+
click()
from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.exception import TimeoutException def explicit_waits(driver, xpath, timeout=10): try: return WebDriverWait(driver, timeout).until( EC.presence_of_element_located((By.XPATH, xpath)), message='' ) except TimeoutException as e: print('元素寻找失败:' + repr(e)) return False ele = explicit_waits(driver, '//div[@class="pagination_index"]') ele.click()
-
ActionChains()
from selenium.webdriver.common.action_chains import ActionChains ActionChains(driver) .move_to_element(driver.find_element_by_xpath('//*')) .click() .perform()
-
execute_script()
js = 'document.getElementById("").click();' driver.execute_script(js)
-
execute_script()
+ elejs = 'arguments[0].click();' ele = driver.find_element_... driver.execute_script(js, ele) #
js获取身份验证信息
js = 'return window.localStorage;'
js = 'return window.sessionStorage;'
js = 'return document.cookie;'
控制已打开的浏览器
在使用selenium进行自动化测试中我们有时会遇到这样的情况:
我们需要手动打开浏览器,进入到所需的页面,执行一些手动任务,如输入表单、输入验证码,登陆成功后,然后再开始运行自动化脚本。
这种情况下如何使用selenium来接管先前已打开的浏览器呢?
这里给出Google Chrome浏览器的解决方案。
我们可以利用Chrome DevTools协议。它允许客户检查和调试Chrome浏览器。
(1)步骤1:启动浏览器
-
Windows
chrome_path = 'C:\\Users\\Billie\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe' # chrome.exe所在目录,注:双斜杠 user_data_dir = 'C:\\selenium_ui_auto\\chrome_temp' os.system(f'start {chrome_path} --remote-debugging-port=9222 --user-data-dir="{user_data_dir}"') # 注:双斜杆;start
-
macOS
chrome_path = '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome' user_data_dir = '~/ChromeProfile' os.system(f'{chrome_path} --remote-debugging-port=9222 --user-data-dir="{user_data_dir}";')
cmd命令中的路径存在空格,导致命令出错
-
措施一
在路径前后加上双引号,如
"user_data_dir"
-
措施二
在路径前后加上双引号,以及前面再加上一个双引号,如
start "" "{chrome_path}"
chrome_path = "C:\Program Files\Google\Chrome\Application\chrome.exe" user_data_dir = "C:\Users\police\AppData\Local\Google\Chrome\User Data" os.system(rf'start "" "{chrome_path}" --remote-debugging-port=9222 --user-data-dir="{user_data_dir}"')
-
(2)步骤2:捕获调试浏览器
options = Options()
options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
driver = webdriver.Chrome(options=options) # 如浏览器不存在,则会在约一分钟(或半分钟)等待之后,报错-WebDriverException
⚠️注:如若捕获不到调试浏览器
- 可能原因:「chromedriver.exe进程冲突」
- 解决方案:检查任务管理器中是否有多个chromedriver.exe的进程,全部停止任务,重试即可捕获成功。
⚠️注:如遇到捕获浏览器之后,元素操作(比如点击、输入)失败,而在常规启动的浏览器中没有此问题
- 可能原因:「Chrome的位数与计算机位数不符」。比如64位的计算机,装了32位的Chrome,则会出现上述情况。
- 解决方案:按同位数安装Chrome浏览器。