Python+dddocr實現(xiàn)自動化通過多缺口滑塊驗證
一、什么是滑塊驗證
滑塊驗證是一種常見的反爬蟲手段,用戶需要按住滑塊拖動到指定位置,才能通過驗證。多缺口滑塊驗證則是在背景圖上有多個缺口,滑塊需要精確拖動到正確的缺口位置。
手動操作很簡單,但自動化通過卻難倒了不少爬蟲新手。本文將帶你用 Python + DrissionPage 實現(xiàn)自動化滑塊驗證。
二、核心思路
- 識別滑塊和背景圖:獲取頁面上的滑塊和背景圖片。
- 識別缺口位置:用 OCR 或圖像處理算法識別缺口的準確位置。
- 模擬人類拖動滑塊:用代碼模擬鼠標按下、移動、釋放,完成滑塊驗證。
三、代碼實戰(zhàn)
1. 環(huán)境準備
- Python 3.8+
- DrissionPage
- pillow(用于圖片處理)
- ddddocr(滑塊識別)
pip install DrissionPage pillow ddddocr
2. 主要代碼結(jié)構(gòu)
2.1 滑塊識別核心:recognize_slider_distance
滑塊驗證的關(guān)鍵是如何準確識別滑塊需要移動的距離。下面詳細講解 recognize_slider_distance 的實現(xiàn)原理和代碼:
import base64
import numpy as np
from PIL import Image
import io
import ddddocr
def base64_decode(str):
return base64.b64decode(str)
def slider_puzzle_qg(p_puzzle_path: str = ''):
"""
將小拼圖去除透明邊緣,返回處理后的base64圖片和位置信息
"""
image = Image.open(p_puzzle_path)
width, height = image.size
pixels = image.load()
_a = 0 # 頂部透明行數(shù)
_b = 0 # 有效拼圖高度
_c = 0 # 底部透明行數(shù)
k = [] # 有效像素
buffered = io.BytesIO()
for x in range(height):
data_pixel = []
for y in range(width):
r, g, b, a = pixels[y, x]
data_pixel += [(r, g, b, a)]
NumPy_data_pixel = np.array(data_pixel)
if np.all(NumPy_data_pixel == 0):
if _b == 0:
_a += 1
else:
if _c == 0:
new_image = Image.new('RGBA', (width, _b), color=(0, 0, 0, 0))
new_image.putdata(k)
new_image.save(buffered, format="PNG")
_c += 1
else:
_b += 1
k += data_pixel
return {
'最頂層-頂層距離': _a,
'中間層-拼圖的高度': _b,
'最底層-底層距離': _c,
'base64': base64.b64encode(buffered.getvalue()).decode()
}
def background_cutting(b_puzzle_path: str = '', b_size_h: int = 0, p_size_h: int = 0):
"""
按小拼圖的高度切割背景圖,返回base64
"""
image = Image.open(b_puzzle_path)
width, height = image.size
left, right = 0, width
top, bottom = b_size_h, b_size_h + p_size_h
cropped_image = image.crop((left, top, right, bottom))
buffered = io.BytesIO()
cropped_image.save(buffered, format="PNG")
return {'base64': base64.b64encode(buffered.getvalue()).decode()}
def recognize_slider_distance(xiaopintu_path, beijingtu_path):
"""
識別滑塊需要移動的距離
:param xiaopintu_path: 小拼圖路徑
:param beijingtu_path: 背景圖路徑
:return: 滑動距離
"""
det = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False)
xiaopintu_data = slider_puzzle_qg(p_puzzle_path=xiaopintu_path)
beijingtu_data = background_cutting(b_puzzle_path=beijingtu_path, b_size_h=xiaopintu_data['最頂層-頂層距離'],
p_size_h=xiaopintu_data['中間層-拼圖的高度'])
res1 = det.slide_match(base64_decode(beijingtu_data['base64']), base64_decode(xiaopintu_data['base64']),
simple_target=True)
res1 = res1['target'][0]
# 為了更像人類操作,可以加一點偏移
res = res1 * 1.1 - 4
return res
原理說明:
- 先用
slider_puzzle_qg去除小拼圖的透明邊緣,獲得有效區(qū)域和高度。 - 用
background_cutting按小拼圖的高度切割背景圖,獲得滑道。 - 用 ddddocr 的
slide_match方法,計算小拼圖在滑道中的最佳匹配位置(即缺口橫坐標)。 - 最后加一點偏移,模擬人類誤差,防止被反爬蟲檢測。
2.2 登錄與滑塊拖動
下面是完整的登錄與滑塊拖動自動化代碼示例,適合新手理解:
import random
import time
import base64
from DrissionPage import Chromium, ChromiumOptions
from utils.ocr_util import recognize_slider_distance # 上文已詳細講解
from service.logger import logger
# 創(chuàng)建瀏覽器實例
co = ChromiumOptions().set_browser_path(r'C:\Path\To\chrome.exe')
tab = Chromium().latest_tab
def base64_decode(data):
return base64.b64decode(data + '==')
def login_with_slider(tab, username, password):
try:
# 1. 打開登錄頁面(URL已脫敏)
tab.get('https://your-domain.com/login')
# 2. 輸入賬號密碼
username_ele = tab.ele('@@tag()=input@@placeholder=請輸入賬號')
password_ele = tab.ele('@@tag()=input@@placeholder=請輸入密碼')
username_ele.input(username)
password_ele.input(password)
# 3. 點擊登錄按鈕
login_button = tab.ele('@@tag()=span@@text():登 錄')
login_button.click(by_js=True)
# 4. 獲取滑塊和背景圖片
background_image_ele = tab.ele('@@tag()=div@@class=verify-img-panel').ele('@@tag()=img')
gap_image_ele = tab.ele('@@tag()=div@@class=verify-sub-block').ele('@@tag()=img')
xiaopintu_data = gap_image_ele.attr('src').split("data:image/png;base64,")[-1]
background_img_data = background_image_ele.attr('src').split("data:image/png;base64,")[-1]
with open('beijingtu.png', 'wb') as f:
f.write(base64_decode(background_img_data))
with open('xiaopintu.png', 'wb') as f:
f.write(base64_decode(xiaopintu_data))
# 5. 識別滑塊需要移動的距離
distance = recognize_slider_distance(xiaopintu_path="xiaopintu.png", beijingtu_path="beijingtu.png")
tab.wait.ele_displayed('@@tag()=div@@class=verify-move-block', timeout=10)
slider = tab.ele('@@tag()=div@@class=verify-move-block').wait.clickable(timeout=10)
if not slider:
logger.error('未找到滑塊元素,請檢查類名或頁面結(jié)構(gòu)')
return False
else:
tab.run_js('arguments[0].style.border="2px solid red"', slider)
logger.info(' 找到滑塊元素,開始滑動')
# 6. 獲取滑塊中心點坐標
slider_rect = tab.run_js('''
const rect = arguments[0].getBoundingClientRect();
return {
x: rect.x + rect.width / 2,
y: rect.y + rect.height / 2
}
''', slider)
try:
# 7. 用 JS 模擬鼠標事件拖動滑塊
tab.run_js('''
function simulateMouseEvent(element, eventType, x, y) {
const event = new MouseEvent(eventType, {
view: window,
bubbles: true,
cancelable: true,
clientX: x,
clientY: y
});
element.dispatchEvent(event);
}
const slider = arguments[0];
const startX = arguments[1];
const startY = arguments[2];
const distance = arguments[3];
simulateMouseEvent(slider, 'mousedown', startX, startY);
const segments = 5;
const segmentDistance = distance / segments;
let currentX = startX;
for (let i = 0; i < segments; i++) {
currentX += segmentDistance;
simulateMouseEvent(slider, 'mousemove', currentX, startY);
}
currentX -= 5;
simulateMouseEvent(slider, 'mousemove', currentX, startY);
simulateMouseEvent(slider, 'mouseup', currentX, startY);
''', slider, slider_rect['x'], slider_rect['y'], distance)
logger.info(' 滑動操作已發(fā)送')
time.sleep(1)
except Exception as e:
logger.error(f' 滑動出錯: {e}')
return False
# 8. 后續(xù)驗證、UKey等操作略
return True
except Exception as e:
logger.error(f"登錄失敗,錯誤信息:{e}")
return False
代碼說明:
步驟1-3:自動化輸入賬號、密碼并點擊登錄。
步驟4:獲取滑塊和背景圖片,保存為本地文件。
步驟5:調(diào)用 recognize_slider_distance 識別滑塊需要移動的距離。
步驟6:獲取滑塊元素的中心點坐標。
步驟7:用 JavaScript 分段模擬鼠標拖動滑塊,模擬人類操作。此處也可以使用drisionpage操作元素例如:
# 向右移動鼠標 # tab_.actions.right(distance - 10) time.sleep(0.05) # tab_.actions.right(10)
步驟8:后續(xù)如UKey驗證等可根據(jù)實際需求補充。
3. 關(guān)鍵技術(shù)點說明
- 圖片識別:
recognize_slider_distance利用 ddddocr 的滑塊識別能力,極大簡化了滑塊距離的計算。 - 圖片預(yù)處理:去除透明邊緣、切割滑道,是提升識別準確率的關(guān)鍵。
- JS 模擬鼠標事件:直接用 JS 觸發(fā)
mousedown、mousemove、mouseup,比傳統(tǒng)動作鏈更容易繞過部分反爬蟲。 - 分段移動:模擬人手抖動,分多段移動更像真人。
- 異常處理:每一步都要加 try/except,方便調(diào)試。
四、常見問題與排查
1.滑塊沒動?
- 檢查元素選擇器是否準確。
- 檢查 JS 事件是否被頁面攔截。
- 嘗試加大分段數(shù),或調(diào)整每段距離。
2.識別距離不準?
- 檢查圖片保存是否完整。
- 調(diào)整識別算法參數(shù)。
- 檢查小拼圖和背景圖的預(yù)處理是否正確。
3.驗證失敗?
- 檢查是否有額外的行為驗證(如軌跡分析、行為分析)。
- 嘗試加大拖動時間,模擬更慢的拖動。
五、總結(jié)
自動化通過多缺口滑塊驗證并不神秘,關(guān)鍵在于:
- 正確識別滑塊和缺口位置(圖片預(yù)處理+滑塊識別)
- 用 JS 或動作鏈模擬真實拖動
- 多調(diào)試、多嘗試,遇到問題多看日志
到此這篇關(guān)于Python+dddocr實現(xiàn)自動化通過多缺口滑塊驗證的文章就介紹到這了,更多相關(guān)Python滑塊驗證內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python應(yīng)用實現(xiàn)雙指數(shù)函數(shù)及擬合代碼實例
這篇文章主要介紹了Python應(yīng)用實現(xiàn)雙指數(shù)函數(shù)及擬合代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-06-06
Python小工具之消耗系統(tǒng)指定大小內(nèi)存的方法
今天小編就為大家分享一篇Python小工具之消耗系統(tǒng)指定大小內(nèi)存的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-12-12
用python修改excel表某一列內(nèi)容的操作方法
這篇文章主要介紹了用python修改excel表某一列內(nèi)容的操作代碼,在實現(xiàn)過程中用到openpyxl這個庫,要生成隨機數(shù)就要有random這個庫,具體代碼跟隨小編一起看看吧2021-06-06
Python通用函數(shù)實現(xiàn)數(shù)組計算的方法
數(shù)組的運算可以進行加減乘除,同時也可以將這些算數(shù)運算符進行任意的組合已達到效果。這篇文章主要介紹了Python通用函數(shù)實現(xiàn)數(shù)組計算的代碼,非常不錯,具有一定的參考借鑒價值,需要的朋友參考下吧2019-06-06
Django多數(shù)據(jù)庫配置及逆向生成model教程
這篇文章主要介紹了Django多數(shù)據(jù)庫配置及逆向生成model教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03
python實現(xiàn)簡單的超市商品銷售管理系統(tǒng)
這篇文章主要為大家詳細介紹了python實現(xiàn)超市商品銷售管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-11-11
Pytorch中實現(xiàn)CPU和GPU之間的切換的兩種方法
本文主要介紹了Pytorch中實現(xiàn)CPU和GPU之間的切換的兩種方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01

