金華房滑動驗證碼破解_阿里驗證(複雜)
阿新 • • 發佈:2022-05-18
需求:
第一次訪問金華房網(https://www.0579fw.com/
)需要進行滑塊校驗,經過判斷此驗證碼為阿里雲驗證碼,但不同於12306、淘寶的驗證碼校驗,現需要對網站滑塊進行驗證碼破解並獲取相應的cookie進行網站資料的採集,滑塊樣式如下:
1. 分析驗證碼來源
經過抓包分析驗證碼來源於案例滑塊驗證碼
2. 確認模擬滑動思路
可以採集用的方案:
- 通過selenium直接進行滑動
- 通過chrome debug模式啟動 + selenium 進行滑動
- 通過chrome debug模式啟動 + selenium + pupynput 進行滑動
- 通過ichrome直接進行滑動
- 通過ichrome + pupynput 進行滑動
- 通過chrome debug模式啟動 + ichrome + pupynput 進行滑動
選取方案:
由於selenium的特徵值比較多,且前端對於selenium的校驗比較簡單容易被識別,所以直接採用ichrome(基於谷歌的CDP協議開發出來的一個自動化框架)進行滑動。
實行方案四程式碼:
import asyncio from ichrome import AsyncChromeDaemon class Crawler: def __init__(self, port): self.port = port self.start_url = 'https://www.0579fw.com/' self.span_tab = '#nc_1__scale_text > span' self.cookie = '' async def get_cookie(self): async with AsyncChromeDaemon(host="127.0.0.1", port=self.port, headless=False, debug=False) as cd: async with cd.connect_tab(index=0, auto_close=True) as tab: await tab.goto(self.start_url, timeout=5) await asyncio.sleep(2) title = await tab.title if "滑動驗證頁面" in title: aaa = await tab.get_element_clip(self.span_tab) start_x = aaa['x'] start_y = aaa['y'] # 滑動滑塊 await tab.mouse_drag_rel_chain(start_x, start_y).move(300, 0, 1) await asyncio.sleep(300) if __name__ == '__main__': loop = asyncio.get_event_loop() crawler = Crawler(9678) loop.run_until_complete(crawler.get_cookie())
方案四存在的問題:
通過對上面的程式碼進行分析,雖然滑塊可以正常的滑動到正確的位置,但是由於網站一部分的校驗無法通過最終校驗,一直重複重新整理驗證碼,如果將移動滑塊進行註釋,手動進行滑動滑塊可以正常通過最終校驗,故放棄採用方案四
方案五存在的問題:
方案五隻是在方案四的基礎上改變了滑動滑塊實現的方法,經過測試依然存在於方案四相同的問題,無法通過最終校驗,故放棄採用方案五
方案六程式碼思路:
- 通過命令列啟動chrome debug模式
- 通過ichrom中的Chrome連線到debug模式的chrome例項中
- 通過pywin32獲取到視窗座標及視窗介面的截圖
- 查詢滑塊的位置
- 計算運動軌跡
- 通過pynput進行滑動
方案六程式碼(最終程式碼):
import os
import time
import random
import shutil
import aircv as ac
from ichrome import Chrome
import win32con, win32gui, win32ui
from pynput.mouse import Button, Controller as c1
USER_DATA_DIR = r"D:\ichrome_user_data\chrome_9222"
COOKIE_STR = ""
def get_trace():
"""
生成執行軌跡
"""
lu = [0.7, 0.3]
# 建立存放軌跡資訊的列表
trace = []
faster_distance = 260
for i in lu:
the_distance = i * faster_distance
# 設定初始位置、初始速度、時間間隔
start, v0, t = 0, 0, 1
# 當尚未移動到終點時
while start < the_distance:
# 如果處於加速階段
if start < the_distance:
# 設定加速度為2
a = 30
# 如果處於減速階段
else:
# 設定加速度為-3
a = -30
# 移動的距離公式
move = v0 * t + 1 / 2 * a * t * t
# 此刻速度
v = v0 + a * t
# 重置初速度
v0 = v
# 重置起點
start += move
# 將移動的距離加入軌跡列表
trace.append(round(move, 2))
# 返回軌跡資訊
return trace
def get_run_chrome():
"""
debug模式開啟遊覽器
"""
cmd_line = "start chrome.exe --remote-debugging-port=9222 --user-data-dir={} --disable-gpu --no-first-run".format(USER_DATA_DIR)
os.system(cmd_line)
def show_chrome_top(hwnd):
"""
將視窗至於前方
"""
win32gui.SetForegroundWindow(hwnd)
def save_chrome_image(hwnd, img_name='output.png'):
"""
儲存視窗圖片
"""
# 獲取視窗的座標位置
left, top, right, bot = win32gui.GetWindowRect(hwnd)
width = right - left
height = bot - top
# 儲存圖片相關
hWndDC = win32gui.GetWindowDC(hwnd)
mfcDC = win32ui.CreateDCFromHandle(hWndDC)
saveDC = mfcDC.CreateCompatibleDC()
saveBitMap = win32ui.CreateBitmap()
saveBitMap.CreateCompatibleBitmap(mfcDC, width, height)
saveDC.SelectObject(saveBitMap)
saveDC.BitBlt((0,0), (width, height), mfcDC, (0, 0), win32con.SRCCOPY)
saveBitMap.SaveBitmapFile(saveDC, img_name)
def get_box_coordinate(imgsrc, imgobj, confidencevalue=0.5):
"""
imgsrc: 原圖
imgobj: 要查詢的圖片(部分圖片)
"""
imsrc = ac.imread(imgsrc)
imobj = ac.imread(imgobj)
match_result = ac.find_template(imsrc, imobj, confidencevalue)
if match_result is None:
return None
else:
return match_result.get('result')
def close_chrome(port=9222):
find_port= 'netstat -aon | findstr %s' % port
result = os.popen(find_port)
text = result.read()
jobs = text.split('\n')
for job in jobs:
pid = job.strip().split(' ')[-1]
find_kill = 'taskkill -f -pid %s' % pid
os.popen(find_kill)
def clear_chrome_logs():
shutil.rmtree(USER_DATA_DIR)
# cmd_line = "del /F /S /Q {}".format(USER_DATA_DIR)
# print(cmd_line)
# os.popen(cmd_line)
def get_cookie():
global COOKIE_STR
clear_chrome_logs()
get_run_chrome()
time.sleep(3)
chrome=Chrome(port=9222)
tab = chrome.tabs[0]
tab.set_url('https://www.0579fw.com/')
time.sleep(1)
title = tab.title
if "滑動驗證頁面" in title:
# 1. 獲取視窗控制代碼
hwnd = win32gui.FindWindow(0, "滑動驗證頁面 - Google Chrome")
# 2. 顯示視窗
show_chrome_top(hwnd)
# 3. 儲存遊覽器圖片
save_chrome_image(hwnd, img_name='output.png')
# 4. 獲取滑塊的座標
coordinate = get_box_coordinate('output.png', 'box.png')
if coordinate is not None:
left, top, right, bot = win32gui.GetWindowRect(hwnd)
mouse = c1()
x_coordinate = left + coordinate[0]
y_coordinate = top + coordinate[1]
# 5. 開始模擬滑動
mouse.position = (x_coordinate, y_coordinate)
mouse.press(Button.left)
time.sleep(1 + random.random())
trace = get_trace()
for d in trace:
mouse.move(d, 0)
time.sleep(random.random() / 10)
time.sleep(random.random())
mouse.release(Button.left)
time.sleep(3)
cookies = tab.get_cookies()
for cookie in cookies:
if cookie['name'] == 'acw_sc__v3':
COOKIE_STR = "{}={}".format(cookie['name'], cookie['value'])
break
if __name__ == "__main__":
try:
get_cookie()
except Exception as e:
print("error: {}".format(e))
close_chrome()