web自动化(2)——浏览器及元素操作

发布时间:2023年12月22日

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_sourceHTML源码
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 元素基本的操作

  1. 点击:click()
  2. 输入:send_keys("123")
  3. 清空: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 元素定位失败

原因:

  1. 没有办法获得元素得定位表达式
  2. 定位元素得时候,元素各种原因导致定位表达式失效
  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()

文章来源:https://blog.csdn.net/weixin_42833736/article/details/135086378
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。