一、前言
今天有空研究了一下这个移动的登录,发现获取手机验证码的时候会弹出一种旋转验证码。这种验证码确实挺头疼。所以顺便研究了一下如何识别。
验证码的样子大家先看一下。看看大家有没有什么更好是思路。
二、验证码识别
我这里就直接上代码。我这里是使用python+selenium来实现的。首先访问中国移动的登录页面。然后等待用户名输入框的出现,输入手机号。然后点击获取手机验证码。这个时候就会跳出上面的验证码。最后识别角度,把角度转换成滑动距离,最后验证通过。
我试验了一下,正确率基本上是100%通过。及时有一点偏差,也是在误差允许的范围内。
import os
import sys
import time
import random
import base64
import requests
import io
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需要注册得塔云网站获得,网站地址:http://www.detayun.cn
key = '9vMU6Ez5gmtaEuZe8iIw'
# 登录输入手机号
phone_number = '13911112222'
# 接口识别
def shibie(img1_base64, img2_base64):
# 验证码识别接口
url = "http://www.detayun.cn/openapi/verify_code_identify/"
data = {
# 用户的key
"key": key,
# 验证码类型
"verify_idf_id": "46",
# 外部矩形大图
"img1": img1_base64,
# 中间圆形小图
"img2": img2_base64,
}
header = {"Content-Type": "application/json"}
# 发送请求调用接口
response = requests.post(url=url, json=data, headers=header)
# 判断是否正确请求
if response.json()['code'] == 200:
return response.json()['data']['px_distance']
else:
print('参数错误,请前往得塔云了解详情:https://www.detayun.cn/tool/verifyCodeHomePage2/?_=1714093687434')
print('错误参数:', response.json())
return None
# 设置手机型号,这设置为iPhone 6
mobile_emulation = {"deviceName": "iPhone 6"}
options = webdriver.ChromeOptions()
options.add_experimental_option("mobileEmulation", mobile_emulation)
driver = webdriver.Chrome(executable_path='.\webdriver\chromedriver.exe', options=options)
# 访问登录页面 https://m.jf.10086.cn/#/pages/user/login/loginSms
driver.get('https://m.jf.10086.cn/#/pages/user/login/loginSms')
time.sleep(2)
# 等待手机输入框出现
WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//input[@class="weui-input"]'))
user_input = driver.find_element_by_xpath('//input[@class="weui-input"]')
user_input.send_keys(phone_number)
time.sleep(2)
# 等待获取验证码按钮
WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//taro-view-core[@class="suffix-btn hydrated"]'))
btn = driver.find_element_by_xpath('//taro-view-core[@class="suffix-btn hydrated"]')
btn.click()
# 等待验证码出现,获取大图
WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//taro-image-core[@class="hydrated"]/img[@class="taro-img__mode-scaletofill"]'))
b_img = driver.find_element_by_xpath('//taro-image-core[@class="hydrated"]/img[@class="taro-img__mode-scaletofill"]')
b_img_base64 = b_img.get_attribute('src')
# 等待验证码出现,获取小图
WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//img[@class="taro-img__mode-aspectfit"]'))
s_img = driver.find_element_by_xpath('//img[@class="taro-img__mode-aspectfit"]')
s_img_base64 = s_img.get_attribute('src')
# 识别图像
move_x = shibie(b_img_base64, s_img_base64)
print('识别滑动距离:{}px'.format(move_x))
# 等待滑块出现
WebDriverWait(driver, 20).until(lambda x: x.find_element_by_xpath('//taro-view-core[@class="verify-left-bar hydrated"]'))
tag = driver.find_element_by_xpath('//taro-view-core[@class="verify-left-bar hydrated"]')
# 滑动滑块
action = ActionChains(driver)
action.click_and_hold(tag).perform()
# 计算实际滑动距离 = 像素距离 + 前面空白距离
# action.move_by_offset(move_x, 5)
if move_x+11 < 238:
action.move_by_offset(move_x+11, 5)
action.move_by_offset(-15, -2)
action.move_by_offset(4, 3)
else:
action.move_by_offset(move_x - 11, 5)
action.move_by_offset(7, -2)
action.move_by_offset(4, 3)
action.release().perform()
想了解更多验证码识别,请访问:得塔云