概要
在对某网站进行访问时,有时会出现旋转图片的验证码(如下图),这会对我们的正常访问造成困扰,因此我想能不能写一个脚本来自动解决这种困扰。
工具
- python
- selenium 浏览器自动化库
步骤
前置步骤
- 安装selenium并使其与当前电脑的谷歌浏览器版本相匹配,这里不再赘述
- 准备一个验证码测试界面,这里使用百度验证码
具体步骤
1. 使用 selenium 打开图片并获取图片src
from selenium.webdriver import Chrome
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
test_url = 'https://wappass.baidu.com/static/captcha/tuxing.html?ak=33c48884b7df83d4230e07cbcd0d07fd&backurl=https%3A%2F%2Faiqicha.baidu.com×tamp=1634288600&signature=02fafac36a570b03a3c9100ec68b02e5'
# 实例化一个浏览器对象
browser = Chrome()
# 访问网站
browser.get(test_url)
# 隐式等待寻找图片元素
img = WebDriverWait(browser, 3).until(
EC.presence_of_element_located((By.CLASS_NAME, 'vcode-spin-img'))
)
# 获取图片元素的src
img_src = img.get_attribute('src')
2. 解析图片
解析图片有多种方式,这里使用api解析图片
import re
import base64
from requests import get, post
from io import BytesIO
# 将图片转化为base64格式
def get_img_base64(self, url):
res = get(url)
return 'data:image/jpeg;base64,' + str(base64.b64encode(BytesIO(res.content).read())).replace("b'", '').replace("'", '')
# 获取图片旋转角度
def get_operator(img_base64):
url = 'https://www.detayun.cn/openapi/verify_code_identify/'
data = {
'key': 'xxxxxxxxxxxxxxxx', # 在https://www.detayun.cn/openapi处申请key
'verify_idf_id': '9', # 9表示旋转图片,详情见api帮助文档
'img_base64': img_base64,
'words': '' # 这里不适用
}
res = post(url, data=data)
if res.status_code == 200:
angel = re.findall('(\\d+)', res.json()['data']['res_str'])[0]
offset = int(angel) / 360 * 211
drag_and_drop(offset)
3. 旋转图片
# 执行图片旋转
# 下面两个定义了每次旋转的角度,使其更符合人类实际操作
def ease_out_quart(x):
return 1 - pow(1 - x, 4)
def get_tracks(distance, seconds):
tracks = [0]
offsets = [0]
for t in np.arange(0.0, seconds, 0.05):
offset = round(ease_out_quart(t / seconds) * distance)
tracks.append(offset - offsets[-1])
offsets.append(offset)
return offsets, tracks
# 旋转操作
def drag_and_drop(offset):
# 找到需要拖动的元素
btn = WebDriverWait(browser, 3).until(
EC.presence_of_element_located((By.CLASS_NAME, 'vcode-spin-button'))
)
# 计算出每次滑动的距离
offset, tracks = get_tracks(offset, 1.5)
# 按住元素
ActionChains(browser).click_and_hold(btn).perform()
# 拖动元素
for x in tracks:
ActionChains(browser).move_by_offset(x, 0).perform()
# 短暂停止后松开鼠标
ActionChains(browser).pause(0.3).release().perform()