DrissionPage使用
验证码
普通文本验证码
img_bytes=page.ele('tag:img@src:image/png;base64').src()
ocr= ddddocr.DdddOcr()
yzm=ocr.classification(img_bytes)
page.ele('#loginCode').input(yzm)
滑块验证码
'''删除img文件夹'''
import os
import shutil
def delete_img_folder():
folder_name = 'img'
# 获取当前工作目录
current_directory = os.getcwd()
# 构造要删除的文件夹的完整路径
folder_path = os.path.join(current_directory, folder_name)
try:
# 删除文件夹及其内容
shutil.rmtree(folder_path)
# print(f"成功删除文件夹: {folder_path}")
except FileNotFoundError:
# print(f"文件夹 '{folder_path}' 不存在")
pass
except Exception as e:
print(f"发生错误: {e}")
import PIL
import cv2
import numpy as np
from pathlib import Path
def pil_to_cv2(img):
"""
pil转cv2图片
:param img: pil图像, <type 'PIL.JpegImagePlugin.JpegImageFile'>
:return: cv2图像, <type 'numpy.ndarray'>
"""
img = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
return img
def bytes_to_cv2(img):
"""
二进制图片转cv2
:param img: 二进制图片数据, <type 'bytes'>
:return: cv2图像, <type 'numpy.ndarray'>
"""
# 将图片字节码bytes, 转换成一维的numpy数组到缓存中
img_buffer_np = np.frombuffer(img, dtype=np.uint8)
# 从指定的内存缓存中读取一维numpy数据, 并把数据转换(解码)成图像矩阵格式
img_np = cv2.imdecode(img_buffer_np, 1)
return img_np
def cv2_open(img, flag=None):
"""
统一输出图片格式为cv2图像, <type 'numpy.ndarray'>
:param img: <type 'bytes'/'numpy.ndarray'/'str'/'Path'/'PIL.JpegImagePlugin.JpegImageFile'>
:param flag: 颜色空间转换类型, default: None
eg: cv2.COLOR_BGR2GRAY(灰度图)
:return: cv2图像, <numpy.ndarray>
"""
if isinstance(img, bytes):
img = bytes_to_cv2(img)
elif isinstance(img, (str, Path)):
img = cv2.imread(str(img))
elif isinstance(img, np.ndarray):
img = img
elif isinstance(img, PIL.Image):
img = pil_to_cv2(img)
else:
raise ValueError(f'输入的图片类型无法解析: {type(img)}')
if flag is not None:
img = cv2.cvtColor(img, flag)
return img
def get_distance(bg, tp, save_path=None):
"""
:param bg: 背景图路径或Path对象或图片二进制
eg: 'assets/bg.jpg'
Path('assets/bg.jpg')
:param tp: 缺口图路径或Path对象或图片二进制
eg: 'assets/tp.jpg'
Path('assets/tp.jpg')
:param save_path: 保存路径, <type 'str'/'Path'>; default: None
:return: 缺口位置
"""
# 读取图片
bg_gray = cv2_open(bg, flag=cv2.COLOR_BGR2GRAY)
tp_gray = cv2_open(tp, flag=cv2.COLOR_BGR2GRAY)
# 边缘检测
tp_gray = cv2.Canny(tp_gray, 255, 255)
bg_gray = cv2.Canny(bg_gray, 255, 255)
# 目标匹配
result = cv2.matchTemplate(bg_gray, tp_gray, cv2.TM_CCOEFF_NORMED)
# 解析匹配结果
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
distance = max_loc[0] + 8
if save_path:
# 需要绘制的方框高度和宽度
tp_height, tp_width = tp_gray.shape[:2]
# 矩形左上角点位置
x, y = max_loc
# 矩形右下角点位置
_x, _y = x + tp_width, y + tp_height
# 绘制矩形
bg_img = cv2_open(bg)
cv2.rectangle(bg_img, (x, y), (_x, _y), (0, 0, 255), 2)
# 保存缺口识别结果到背景图
if save_path:
save_path = Path(save_path).resolve()
save_path = save_path.parent / f"{save_path.stem}.{distance}{save_path.suffix}"
save_path = save_path.__str__()
cv2.imwrite(save_path, bg_img)
return distance
'''使用ddddocr计算缺口距离'''
def get_distance_by_ddddocr():
'''
直接使用img文件夹下的target.png和background.png
target.png:指的是小滑块图片
background.png:带坑位的背景图
'''
det = ddddocr.DdddOcr(det=False, ocr=False)
with open('./img/target.png', 'rb') as f:
target_bytes = f.read()
with open('./img/background.png', 'rb') as f:
background_bytes = f.read()
res = det.slide_match(target_bytes, background_bytes)
x_distance = res["target"][0]
return x_distance
'''据偏移量获取移动轨迹'''
import random
def get_tracks(distance):
"""
:param distance: 缺口距离
:return: 轨迹
"""
# 分割加减速路径的阀值
value = round(random.uniform(0.55, 0.75), 2)
# 划过缺口 20 px
#distance += 20
# 初始速度,初始计算周期, 累计滑动总距
v, t, sum = 0, 0.3, 0
# 轨迹记录
plus = []
# 将滑动记录分段,一段加速度,一段减速度
mid = distance * value
while sum < distance:
if sum < mid:
# 指定范围随机产生一个加速度
a = round(random.uniform(2.5, 3.5), 1)
else:
# 指定范围随机产生一个减速的加速度
a = -round(random.uniform(2.0, 3.0), 1)
s = v * t + 0.5 * a * (t ** 2)
v = v + a * t
sum += s
plus.append(round(s))
# end_s = sum - distance
# plus.append(round(-end_s))
# 手动制造回滑的轨迹累积20px
# reduce = [-3, -3, -2, -2, -2, -2, -2, -1, -1, -1]
reduce = [-6, -4, -6, -4]
return {'plus': plus, 'reduce': reduce}
'''嵌入式滑块'''
page.get("https://castatic.fengkongcloud.cn/pr/v1.0.4/demo.html")
delete_img_folder()
demo = page.ele("@text()=返回demo列表",timeout=1)
if demo:
demo.click()
page.ele("@text()=嵌入式(embed)").click()
page.ele('@name=account').input("test")
page.ele('@name=password').input("test")
page.ele('.shumei_captcha_loaded_img_fg').save(path="./img/",name='target.png')
page.ele('.shumei_captcha_loaded_img_bg').save(path="./img/",name='background.png')
# 在网址上计算的距离必须除2,可能是分辨率导致的
x_distance = get_distance_by_ddddocr() / 2
trajectory = get_tracks(x_distance)
move_to_gap(slide_ele =".shumei_captcha_slide_btn_icon sm-iconfont",tracks = trajectory)
time.sleep(0.2)
gugu = page.ele('#shumei_form_captcha_wrapper')
if gugu:
gugu.get_screenshot(path="./img/captcha.png")
定位
page.ele('x://*[@id="app"]/div/div[1]/div/div/div[2]/div[2]/div[2]/form/div[1]/div/div/div/div[1]/input').input(username)
注意
加载网页最好设置好超时时间,以免等待过久
co = ChromiumOptions(timeout=5)
HTML文档通常是从上到下顺序加载和解析的。浏览器会从文档的顶部开始,逐行解析HTML内容,并在遇到各种资源(如CSS、JavaScript、图片等)时进行相应的处理。
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 程序员小航
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果