首页 > 编程语言 >Python识别海外版抖音Tiktok、巨量引擎滑块验证码识别

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

时间:2023-08-24 22:47:30浏览次数:96  
标签:xpath 滑块 img format Python driver element 识别 find

闲的无聊搞了一个相对简单的验证码,就是抖音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
# Python学习交流Q裙:708525271
# 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('[email protected]')
 
    # 等待【密码】元素出现
    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 也请各位大神指点。所以我代码使用的巨量引擎(巨量引擎是字节跳动旗下的品牌)网站进行的测试。

好了,文章分享到这里就结束了,下次再见!

um.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编码defPIL_base64(img, coding='utf-8'): img_format = img.formatif 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 # 验证码识别接口defshibie(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()defrun(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('[email protected]')# 等待【密码】元素出现 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 inrange(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:breakif __name__ =='__main__': run(headless=False)

标签:xpath,滑块,img,format,Python,driver,element,识别,find
From: https://www.cnblogs.com/hahaa/p/17623824.html

相关文章

  • Python教程:方法重载
    方法重载在Python中起着关键作用。方法有时接受零参数,有时接受一个或多个参数。当我们以不同的方式调用同一个方法时,这就被称为方法重载。Python不像其他语言那样默认支持重载方法。在Python中,两个或多个方法不能有相同的名字,因为方法重载允许我们使同一个操作符具有不同的含义......
  • Python 中如何向列表或数组添加元素
    1.Python中的列表是什么?给初学者的定义编程中的数组是一个有序的项目集合,所有的项目都需要是相同的数据类型。然而,与其它编程语言不同,数组在Python中不是一个内置的数据结构。Python使用列表取代传统的数组。列表本质上是动态数组,是Python中最常见的和最强大的数据结构之......
  • python调用SAP脚本下载库存报表MB52
    importmathimportos,sys,win32com.clientimportclipboardfrompprintimportpprintimportcsvdefget_mb52(session,args={},plant='0001'):result=download_from_sap(session,args=args,plant=plant)ifnotresult:#n......
  • Python教程:Gzip解压缩
    我们将介绍Python中的gzip解压。我们还将介绍如何使用gzip解压来解压压缩的内容。Python中的Gzip解压在Python中为压缩和解压目的建立了许多库,但我们将介绍Gzip库。它是一个流行的数据压缩工具。我们可以使用gzip,通过对数据进行特殊格式的编码来减少文件的大小,这种格式不......
  • Python SAP 脚本定时自动下载资产清单 S_ALR_87011990
    业务场景使用了外部工作流系统管理固定资产申请,转移(负责人变更),盘点,报废等涉及固定资产的业务,而固定资产采购,折旧等仍在SAP中进行,所以需要定时从SAP中下载包括固定资产账面值的固定资产清单,以作为工作流审批节点流转的依据主要功能说明定时运行自动登录SAP下载SAP固定资......
  • Python虚拟环境
    以前在打比赛和做项目的时候都一直都没有注重管理python包,以至于把所有的包都堆到Anaconda下,以前出现包问题的时候能百度解决的解决,结局不了就卸了重装,感觉没什么。最近开始做一些项目,在自己的电脑上做好,去别的地方打包运行,结果要配两次环境非常的麻烦,所以开始认真对待起不同项目......
  • Python 项目以及常见的目录结构
    当今世界,Python可以说是最受欢迎的编程语言之一。作为一种高级动态语言,Python具有简单易学、代码可读性强和生态系统丰富等特点,广泛应用于Web开发、数据科学、机器学习、网络爬虫等领域。在Python项目中,良好的目录结构设计是一个成功项目的关键因素之一。Python项......
  • python 中 if __name__ == '__main__'
    当我们编写Python模块时,有时候需要让某些代码只在该模块作为主程序运行时才执行,而不是被其他模块import引入时就执行。这时候可以使用if__name__=='__main__'这个条件语句。什么是 name 变量在Python中,每个模块(Python文件)都有一个内置变量__name__,用于指示当前模......
  • 使用 conda 管理电脑多个 python 版本
    背景之前一直使用python自带的虚拟环境管理工具(virtualen包),虽然很舒服,可以有不同的软件包环境,但是所有环境都只能基于一个python版本。由于历史原因,系统(Ubuntu)升级时给我新增了一个python3.11,我索性就只保留了这一个版本。这两天要使用open3d,结果发现不支持最新版本的......
  • python独立脚本应用Django项目的环境
    一、需求说明一直用Django在开发一个网站项目,其中的注册用户和登录,都是使用Django自带的认证系统。主要是对密码的加密,在注册或者登录的时候,前端传递多来的密码,我会使用Django的set_password()方法在加密一次经过加密后的数据库中的数据样子如下:......