巨某量引擎后台登录实战笔记 | Playwright自动化框架

news2025/1/16 13:51:30

前言

本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!

入正题看看滑块是怎么个事

目标网站:aHR0cHM6Ly9idXNpbmVzcy5vY2VhbmVuZ2luZS5jb20vbG9naW4=

开启F12,选择邮箱登录,邮箱填的简单一点就可以触发滑块验证码,比如"abcabc123456@qq.com"

点击登录后我们就可以看见滑块,观察请求,可以看见是一个"/account_login/v2/..."的请求返回了验证码的一些信息,这个接口实际上就是登录接口,异常就会返回验证码信息。

[显示滑块和接口参数的图片]

分析请求

我们继续看请求,下面有一个"rmc.bytedance.com/verifycenter/captcha/v2/....."的get请求,并且是一个html页面,我们直接双击进去,可以发现这就是滑块验证码本体。这个验证码窗口实际上是内嵌进登录页面的"iframe"中的,那么我们后面的滑动测试和分析都可以单独打开这个页面进行了。

[完成滑动后请求图片]
我们手动滑动测试一下看看它会发送什么请求。

在这里插入图片描述

可以看见有2个请求,请求1(验证是否滑动成功)"/captcha/verify/...";请求2(重新登录)"/account_login/v2/..."。

到这就差不多确定整个流程了:

在这里插入图片描述

了解滑块验证码构成

滑块验证码一般是由滑块角块(也是图片)和背景图片两部分构成,其中滑块背景图片位置是固定的,我们滑动的是滑块角块图片到背景图片缺口位置。

滑块的初始位置一般会是随机的,而巨量(抖音系)的滑块则是固定在最左边,这无形中降低了我们的处理难度,因为不需要去找滑块角块的初始位置。

ddddocr 解决方案

经过测试,发现巨量滑块是可以使用无头浏览器进行处理的,所以我们这里使用ddddocr框架进行图像识别,然后获取滑动距离;使用无头浏览器进行滑块滑动。

所以我们想要实现自动化登录就需要处理几个关键点:

  1. 获取滑块验证码的参数信息。滑块图片、背景图片(如果有滑块验证码)、以及获取滑块的参数(用于验证)。
  2. 使用无头浏览器滑动滑块。

1、获取滑块验证码的参数信息

我们清空缓存,刷新页面重新登录,找到/account_login/v2/...接口,可以看到我们在清空缓存后的第一次请求fp是空的,并且有一个a_bogus参数,account、password是经过一定算法处理的账号和密码。

在这里插入图片描述

然后我们在关闭验证码框,账号密码不变,重新点一次登录,再次观察请求,我们会发现fp参数就不为空了,并且a_bogus也改变了,只有账号和密码还有其他参数没有改变,因此我们可以得出结论:在账号密码不变的情况下,登录接口只有a_bogus和fp参数是动态改变的。

在这里插入图片描述

a_bogus算法处理生成的(这个参数登录接口暂时没有做强校验,如果设置为空后台登录只是会显示未知登录设备,所以暂不处理,后续单独出一篇内容讲解。),而fp参数是由登录接口返回的。

我们在看请求接口"rmc.bytedance.com/verifycenter/captcha/v2/...",可以发现它的请求参数fp、verify_data就是在登录接口中获得到的2个参数,并且其他的参数只有一个时间戳会改变。
我们在手动滑动滑块到正确的位置,可以看见先发送了一个请求/captcha/verify/...这是一个验证是否滑动正确的请求,然后又发送了第二次/account_login/v2/...登录请求,并且这一次的响应不是验证码信息,而是登录成功/密码错误的信息。
那么其实到这我们需要的所有内容就已经得到了。
完整的流程是:先登录获取验证码参数 -> 构造验证码html -> 访问html(滑块图片、背景图片都包含在内) -> 通过无头浏览器去处理滑块。

在这里插入图片描述

2、使用无头浏览器滑动

使用无头浏览器滑动我们需要先获得滑块和目标位置的距离,而巨量这个滑块起点固定在初始的位置,并且没有y轴的需求,所以我们使用ddddocr可以很轻松的得到距离。

import time
import base64
import random
import ddddocr
import requests
from playwright.sync_api import sync_playwright, Page


def get_img_bytes_by_htmltag_selector(page: Page, selector: str) -> bytes:
    """
    根据浏览器标签id获取图片bytes 数据

    :param page: page对象
    :param selector: css选择器 img#captcha-verify_img_slide  表示找img标签id=captcha-verify_img_slide的
    :return:
    """
    img_bytes = b''
    if "img" in selector:
        page.wait_for_selector(selector)
        img_element = page.query_selector(selector)
        img_url = img_element.get_attribute('src')
        img_bytes = requests.get(img_url).content
    elif "canvas" in selector:
        page.wait_for_selector(selector)
        canvas = page.query_selector(selector)
        base64_data: str = page.evaluate('(canvas) => canvas.toDataURL("image/jpg")', canvas).replace(
            'data:image/png;base64,', '')
        img_bytes = base64.b64decode(base64_data)
    return img_bytes


def get_distance_by_ddddocr(slide_img_bytes, target_img_bytes) -> int:
    """
    通过ddddocr识别到目标图案的坐标

    :param slide_img_bytes: 小滑块图片字节
    :param target_img_bytes: 目标背景图片字节
    :return: 目标图案坐标x轴
    """
    det = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False)
    res = det.slide_match(slide_img_bytes, target_img_bytes, simple_target=True)
    target_x = res["target"][0]
    return target_x


if __name__ == '__main__':
    # 滑块iframe测试链接
    url_base64='aHR0cHM6Ly9ybWMuYnl0ZWRhbmNlLmNvbS92ZXJpZnljZW50ZXIvY2FwdGNoYS92Mj9mcm9tPWlmcmFtZSZmcD12ZXJpZnlfbHdlejN5ZmdfYmM3YWIxMTRfNGMwOF9lNmU2XzNmZWFfNDc1NzIxM2EwNzE3JmVudj0lN0IlMjJzY3JlZW4lMjIlM0ElN0IlMjJ3JTIyJTNBMTkyMCUyQyUyMmglMjIlM0ExMDgwJTdEJTJDJTIyYnJvd3NlciUyMiUzQSU3QiUyMnclMjIlM0ExOTIwJTJDJTIyaCUyMiUzQTEwNTUlN0QlMkMlMjJwYWdlJTIyJTNBJTdCJTIydyUyMiUzQTkwMSUyQyUyMmglMjIlM0E5MzQlN0QlMkMlMjJkb2N1bWVudCUyMiUzQSU3QiUyMndpZHRoJTIyJTNBOTAxJTdEJTJDJTIycHJvZHVjdF9ob3N0JTIyJTNBJTIyYnVzaW5lc3Mub2NlYW5lbmdpbmUuY29tJTIyJTJDJTIydmNfdmVyc2lvbiUyMiUzQSUyMjEuMC4wLjYwJTIyJTJDJTIybWFza1RpbWUlMjIlM0ExNzE2MjA5OTc4NDYyJTJDJTIyaDVfY2hlY2tfdmVyc2lvbiUyMiUzQSUyMjQuMC41JTIyJTdEJmFpZD0xNDAyJnNjZW5lX2xldmVsPXAyJmFwcF9uYW1lPWFjd2ViJmhvc3Q9JTJGJTJGdmVyaWZ5LnppamllYXBpLmNvbSZsYW5nPXpoJnRoZW1lPSU3QiUyMmhhbGZfY25fT2tCdG5CZ0NvbG9yJTIyJTNBJTIyJTIzMkE1NUU1JTIyJTdEJnZlcmlmeV9kYXRhPSU3QiUyMmNvZGUlMjIlM0ElMjIxMDAwMCUyMiUyQyUyMmZyb20lMjIlM0ElMjJzaGFya19hZG1pbiUyMiUyQyUyMnR5cGUlMjIlM0ElMjJ2ZXJpZnklMjIlMkMlMjJ2ZXJzaW9uJTIyJTNBJTIyMSUyMiUyQyUyMnJlZ2lvbiUyMiUzQSUyMmNuJTIyJTJDJTIyc3VidHlwZSUyMiUzQSUyMnNsaWRlJTIyJTJDJTIydWlfdHlwZSUyMiUzQSUyMiUyMiUyQyUyMmRldGFpbCUyMiUzQSUyMnhSRnZOOVJhNXE0ZmhHZHc0ek5YdTRsbk5tNmQ0b1dEbW1UU1FPOGxpM1dBOUNEa2JoRUdpaEZqUUFvcEtGY2czVEZHVioqU01ZeFFObWdIN1lHMXZJUnpuM1lORCpOWW14QWFuVmotenprNmNMUFZUWVllS3dicVF0MEpnZlBRRDZ6KnBick9PeGFhS2FPd3ktQnZYczZzcHkqY0lFUU5wQ0c1dGQyd3NXT3FVM21sZ1lJMDlucVhvUDBZRWViRTY4ZW1mVEk1NzkqNW1nTk5hMjdTeHFoeEJBM1AzRHFNb2tDWHRoLVM0SjJMcSpPbHJ5aDg1QTZycFA0TU1SMkg5RmFodTJkUy1oUzNHV254UEdxbGdqZWZlZjljZCpRVE5IckRLd1UxTll5QVUqNS1HVEh0ZEI3aVV6Zk40RU8tVlJzTm1rbWt6YkdpUEFZRXUyMnZ6cGRSVnd2dWhZWWlmeDRqRVhPdDFyY25zVG5mWXNRWmxPYWFCd09XWDh1bEotSDl4TDhjWnpnRTh0enI1dy1XKlc3ZyUyMiUyQyUyMnZlcmlmeV9ldmVudCUyMiUzQSUyMnR0X3Nzb19hY2NvdW50X2xvZ2luJTIyJTJDJTIyZnAlMjIlM0ElMjJ2ZXJpZnlfbHdlejN5ZmdfYmM3YWIxMTRfNGMwOF9lNmU2XzNmZWFfNDc1NzIxM2EwNzE3JTIyJTJDJTIyc2VydmVyX3Nka19lbnYlMjIlM0ElMjIlN0IlNUMlMjJpZGMlNUMlMjIlM0ElNUMlMjJsZiU1QyUyMiUyQyU1QyUyMnJlZ2lvbiU1QyUyMiUzQSU1QyUyMkNOJTVDJTIyJTJDJTVDJTIyc2VydmVyX3R5cGUlNUMlMjIlM0ElNUMlMjJwYXNzcG9ydCU1QyUyMiU3RCUyMiUyQyUyMmxvZ19pZCUyMiUzQSUyMjIwMjQwNTIwMjA1OTM4RTlGN0U5REJGQ0I3Rjc4OTE5NzclMjIlMkMlMjJpc19hc3Npc3RfbW9iaWxlJTIyJTNBZmFsc2UlMkMlMjJpc19jb21wbGV4X3NtcyUyMiUzQWZhbHNlJTJDJTIyaWRlbnRpdHlfYWN0aW9uJTIyJTNBJTIyJTIyJTJDJTIyaWRlbnRpdHlfc2NlbmUlMjIlM0ElMjIlMjIlMkMlMjJ2ZXJpZnlfc2NlbmUlMjIlM0ElMjJwYXNzcG9ydCUyMiUyQyUyMmxvZ2luX3N0YXR1cyUyMiUzQTAlMkMlMjJhaWQlMjIlM0EwJTJDJTIybWZhX2RlY2lzaW9uJTIyJTNBJTIyJTIyJTdE'
    
    url=...
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False, args=['--disable-blink-features=AutomationControlled'])
        page = browser.new_page()
        page.goto(url)
        page.wait_for_timeout(2000)  # 滑块加载太慢了等待5秒防止异常
        # ddddocr识别
        slide_img_bytes = get_img_bytes_by_htmltag_selector(page, "img#captcha-verify_img_slide")
        target_img_bytes = get_img_bytes_by_htmltag_selector(page, "img#captcha_verify_image")
        x = get_distance_by_ddddocr(slide_img_bytes, target_img_bytes)

        # 计算实际x轴位置
        selector = "div.captcha-slider-btn"
        slide_element = page.wait_for_selector(selector)
        slide_element_pos = slide_element.bounding_box()
        width = slide_element_pos['width']
        height = slide_element_pos['height']
        x = x / (width / height) # 计算实际位置,x/宽高比

        # 开始滑动
        mouse = page.mouse
        mouse.move(slide_element_pos['x'], slide_element_pos['y'])
        page.wait_for_timeout(200)
        mouse.down()
        mouse.move(slide_element_pos['x'] + x, slide_element_pos['y'], steps=random.randint(10, 15))
        page.wait_for_timeout(200)
        mouse.up()
        time.sleep(60)
        browser.close()

在这里插入图片描述

结束

因为在之前的版本中,某音系滑块的背景图顺序是打乱的,如果你获取到图片需要自己进行裁剪合并完整图像,所以我们上面的代码是使用单独的验证码窗口去进行滑动的,并且获取图片的方式是直接读取元素。

实际上也可以直接在登录页面,读取iframe的对象然后直接滑动,并且新版的图片顺序没有打乱,所以滑块的图片可以使用page.on捕获请求,当链接命中请求图片的接口就处理滑块。

如果文章内容有什么地方不对,欢迎评论或者私信提醒。
如果你有更多的案例也可以私信我添加到文章内容中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1682885.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数字孪生项目开发流程

数字孪生(Digital Twin)项目的开发流程涉及多个步骤,从初始概念到最终部署和维护。以下是一个典型的数字孪生项目开发流程,通过这些步骤,开发团队可以有效地规划、设计、开发和维护数字孪生项目,确保其在实…

YOLOv5 Exception: Dataset not found.

在使用yolo v5训练时弹出了这个报错,就是没有找到数据集,dataset.yaml文件里面的train 和val 的路径配置不对,开始我是使用相对路径,后面修改成绝对路径就可以了

Ubuntu23.04开机时whoopsie-upload-all占用CPU 100%,风扇狂转

Ubuntu23.04开机时,风扇狂转散热,打开终端,输入top -c,查看占用cpu最高的进程,发现是python3在执行whoopsie-upload-all脚本文件。 什么是whoopsie? 这是“Ubuntu错误报告”守护程序,默认安装在…

DAB协议解读ETSI TS 103 461

一、说明 数字信号广播( Digital Audio Broadcasting 简称DAB)是继AM、FM传统模拟广播之后的第三代广播--数字信号广播,它提供了接近CD质量的声音,广播及商机无限的附加数据服务,具有抗噪声、抗干扰、抗电波传播衰落、…

采用LoRA方法微调llama3大语言模型

文章目录 前言一、Llama3模型简介1.下载llama3源码到linux服务器2.安装依赖3.测试预训练模型Meta-Llama-3-8B4.测试指令微调模型Meta-Llama3-8B-Instruct5.小结 二、LoRA微调Llama31.引入库2.编写配置文件3.LoRA训练的产物 三、测试新模型效果1.编写配置文件2.运行配置文件&…

(Qt) 默认QtWidget应用包含什么?

文章目录 ⭐前言⭐创建🛠️选择一个模板🛠️Location🛠️构建系统🛠️Details🛠️Translation🛠️构建套件(Kit)🛠️汇总 ⭐项目⚒️概要⚒️构建步骤⚒️清除步骤 ⭐Code🔦untitled…

Arcpy安装和环境配置

一、前言 ArcPy 是一个以成功的arcgisscripting 模块为基础并继承了arcgisscripting 功能进而构建而成的站点包。目的是为以实用高效的方式通过 Python 执行地理数据分析、数据转换、数据管理和地图自动化创建基础。该包提供了丰富纯正的 Python 体验,具有代码自动…

思维导图-VPN

浏览器集成了受信任的机构的证书

解决word里加入mathtype公式后行间距变大

1.布局>页面设置>文档网格,网格栏选为无网格 2.固定间距

数据库|基于T-SQL创建数据库

哈喽,你好啊,我是雷工! SQL Server用于操作数据库的编程语言为Transaction-SQL,简称T-SQL。 本节学习基于T-SQL创建数据库。以下为学习笔记。 01 打开新建查询 首先连接上数据库,点击【新建查询】打开新建查询窗口, …

Linux基础命令[27]-gpasswd

文章目录 1. gpasswd 命令说明2. gpasswd 命令语法3. gpasswd 命令示例3.1 不加参数3.2 -a(将用户加入组)3.3 -d(从组中删除用户)3.4 -r(删除组密码)3.5 -M(多个用户一起加入组)3.6 …

23种设计模式(持续输出中)

一.设计模式的作用 设计模式是软件从业人员长期总结出来用于解决特定问题的通用性框架,它提高了代码的可维护性、可扩展性、可读性以及复用性。 二.设计模式 1.工厂模式 工厂模式提供了创建对象的接口,而无需制定创建对象的具体类,工厂类…

kafka集群跨区域跨集群同步方案MirrorMaker1 —— 筑梦之路

MirrorMaker原理架构 数据流向 上图也是一种比较常见的用法,这里作为记录。下面介绍一则实战案例。 网络架构 配置日志采集器filebeat 配置从哪里采集日志 输出到kafka集群 配置MirrorMaker消费者 参数说明: bootstrap.servers 指定消费哪个kafka的数…

【HarmonyOS4学习笔记】《HarmonyOS4+NEXT星河版入门到企业级实战教程》课程学习笔记(八)

课程地址: 黑马程序员HarmonyOS4NEXT星河版入门到企业级实战教程,一套精通鸿蒙应用开发 (本篇笔记对应课程第 15 节) P15《14.ArkUI组件-状态管理state装饰器》 回到最初的 Hello World 案例,首先验证 如果删掉 State…

Day22:Leetcode:654.最大二叉树 + 617.合并二叉树 + 700.二叉搜索树中的搜索 + 98.验证二叉搜索树

LeetCode:654.最大二叉树 1.思路 解决方案: 单调栈是本题的最优解,这里将单调栈题解本题的一个小视频放在这里 单调栈求解最大二叉树的过程当然这里还有leetcode大佬给的解释,大家可以参考一下: 思路很清晰&#xf…

软件开源协议与QT的开源协议介绍

一.常见的六种开源协议 1.BSD协议 BSD协议全称为“Berkely Software Distribution”,中文译为“伯克利软件发行版”。其最早用于伯克利UNIX操作系统上的开源贡献。 主要特点: 允许修改源码 允许源码再发布 允许商业软件发布和销售 约束&#xff1…

JVM学习-垃圾回收(二)

标记-清除(Mark-Sweep)算法 当堆中的有效内存空间被耗尽的时候,就会停止整个程序(stop the world),然后进行两项工作,第一项则是标记,第二项是清除 标记:Collector从引用根节点开始遍历,标记所有被引用的…

fork 与 vfork 的区别

关键区别一: vfork 直接使用父进程存储空间,不拷贝。 关键区别二: vfork保证子进程先运行,当子进程调用exit退出后,父进程才执行。 我们可以定义一个cnt,在子进程中让它变成3, 如果使用fork,那…

java 8--Lambda表达式,Stream流

目录 Lambda表达式 Lambda表达式的由来 Lambda表达式简介 Lambda表达式的结构 Stream流 什么是Stream流? 什么是流呢? Stream流操作 中间操作 终端操作 Lambda表达式 Lambda表达式的由来 Java是面向对象语言,除了部分简单数据类型…

【机器学习】前沿探索,如何让前端开发更加搞笑

在当今数字化时代,机器学习的崛起为前端开发带来了巨大的机遇和挑战。随着人工智能和数据科学的不断进步,前端工程师不再局限于传统的界面设计和交互体验,而是开始探索如何将机器学习技术融入到他们的工作中,以创造更加智能、个性…