1.浏览器坐标系
整个浏览器的坐标系示意图如下图所示,原点在网页的左上角,水平向右是x轴正方向,水平向下是y轴正方向,这个基础知识对于接下来使用playwright模拟鼠标点击滑动验证是非常重要的。
2.实现流程
(1)playwright访问豆瓣网站,定位账号输入框并输入账号,定位获取验证码按钮,让网页弹出滑动验证码窗口,定位整个滑动验证码图片(在下面的代码中我们可以看到,我们下载图片验证码的时候定义的是整个与滑动验证码有关的div块)。
(2)下载滑动验证码图片,如下图所示,将滑动验证码图片交给图鉴,图鉴会以字符串的形式返回一个滑块移动的距离。
(3)playwright定位到滑块标签,使用playwright的内置方法获取滑块标签的坐标以及宽度。
(4)playwright模拟鼠标选中滑块标签,拖到滑块标签滑动图鉴返回的移动距离,松开鼠标。
3.代码实现
'''
程序不能实现我们需要的滑动验证的效果使用图鉴中的单张图片识别,现在的问题是没有看到鼠标拖动的效果,页没有看到验证成功的效果
'''
from playwright.sync_api import sync_playwright
import base64
import json
import requests# 一、图片文字类型(默认 3 数英混合):
# 1 : 纯数字
# 1001:纯数字2
# 2 : 纯英文
# 1002:纯英文2
# 3 : 数英混合
# 1003:数英混合2
# 4 : 闪动GIF
# 7 : 无感学习(独家)
# 11 : 计算题
# 1005: 快速计算题
# 16 : 汉字
# 32 : 通用文字识别(证件、单据)
# 66: 问答题
# 49 :recaptcha图片识别
# 二、图片旋转角度类型:
# 29 : 旋转类型
#
# 三、图片坐标点选类型:
# 19 : 1个坐标
# 20 : 3个坐标
# 21 : 3 ~ 5个坐标
# 22 : 5 ~ 8个坐标
# 27 : 1 ~ 4个坐标
# 48 : 轨迹类型
#
# 四、缺口识别
# 18 : 缺口识别(需要2张图 一张目标图一张缺口图)
# 33 : 单缺口识别(返回X轴坐标 只需要1张图)
# 五、拼图识别
# 53:拼图识别
def base64_api(uname, pwd, img, typeid):with open(img, 'rb') as f:base64_data = base64.b64encode(f.read())b64 = base64_data.decode()data = {"username": uname, "password": pwd, "typeid": typeid, "image": b64}result = json.loads(requests.post("http://api.ttshitu.com/predict", json=data).text)if result['success']:return result["data"]["result"]else:#!!!!!!!注意:返回 人工不足等 错误情况 请加逻辑处理防止脚本卡死 继续重新 识别return result["message"]return ""def get_instance(img_path,typeid):result = base64_api(uname='自己登录图鉴的账号', pwd='自己登录图鉴的密码', img=img_path, typeid=typeid)return resultwith sync_playwright() as p:browser = p.chromium.launch(headless=False)context = browser.new_context()page = context.new_page()page.goto("https://www.douban.com/")# page.locator("iframe").content_frame.get_by_placeholder("手机号").fill("13695457910")page.frame_locator('xpath=/html/body/div[2]/div/div[1]/iframe').get_by_placeholder('手机号').fill('13695457910')# page.locator("iframe").content_frame.get_by_role("link", name="获取验证码").click()page.frame_locator('xpath=/html/body/div[2]/div/div[1]/iframe').get_by_role("link",name="获取验证码").click()page.wait_for_timeout(10000) # 等待图片加载完成,如果不加入等待时间,截图会很模糊导致后续识别失败# 下载滑动图片,先得到图片的下载地址(通过playwright直接截取图片不知道为什么截取的很不清楚)iframe_1 = page.frame_locator('xpath=/html/body/div[2]/div/div[1]/iframe')iframe_1.frame_locator('#tcaptcha_iframe_dy').locator('//*[@id="bodyWrap"]').screenshot(path='background.png')# 计算滑块移动的距离result = get_instance(img_path='background.png',typeid=33)print('滑块滑动的距离为',result,type(result)) # 返回值是x轴的移动距离d = int(result)# 定位到滑块标签slide = iframe_1.frame_locator('#tcaptcha_iframe_dy').locator('//*[@id="tcOperation"]/div[6]')# 找到滑块在当前页面的坐标(这个会返回一个字典里边四个数字)# {'x': 858, 'y': 339.9921875, 'width': 55, 'height': 55}box = slide.bounding_box()print(box)# 让鼠标移动到滑块标签的中心的位置上page.mouse.move(box["x"] + box["width"] / 2, box["y"] + box["height"] / 2)# 按下鼠标page.mouse.down()# 测试能否滑动page.mouse.move(x=box['x'] + d,y=box["y"])# 移动结束鼠标释放page.mouse.up()page.wait_for_timeout(5000)page.close()context.close()browser.close()