百度文库AI中文成语点选识别

最近百度文库又出了新验证码。在出现AI旋转验证码之后,又出现了AI中文成语点选。看样子验证码的未来发展路径是全面走向AI。出现这样的情况是谁都不想看到的。由于AI的随机性,未来识别可能会越来越难。

下图就是百度最新的AI中文成语点选的样例图

图片

没有办法,我们只能用AI去打败AI。经过我们不懈努力,我们终于完成了这款验证码的识别工作。经过几天多轮的测试。正确率达到了惊人的98%左右。

废话不多说,直接上代码。我这里使用的是python+selenium的方式,大家直接运行,可以更加直观看到点击识别的效果。如果想使用js逆向,请各位大神自行研究。

python版本是3.7,selenium==3.141.0

import os
import io
import sys
import time
import random
import base64
import requests
from io import BytesIO
from PIL import Image, ImageDraw
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.support.select import Select
from selenium.webdriver import FirefoxOptions


# 用户的key
key = ''
# 记录成功次数
t = 0
# 记录失败次数
f = 0
# 打开邮政页面
option = FirefoxOptions()
# option.add_argument('--headless')
driver = webdriver.Firefox(executable_path=r'webdriver\geckodriver.exe', options=option)

#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)
    # base64_str = base64.b64encode(byte_data).decode(coding)

    return base64_str

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

    # 发送请求调用接口
    response = requests.post(url=url, json=data, headers=header)
    # 判断是否正确请求
    if response.json()['code'] == 200:
        return eval(response.json()['data']['res_str'])
    else:
        print('参数错误,请前往得塔云了解详情:https://www.detayun.cn/tool/verifyCodeHomePage2/?_=1714093687434')
        print('错误参数:', response.json())
        return None


for i in range(2000):
    driver.get('https://seccaptcha.baidu.com/v1/webapi/verint/svcp.html?ak=M7bcdh2k6uqtYV5miaRiI8m8x6LIaONq&backurl=https%3A%2F%2Fwenku.baidu.com%2F%3F_wkts_%3D1705066238641&ext=ih2lW9VV3PmxmO%2B%2Bx8wZgk9i1xGx9WH05J9hI74kTEVkpokzRQ8QxLB082MG2VoQUUT15llYBwsC%2BAaysNoPxpuKg0Hkpo4qMzBjXDEGhuQ%3D&subid=pc_home&ts=1705066239&sign=1cebe634245cd92fc9eca10d0850a36b')
    time.sleep(3)

    html_str = driver.page_source
    if 'canvas' in html_str:
        if '请依次点击' in html_str:
            print('中文验证码')
            for j in range(2000):
                # 获取中文
                WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//div[@class="b6991750d5 "]'))
                word_tag = driver.find_element_by_xpath('//div[@class="b6991750d5 "]')
                # 获取<div>元素及其子元素的文本内容
                old_word =  word_tag.text  # 用于与刷新后对比
                words = word_tag.text
                words = str(words).replace('请依次点击','').replace('"','').replace(' ','')
                print('页面点击中文:', words)

                # 等待画布加载完成
                WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('/html/body/div/div[2]/div/div/div/div[2]/canvas'))
                canvas_list = driver.find_elements_by_xpath('/html/body/div/div[2]/div/div/div/div[2]/canvas')
                # 图片列表
                img_list = []
                # 遍历所有的画布元素
                for canvas in canvas_list:
                    # 使用JavaScript获取canvas的内容,并在WebDriver对象上调用execute_script
                    canvas_content = driver.execute_script("return arguments[0].toDataURL('image/png');", canvas)
                    # 将base64编码的图片内容解码为字节
                    img_bytes = base64.b64decode(canvas_content.split(',')[1])
                    # 将字节转换为图片对象
                    img = Image.open(io.BytesIO(img_bytes))
                    img_list.append(img)

                # 合并所有图片为一张
                # 创建一个新的图片对象,用于合并所有的图片
                merged_img = Image.new('RGBA', (max(img.size[0] for img in img_list), max(img.size[1] for img in img_list)))

                # 将每个图片合并到merged_img上,保持透明度
                y_offset = 0
                for img in img_list:
                    # 计算x偏移量以保持图片对齐(这里假设所有图片宽度相同)
                    x_offset = 0
                    # 将图片合并到merged_img上,保持透明度
                    merged_img.paste(img, (x_offset, y_offset), img)

                # png图片转
                # 如果是png图片
                if str(merged_img.format).lower() == 'png':
                    # 输出颜色模式
                    if merged_img.mode == 'RGBA':
                        # 创建一个新的白色背景图像
                        white_background = Image.new('RGBA', merged_img.size, (255, 255, 255, 255))
                        # 创建一个可以在白色背景上绘图的对象
                        draw = ImageDraw.Draw(white_background)
                        # 将原始的PNG图像粘贴到白色背景上,使用一个全白色的图像作为蒙版
                        white_background.paste(merged_img, mask=merged_img)
                        merged_img = white_background
                        # img = img.convert('RGB')

                # 转换为JPG格式
                # 创建一个BytesIO对象
                output = io.BytesIO()
                # 将PNG图像转换为JPG格式并保存到BytesIO对象中
                merged_img.convert('RGB').save(output, 'JPEG')
                # 通过BytesIO对象创建PIL对象
                merged_img = Image.open(output)

                # 识别图片
                y = shibie(merged_img, words)
                if y == None:
                    break
                print('识别结果:',y)

                # 页面点击
                ele = driver.find_element_by_xpath('//div[@class="b9c1b9d670"]')
                # 顺序点击文字
                for point in y:
                    ActionChains(driver).move_to_element_with_offset(ele, point[0], point[1]).click().perform()
                    time.sleep(0.5)

                # 判断是否成功 app
                try:
                    WebDriverWait(driver, 5).until(lambda x: x.find_element_by_xpath('//div[@id="app"]'))
                    t += 1
                    print('成功')
                    print('总次数:{},成功:{},失败:{},正确率:{}'.format(t + f, t, f, t / (t + f)))
                    break
                except:
                    f += 1
                    print('失败')
                    name = int(time.time() * 1000)
                    # 保存合并后的图片到文件
                    merged_img.save('error_img/{}.jpg'.format(name))

                    print('总次数:{},成功:{},失败:{},正确率:{}'.format(t + f, t, f, t / (t + f)))

                    # 点击刷新按钮
                    WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//a[@class="b559997a43 b01b817824"]'))
                    shuaxin_tag = driver.find_element_by_xpath('//a[@class="b559997a43 b01b817824"]')
                    shuaxin_tag.click()

                    # 判断是否刷新成功
                    is_break = False
                    for k in range(20):
                        try:
                            WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//div[@class="b6991750d5 "]'))
                        except:
                            is_break = True
                            break
                        word_tag = driver.find_element_by_xpath('//div[@class="b6991750d5 "]')
                        # 获取<div>元素及其子元素的文本内容
                        try:
                            if '加载中...' == word_tag.text:
                                time.sleep(1)
                                continue

                            if old_word != word_tag.text:
                                break
                            else:
                                time.sleep(1)
                                continue
                        except:
                            time.sleep(2)
                            continue

                    if is_break:
                        break

                    time.sleep(5)

想了解更多验证码识别,请访问:得塔云

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-05-10 16:38:06       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-10 16:38:06       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-10 16:38:06       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-10 16:38:06       18 阅读

热门阅读

  1. 【C++ list所有函数举例如何使用】

    2024-05-10 16:38:06       11 阅读
  2. 【AAGNet】GNN模型用于BREP数模分割代码复现笔记

    2024-05-10 16:38:06       12 阅读
  3. 将每个Excel文件的数据量统一减少至120000行

    2024-05-10 16:38:06       13 阅读
  4. 商城数据库88张表DDL(71-88)

    2024-05-10 16:38:06       11 阅读
  5. 典型相关分析模型评价的标准和代码

    2024-05-10 16:38:06       9 阅读
  6. 设置docker容器时区

    2024-05-10 16:38:06       10 阅读
  7. leetcode55-Jump Game

    2024-05-10 16:38:06       10 阅读
  8. leetcode53-Maximum Subarray

    2024-05-10 16:38:06       10 阅读
  9. Gateway基础配置指南

    2024-05-10 16:38:06       9 阅读