Python 通过Playwright+OpenCV破解滑动验证码 实例

由于公司最近需要对接某业务系统,涉及到部分数据需要提交至其它平台业务系统,只有其它平台账户,没有接口,因此做此开发。首先通过OpenCV计算出验证验证码滑块距离,根据距离,使用 Playwright 利用滑动距离模拟登录

复制代码
 下面展示Python  通过 Playwright 滑动及登录过程
  1. 首先下载 安装 Playwright
bash 复制代码
pip install playwright
  1. 安装浏览器驱动(此步骤会在本地安装二进制浏览器:火狐、谷歌等)
bash 复制代码
	python -m playwright install
  1. Playwright 录制脚本(通过脚本录制,不需要写代码,通过鼠标事件将代码输出到文件当中)
bash 复制代码
python -m playwright codegen -o "D:test.py"
  1. 主要代码展示
python 复制代码
import re
from playwright.sync_api import Playwright, sync_playwright
import time
import random
from result  import error_result, success_result
from position import get_gap_position

def perform_slide(page, max_retries=3):
    """执行滑块验证,支持自动重试"""
    retry_count = 0
    while retry_count < max_retries:
        try:
            page.wait_for_selector("#circle", state="visible", timeout=2000)
            page.wait_for_selector("#bg_canvas", state="visible", timeout=2000)

            # 计算缺口位置
            try:
                image_data = page.evaluate("document.getElementById('bg_canvas').toDataURL('image/png').split(',')[1]")
                gap_x = get_gap_position(image_data)
            except Exception as e:
                print(f"缺口检测失败,使用默认偏移量: {e}")
                gap_x = 50  # 备用值

            # 模拟拖动
            slider = page.query_selector("#circle")
            slider_bbox = slider.bounding_box()
            start_x = slider_bbox["x"] + slider_bbox["width"] / 2
            start_y = slider_bbox["y"] + slider_bbox["height"] / 2
            target_x = start_x + gap_x + 8

            page.mouse.move(start_x, start_y)

            page.mouse.down()
            steps = random.randint(15, 30)
            for i in range(steps):
                x = start_x + (target_x - start_x) * (i / steps)
                y = start_y + random.uniform(-2, 2)
                page.mouse.move(x, y)
                #time.sleep(random.uniform(0.01, 0.02))

            page.mouse.up()

            # 检查成功
            if page.query_selector(".popup-success"):
                print("验证成功!")
                return True
            else:
                retry_count += 1
                print(f"验证失败,第 {retry_count} 次重试...")
                time.sleep(0.5)

        except Exception as e:
            print(f"滑动过程中出错: {e}")
            retry_count += 1

    return False

def login_with_slide(
    username: str,
    password: str,
    login_url: str = "http://test.com/",
    max_slide_retries: int = 3
) -> dict:
    """执行带滑块验证的登录,并返回登录接口的 JSON 数据"""
    with sync_playwright() as playwright:
        browser = playwright.webkit.launch(headless=True)
        context = browser.new_context()
        page = context.new_page()
        page.set_default_timeout(5000)

        login_response = None

        def handle_response(response):
            nonlocal login_response
            if "login2" in response.url and response.status == 200:
                try:
                    print("登录接口响应:", response.json())
                    login_response = login_result(response.json())
                except ValueError:
                   return error_result("接口返回非json数据")

        page.on("response", handle_response)

        try:
            page.goto(login_url)
            page.get_by_role("textbox", name="请输入统一社会信用代码或身份证号").fill(username)
            page.get_by_role("textbox", name="请输入密码").fill(password)
            page.get_by_role("button", name="登录").click()

            if not perform_slide(page, max_slide_retries):
                return error_result("滑块验证失败")

            # 等待登录接口响应
            page.wait_for_timeout(500)  # 简单延迟,确保响应已捕获
            return login_response or  error_result("未获取到登录异常")

        except Exception as e:
            return  error_result("f登录异常: {}"+str(e))
        finally:
            page.close()
            context.close()
            browser.close()

def login_result(response: dict) -> dict:
    if response.get("result")==0:
        return success_result("成功",response.get("data",{}).get("userDetail"))
    return error_result("登录失败,接口信息异常")
if __name__ == "__main__":

        result = login_with_slide(
            username="admin",
            password="hpg123789"
        )
        print("最终结果:", result)
相关推荐
郭庆汝8 分钟前
(六)MCP+A2A之——Playwright与BrowserUse:让AI学会像人类一样使用浏览器
开发语言·python
Yolanda_202213 分钟前
26.网络模型的保存与读取
人工智能·pytorch·python
weixin1997010801630 分钟前
《京东JOS API:落地方案、接口边界与业务踩坑 —— 联盟免费 vs 商家按量的双轨制》(附python源码)
java·网络·python
外收内放31 分钟前
数据分析(数据查询与选择)
python·学习·数据分析
林澈在路上35 分钟前
哪个写歌软件可以用自己声音?MELO音乐详解
人工智能·python·算法
外收内放43 分钟前
数据分析(数据读取与写入)
python·学习·数据分析
LittroInno1 小时前
全景拼接中的重叠区域 视差与动态重影
图像处理·opencv·计算机视觉·图像配准·全景拼接
zh路西法1 小时前
【离策略强化学习】DDPG、TD3 与 SAC:核心公式推导与源码解析
python·强化学习·ddpg·td3·sb3·off-policy·sac
秋秋小事1 小时前
python 数据契约层FastAPI+Pydantic(一)
python
AIFQuant1 小时前
Python港股实时行情API接入:恒生股票数据获取与AH股溢价监控实战
开发语言·数据库·python·金融·实时数据api