web自动化(2)——浏览器及元素操作
1.浏览器常规操作
1.1 启动关闭
close:关闭当前窗口
quit:退出浏览器
1.2 窗口大小
最大化:maximize_window()
最小化:minimize_window()
设置指定大小:set_window_size(1000,600)
1.3 导航窗口
方法 | 作用 |
get(url) | 跳转到指定页面 |
back() | 返回上个页面 |
forward() | 前进到下一页面 |
refresh() | 刷新当前页面 |
1.4 获取页面信息
属性 | 内容 |
name | 浏览器名字 |
capabilities | 浏览器能力 |
current_url | 当前网址 |
title | 页面title |
page_source | HTML源码 |
current_window_handle | 当前窗口ID |
window_handles | 所有窗口ID |
switch_to | 窗口切换 |
timeouts | 超时时间 |
1.5 页面截图
get_screenshot_as_png 获取二进制内容
get_screenshot_as_file 获取文件
from selenium.webdriver import Chrome
# 启动浏览器
driver = Chrome()
driver.get('http://www.baidu.com') # 访问百度
print(driver.title) # 网页标题
print(driver.capabilities) # 浏览器的信息
print(driver.name) # 浏览器的名字
print(driver.current_url) # 网址url
print(driver.page_source) # 网页HTML
driver.maximize_window() # 最大化
driver.minimize_window() # 最小化
driver.set_window_size(1000, 600) # 设置大小
driver.get_screenshot_as_png() # 获取二进制内容
driver.get_screenshot_as_file('a.png') # 将二进制内容保存文件中
driver.back() # 返回
driver.forward() # 前进
driver.refresh() # 刷新
# # 关闭浏览器
driver.quit()
2. 元素定位
通过WebDriver获取WebElement
2.1 find_element方法
webDriver.find_element ->webElement
2.2 定位策略
定位器 | 描述 |
id | 定位id属性与搜索值匹配的元素 |
name | 定位 name 属性与搜索值匹配的元素 |
tag name | 定位标签名称与搜索值匹配的元素 |
class name | 定位class属性与搜索值匹配的元素 (不允许使用复合类名) |
link text | 定位link text可视文本与搜索值完全匹配的锚元素 |
partial link text | 定位link text可视文本部分与搜索值部分匹配的锚点元素 |
xpath | 定位与XPath 表达式匹配的元素 |
css selector | 定位CSS选择器匹配的元素 |
常用的xpath 和css selector,可以选择任意一个定位方法对元素进行定位。
在浏览器的开发者工具中,选择元素,鼠标定位在元素上,右键选择复制xpath或者css selector
2.3 find_elements方法
find_element方法定位一个元素,返回webelement,定位失败报错
find_elements方法定位多个元素,返回一个列表,列表中存放多个webelement,定位失败返回空列表,不报错
2.4 手写xpath
通过手写xpath,创造可维护性高,可读性好,能够处理复杂逻辑的表达式
2.4.1 xpath语法
字符 | 含义 |
input | 选择所有的input元素 |
* | 选择所有的元素 |
/ | 从当前中选择元素 |
// | 从当前节点及以下节点中选择元素 |
. | 当前节点 |
.. | 父节点 |
@ | 根据属性进行筛选元素 |
[n] | 返回列结果第n项目 |
2.4.2 xpath函数
函数 | 作用 | 示例 |
text | 获取元素内的文本(精确匹配) | //a[text()="新闻"] |
contains | 任意位置包含(模糊匹配) | //a[contains(text(),"o")] |
starts-with | 开头相同(半模糊匹配) | //a[starts-with(text(),"地图")] |
last() | 列表最后一个 | //div[@id="s-top-left"]/a[last()] |
3. 元素操作
3.1 元素基本的操作
- 点击:click()
- 输入:send_keys("123")
- 清空:clear()
from selenium.webdriver import Chrome
from selenium.webdriver.common.by import By
# 启动浏览器
driver = Chrome()
driver.get('http://www.baidu.com')
el = driver.find_element(By.ID, 'kw') # 定位输入框
el.send_keys("123456") # 输入123456
el.clear() # 清空输入框
el.send_keys('654324') # 输入654324
el_1 = driver.find_element(By.XPATH, '//*[@id="su"]') # 通过xpath定位百度一下按钮
el.click() # 点击百度一下按钮
driver.quit() # 关闭浏览器
3.2 键盘鼠标的操作
3.2.1 键盘操作
send_keys() 方法用于输入文本,可以模拟键盘输入字母数字等,但一些特殊的键,例如Enter,Tab等,需要使用selenium提供常量进行表示,首先就是导库,我们可以在源码中看到所有键的表示
from selenium.webdriver.common.keys import Keys
示例代码如下:
from selenium.webdriver import Chrome
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
# 启动浏览器
driver = Chrome()
driver.get('http://www.baidu.com')
driver.find_element(By.ID, 'kw').send_keys('654324') # 输入654324
el_1 = driver.find_element(By.XPATH, '//*[@id="su"]') # 通过xpath定位百度一下按钮
el_1.send_keys(Keys.ENTER) # 方法用于模拟“回车”键
driver.quit() # 关闭浏览器
还有一些特殊场景下,同时按下多个按键,例如ctrl+a,需要通过动作链ActionChains来实现
from selenium.webdriver import Chrome, ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
# 启动浏览器
driver = Chrome()
driver.get('http://www.baidu.com')
el = driver.find_element(By.ID, 'kw') # 定位输入框
el.send_keys("123456") # 输入123456
ac = ActionChains(driver)
ac.key_down(Keys.CONTROL) # 按下ctrl
ac.send_keys("a") # a
ac.perform() # 同时执行:ctrl+a全选
driver.quit() # 关闭浏览器
3.2.2 鼠标操作
移动到指定位置:move_by_offset()
移动到指定元素:move_to_element()
左键单击:click
鼠标的操作都包含在 ActionChains 类中,所以要模拟鼠标操作是首先要导入该包,F4去ActionChains查看源码里所有方法
from selenium.webdriver import ActionChains
3.3 元素定位失败
原因:
- 没有办法获得元素得定位表达式
- 定位元素得时候,元素各种原因导致定位表达式失效
- 定位成功,但是不能操作
NoSuchElementException 元素不存在原因:
- 元素尚未加载
- 元素被动态删除
ElementNotVisibleException 元素不可见原因:
- 0像素
- 在屏幕之外
- 上级节点被隐藏
ElementNotInteractableException 元素不可交互原因:
- 元素只读
- 元素被禁用
- 元素被遮挡
3.3.1 获取动态元素定位表达式
? ? ? ?有些元素的定位表达式是动态的,可能会一直变化,导致我们复制的Xpath不能定位到该元素,此时可以使用debugger(driver)让python和浏览器暂停执行,方便观察自动化执行情况。进入debug模式之后,输入c退出debug模式
3.3.2 等待元素
? ? ? ?有时候元素定位失败得原因是元素尚未加载,此时需要添加等待直到元素被加载出来。
1.强制等待
是编程语言提供得休眠功能,让代码暂停执行,等待页面加载。缺点:不知道该休眠多少秒,不同的电脑可能需要不同的休眠时间
time.sleep(3) # 强制等待3秒
2.隐式等待
是selenium提供的便捷等待,在元素定位失败之后,马上重试,直到超时。缺点:无法满足复杂的业务场景,只能解决元素存不存在的问题,无法解决元素中内容存不存在的问题
driver.implicitly_wait(100) # 设置超时时间为100,大于0表示启用
3.显示等待
是selenium提供的,可以自定义等待的时机。在使用时必须关闭隐式等待。
from selenium.webdriver import Chrome, ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
# 启动浏览器
driver = Chrome()
driver.get('http://www.baidu.com')
el = driver.find_element(By.ID, 'kw') # 定位输入框
el.send_keys('654324') # 输入654324
# 1.定义函数,判断条件为当元素里内容不为空时返回true
def func(driver):
ele = driver.find_element(By.XPATH, '//*[@id="su"]')
if ele.text != "":
return True
wait = WebDriverWait(driver, 10) # 2.设置超时时间
wait.until(func) # 3.为等待指定等待条件
el_1 = driver.find_element(By.XPATH, '//*[@id="su"]') # 通过xpath定位百度一下按钮
el_1.click() # 点击百度一下按钮
driver.quit() # 关闭浏览器
4. 验证码处理
方法1:让开发人员注掉代码,关闭验证码
方法2:使用万能验证码
方法3:使用第三方验证码识别工具
方法4:记录cookie跳过登录
这里我们先介绍第三个方法:使用第三方验证码识别工具识别验证码
首先,获取登录界面的验证码截图(我这里是4位数字验证码),我这里使用的第三方工具叫超级鹰,你也可以使用别的工具,这里使用该工具识别接口获取接口返回值就是识别到的验证码,再把识别到的结果传入,具体代码如下:
import requests
def img1code(path):
resp = requests.post(
"https://upload.chaojiying.net/Upload/Processing.php",
data={
"user": "****", # 需要自己注册输入自己的用户名密码
"pass": "****",
"softid": "96002",
"codetype": "1902", # 在官网根据自己的验证码选择验证码类型
},
files={"userfile": open(path, "rb")}, # 验证码截图
)
if resp.json()["err_no"] == 0:
print("识别成功")
return resp.json()["pic_str"]
else:
print("识别失败", resp.json()["err_str"])
return False
code = img1code("code.png") # 调用方法将截到的验证码图片进行识别
print(code)
但是这种使用第三方工具的方法存在一些问题:自动化的测试频率高,可能需要成千次的识别,导致成本高。因为我们介绍第四种方法,记录cookie,自动登录。
selenium绕过登录的思路
1.首次进行正常登录,
2.输入密码与账号后进行登录
3.登录后将cookies保存到一个文件中
4.绕过登录,首先将cookies的信息读取出来
5.将cookies的信息添加到driver中,访问个人信息页面,后续将使用cookies,不再需要输入账户密码验证码进行登录。代码如下:
import json
import requests
from selenium.webdriver import Chrome
from selenium.webdriver.common.by import By
def img1code(path):
resp = requests.post(
"https://upload.chaojiying.net/Upload/Processing.php",
data={
"user": "****", # 需要自己注册输入自己的用户名密码
"pass": "****",
"softid": "96002",
"codetype": "1902", # 在官网根据自己的验证码选择验证码类型
},
files={"userfile": open(path, "rb")}, # 验证码截图
)
if resp.json()["err_no"] == 0:
print("识别成功")
return resp.json()["pic_str"]
else:
print("识别失败", resp.json()["err_str"])
return False
def save_cookies(driver):
"""获取cookies将其存入本地文件"""
cookies = driver.get_cookies() # 获取cookies
with open("cookies.json", "w") as f:
f.write(json.dumps(cookies))
def load_cookies(driver):
"""从本地文件加载cookies"""
driver.get('http://47.107.116.139/fangwei/m.php?m=Public&a=login&')
with open("cookies.json") as f:
_data = f.read()
if _data:
cookies = json.loads(_data)
else:
cookies = []
for cookie in cookies:
driver.add_cookie(cookie) # 使用cookies
driver.refresh() # 刷新页面,向服务器发送cookies
def is_login(driver):
"""判断是否登录"""
if '管理员登录' in driver.title:
return False
else:
print('已经登录')
return True
driver = Chrome()
load_cookies(driver) # 浏览器启动后,加载cookies
driver.refresh() # 刷新页面,向服务器发送cookies
# 判断:只有未登录,才执行登陆流程
if is_login(driver) is False:
driver.get('http://47.107.116.139/fangwei/m.php?m=Public&a=login&')
driver.find_element(By.XPATH, '//*[@id="verify"]').screenshot("code.png") # 保存验证码图片
code = img1code("code.png") # 识别验证码
if code:
driver.find_element(By.XPATH, '/html/body/form/table/tbody/tr/td[3]/table/tbody/tr[2]/td[2]/input').send_keys(
'admin') # 输入用户名
driver.find_element(By.XPATH, '/html/body/form/table/tbody/tr/td[3]/table/tbody/tr[3]/td[2]/input').send_keys(
'msjy123') # 输入密码
driver.find_element(By.XPATH, '/html/body/form/table/tbody/tr/td[3]/table/tbody/tr[5]/td[2]/input').send_keys(
code) # 输入验证码
driver.find_element(By.XPATH, '//*[@id="login_btn"]').click() # 点击登录
else:
print("验证码识别失败,无法登录")
save_cookies(driver) # 浏览器关闭前,保存cookies
driver.quit()
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!