Python识别抖音Tiktok、巨量引擎滑块验证码识别

由于最近比较忙,所以本周搞了一个相对简单的验证码,就是抖音Tiktok的滑块验证码,这也是接到客户的一个需求。这种验证码通常在电脑端登录抖音、巨量引擎的的时候出现。

首先看一下最终的效果:

 

验证码识别过程

1、利用爬虫采集图像

由于是识别滑块缺口位置,分析了一下,大图已经包含了滑块缺口的位置信息,所以这里只需要采集大图就够了。不需要小图进行比对,这样可以简单一点。

(1)采集大图

2、人工标记

为了保障识别的精度,这里需要进行大量的人工标记,最好将误差控制在1-2像素以内,这样训练出来的识别模型效果才好。

 3、训练模型

4、测试验证

我们将训练好的模型用100张图片来进行测试,发现全部都能正确识别位置,所以正确率接近100%。因为100张测试图片比较少,所以保守估计正确率应该在99%左右。

如果再想提升正确率,可以再增加训练的数据量,就需要再投入大量人力,这个投入与提升产出比需要自己权衡。

5、实战测试

这里我就直接上代码,就是文章开通动图的演示效果。我也将模型封装成了免费的接口给感兴趣的小伙伴调用:得塔云

__author__ = "dengxinyan"

import io
import time
import json
import requests
import urllib
import random
import base64
from io import BytesIO
from PIL import Image, ImageDraw, ImageFont
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.webdriver import ChromeOptions
from selenium.webdriver import FirefoxOptions

# PIL图片保存为base64编码
def PIL_base64(img, coding='utf-8'):
    img_format = img.format
    if img_format == None:
        img_format = 'JPEG'

    format_str = 'JPEG'
    if 'png' == img_format.lower():
        format_str = 'PNG'
    if 'gif' == img_format.lower():
        format_str = 'gif'

    if img.mode == "P":
        img = img.convert('RGB')
    if img.mode == "RGBA":
        format_str = 'PNG'
        img_format = 'PNG'

    output_buffer = BytesIO()
    # img.save(output_buffer, format=format_str)
    img.save(output_buffer, quality=100, format=format_str)
    byte_data = output_buffer.getvalue()
    base64_str = 'data:image/' + img_format.lower() + ';base64,' + base64.b64encode(byte_data).decode(coding)

    return base64_str

# 验证码识别接口
def shibie(img):
    url = "http://www.detayun.cn/openapi/verify_code_identify/"
    data = {
        # 用户的key
        "key":"nWrzPFUgFuqXQrCJJUME",
        # 验证码类型
        "verify_idf_id":"6",
        # 样例图片
        "img_base64":PIL_base64(img),
        "img_byte": None,
        # 中文点选,空间语义类型验证码的文本描述(这里缺省为空字符串)
        "words":""
    }
    header = {"Content-Type": "application/json"}

    # 发送请求调用接口
    response = requests.post(url=url, json=data, headers=header)
    print(response.text)
    return response.json()


def run(headless=False):
    # 配置参数
    options = FirefoxOptions()
    if headless:
        options.add_argument('--headless')
    else:
        options.add_argument('--window-size=100,100')
    options.add_argument('--disable-blink-features=AutomationControlled')
    options.add_argument('--disable-dev-shm-usage')
    options.set_preference('general.useragent.override', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36')

    driver = webdriver.Firefox(executable_path=r'F:\验证码项目\小红书旋转验证码\webdriver\geckodriver.exe', options=options)
    # 伪装浏览器
    driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => false,});")
    navigator_webdriver = driver.execute_script("return navigator.webdriver")
    driver.execute_script("Object.defineProperty(navigator, 'plugins', {get: () => [1, 2, 3, 4, 5],});")
    plugins_length = driver.execute_script("return navigator.plugins.length")

    # 发送请求
    driver.get('https://business.oceanengine.com/login?appKey=51')

    # 等待【请输入邮箱】元素出现
    WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//input[@placeholder="请输入邮箱"]'))
    # 找到【请输入邮箱】元素
    tag1 = driver.find_element_by_xpath('//input[@placeholder="请输入邮箱"]')
    # 点击【请输入邮箱】元素
    tag1.click()
    # 输入邮箱
    tag1.send_keys('123451111@qq.com')

    # 等待【密码】元素出现
    WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//input[@placeholder="密码"]'))
    # 找到【密码】元素
    tag2 = driver.find_element_by_xpath('//input[@placeholder="密码"]')
    # 点击【密码】元素
    tag2.click()
    # 输入密码
    tag2.send_keys('13611112222')

    # 等待【用户协议】元素出现
    WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//div[@class="account-center-agreement-check"]'))
    # 找到【用户协议】元素
    tag3 = driver.find_element_by_xpath('//div[@class="account-center-agreement-check"]')
    # 点击【用户协议】元素
    tag3.click()


    # 等待【登录】元素出现
    WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//button[@class="ace-ui-btn account-center-action-button active ace-ui-btn-primary"]'))
    # 找到【登录】元素
    tag4 = driver.find_element_by_xpath('//button[@class="ace-ui-btn account-center-action-button active ace-ui-btn-primary"]')
    # 点击【登录】元素
    tag4.click()

    # 可能一次不成功,需要多次滑动
    for i in range(5):
        # 等待【验证码大图】元素出现
        WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//img[@id="captcha-verify-image"]'))
        # 找到【验证码大图】元素
        tag5 = driver.find_element_by_xpath('//img[@id="captcha-verify-image"]')
        # 获取图像链接
        img_url = tag5.get_attribute('src')
        print(img_url)
        header = {
            "Host": "p9-catpcha.byteimg.com",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0",
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
            "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
            "Accept-Encoding": "gzip, deflate, br",
            "Connection": "keep-alive",
            "Upgrade-Insecure-Requests": "1",
        }

        # 下载图片
        response = requests.get(url=img_url)
        img = Image.open(BytesIO(response.content))
        y = shibie(img)
        # 获得滑动像素距离
        y = int(str(y['data']['res_str']).replace('滑动','').replace('px',''))

        # 等待【滑块】元素出现
        WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//div[@class="secsdk-captcha-drag-icon sc-kEYyzF fiQtnm"]'))
        # 找到【滑块】元素
        tag6 = driver.find_element_by_xpath('//div[@class="secsdk-captcha-drag-icon sc-kEYyzF fiQtnm"]')

        # 滑动滑块
        action = ActionChains(driver)
        action.click_and_hold(tag6).perform()
        time.sleep(1)
        # 计算实际滑动距离 = 像素距离 * 滑动系数
        move_x = y * 0.61

        # 滑动1:直接滑动
        action.move_by_offset(move_x + 20, 5)
        time.sleep(0.5)
        action.move_by_offset(-10, -15)
        time.sleep(0.5)
        action.move_by_offset(-10, 10)

        # 滑动2:分段滑动
        # n = (random.randint(5, 8))
        # move_x = move_x / n
        # for i in range(n):
        #     action.move_by_offset(move_x, 5)
        #     time.sleep(0.5)
        time.sleep(1)

        # 释放鼠标
        action.release().perform()

        time.sleep(2)

        # 判断是否滑动成功
        try:
            # 等待【错误提示】元素出现
            WebDriverWait(driver, 5).until(lambda x: x.find_element_by_xpath('//div[@class="sc-htoDjs jwiskW"]'))

            # 等待【刷新】元素出现
            WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//span[@class="secsdk_captcha_refresh--text sc-bwzfXH gBXrMn"]'))
            # 找到【刷新】元素
            tag7 = driver.find_element_by_xpath('//span[@class="secsdk_captcha_refresh--text sc-bwzfXH gBXrMn"]')
            # 点击【刷新】元素
            tag7.click()
            time.sleep(1)
        except:
            break

if __name__ == '__main__':
    run(headless=False)

6、总结分析

(1)抖音图片标注工作比较复杂,我统计了一下背景图的种类超过800中,所以给标注、识别增加了一定难度

(2)抖音的滑动轨迹检测比较厉害,直接滑动到位完全无法通过,分段轨迹也很难通过。所以我首先滑过,再返回对齐,这样就能完美一次通过验证(最前面动图就是这样的效果)

(3)抖音页面有很强的反爬措施,检测我使用 selenium 始终无法通过验证,始终不会条验证码。这一点如何防检测 selenium 也请各位大神指点。所以我代码使用的巨量引擎(巨量引擎是字节跳动旗下的品牌)网站进行的测试

各位大神也请指出我的不足,或者有其他建议都可以给我留言,或私信我,谢谢指点。
 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

jenkins的cicd操作

cicd概念 持续集成( Continuous Integration) 持续频繁的(每天多次)将本地代码“集成”到主干分支,并保证主干分支可用 持续交付(Continuous Delivery) 是持续集成的下一步,持续…

【ArcGIS Pro二次开发】(57):地图系列

在ArcGIS Pro中,有一个地图系列,可以在一个布局中导出多个地图。 在SDK中为ArcGIS.Desktop.layout.MapSeries类和映射系列导出选项,可以以支持多页导出。 MapSeries类提供了一个静态CreateSpatialMapSeries方法,该方法使用指定的…

【0807作业】使用消息队列实现AB进程对话+使用共享内存实现A进程打印字符串,B进程逆置字符串,打印结果为【正序 逆序 正序 逆序】

作业一:使用消息队列实现AB进程对话 ① 打开两个终端,要求实现AB进程对话 A进程先发送一句话给B进程,B进程接收后打印B进程再回复一句话给A进程,A进程接收后打印重复1.2步骤,当收到quit后,要结束AB进程 ② …

K8s中的PV和PVC和监控

1.PV和PVC PV:持久化存储,对存储资源进行抽象,对外提供可以调用的地方(类似:生产者) PVC:用于调用,不需要关心内部实现细节(类似:消费者) 2.实…

ChatGPT 作为 Python 编程助手

推荐:使用 NSDT场景编辑器 助你快速搭建可编辑的3D应用场景 简单的数据处理脚本 我认为一个好的起点是某种数据处理脚本。由于我打算让 ChatGPT 之后使用各种 Python 库编写一些机器学习脚本,这似乎是一个合理的起点。 目标 首先,我想尝试…

8.7一日总结

后台管理项目(使用vue3) 1.创建项目 npm init vuelatest 2.进入项目,下载依赖 3.下载需要的项目依赖 下载重置样式表 npm install reset-css 在main.js中阴入 import reset-css 4.清理目录 将项目中不需要的内容删除 5.运行项目 npm run dev 6.将仓库推送…

Unity Shader编辑器工具类ShaderUtil 常用函数和用法

Unity Shader编辑器工具类ShaderUtil 常用函数和用法 Unity的Shader编辑器工具类ShaderUtil提供了一系列函数,用于编译、导入和管理着色器。本文将介绍ShaderUtil类中的常用函数和用法。 编译和导入函数 CompileShader 函数签名:public static bool C…

一百四十三、Linux——Linux的CentOS 7系统语言由中文改成英文

一、目的 之前安装CentOS 7系统的时候把语言设置成中文,结果Linux文件夹命名出现中文乱码的问题,于是决定把Linux系统语言由中文改成英文 二、实施步骤 (一)到etc目录下,找到配置文件locale.conf # cd /etc/ # ls…

Vue3 第三节 计算属性,监视属性,生命周期

1.computed计算属性 2.watch监视函数 3.watchEffect函数 4.Vue的生命周期函数 一.computed计算属性 计算属性简写和完整写法 <template><h1>一个人的信息</h1>姓&#xff1a;<input type"text" v-model"person.firstName" />…

100G光模块的应用案例分析:电信、云计算和大数据领域

100G光模块是一种高速光模块&#xff0c;由于其高速率和低延迟的特性&#xff0c;在电信、云计算和大数据领域得到了广泛的应用。在本文中&#xff0c;我们将深入探讨100G光模块在这三个领域的应用案例。 一、电信领域 在电信领域&#xff0c;100G光模块被广泛用于构建高速通…

什么是应用的贴身防护盾?来看F5洞察风险

从云原生的发展来看&#xff0c;由于云原生技术的革新以及现代应用随之进化&#xff0c;可以清晰地看到云原生吞噬一切的势头&#xff0c;但是云原生也面临着众多挑战。2022 年很多公开调查报告显示&#xff0c;在云原生发展中&#xff0c;CEO/CIO 最关注的就是云原生安全&…

FFmpeg将编码后数据保存成mp4

以下测试代码实现的功能是&#xff1a;持续从内存块中获取原始数据&#xff0c;然后依次进行解码、编码、最后保存成mp4视频文件。 可保存成单个视频文件&#xff0c;也可指定每个视频文件的总帧数&#xff0c;保存多个视频文件。 为了便于查看和修改&#xff0c;这里将可独立的…

SpringBoot整合Sfl4j+logback的实践

一、概述 对于一个web项目来说&#xff0c;日志框架是必不可少的&#xff0c;日志的记录可以帮助我们在开发以及维护过程中快速的定位错误。slf4j,log4j,logback,JDK Logging等这些日志框架都是我们常见的日志框架&#xff0c;本文主要介绍这些常见的日志框架关系和SpringBoot…

自然语言处理: 第六章Transformer- 现代大模型的基石

理论基础 Transformer&#xff08;来自2017年google发表的Attention Is All You Need (arxiv.org) &#xff09;&#xff0c;接上面一篇attention之后&#xff0c;transformer是基于自注意力基础上引申出来的结构&#xff0c;其主要解决了seq2seq的两个问题: 考虑了原序列和目…

拦截器对接口细粒度权限校验

文章目录 一、逻辑分析二、校验规则1.规则类型2.规则划分3.规则配置信息4.规则案例说明5.规则加载 三、拦截器定义1.自定义拦截器2.注册拦截器 四、获取请求参数1.获取get提交方式参数2.获取post提交方式参数&#xff08;1&#xff09;定义RequestWrapper类&#xff08;2&#…

【知网检索】2023年金融,贸易和商业管理国际学术会议(FTBM2023)

随着经济全球化&#xff0c;贸易自由化的进程加快&#xff0c;我国经济对外开放程度不断加深&#xff0c;正在加快融入世界经济一体化当中。当今世界各国竞争过程中&#xff0c;金融、贸易以及商业形态已成为其关键与焦点竞争内容。 2023年金融、贸易和商业管理国际学术会议(F…

科技云报道:向量数据库:AI时代的下一个热点

科技云报道原创。 最近&#xff0c;又一个概念火了——向量数据库。 随着大模型带来的应用需求提升&#xff0c;4月以来多家海外知名向量数据库创业企业传出融资喜讯。 4月28日&#xff0c;向量数据库平台Pinecone宣布获得1亿美元&#xff08;约7亿元&#xff09;B轮融资&am…

尚品汇总结七:商品详情模块(面试专用)

一、业务介绍 订单业务在整个电商平台中处于核心位置&#xff0c;也是比较复杂的一块业务。是把“物”变为“钱”的一个中转站。 整个订单模块一共分四部分组成&#xff1a; 结算页面 在购物车列表页面中,有一个结算的按钮,用户一点击这个按钮时,跳转到结算页,结算页展示了用…

ROS实现机器人移动

开源项目 使用是github上六合机器人工坊的项目。 https://github.com/6-robot/wpr_simulation.git 机器人运动模型 运动模型如下所示&#xff1a;&#x1f447; 机器人运动的消息包&#xff1a; 实现思路&#xff1a;&#x1f447;   为什么要使用/cmd_vel话题。因为这…

2023应急指挥系统总体架构方案 PPT

导读&#xff1a;原文《应急指挥系统总体架构方案PPT》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。 完整版领取方式 完整版领取方式&#xff1a; 如需获取完整的电…