1. 程式人生 > 其它 >金華房滑動驗證碼破解_阿里驗證(複雜)

金華房滑動驗證碼破解_阿里驗證(複雜)

需求:

第一次訪問金華房網(https://www.0579fw.com/)需要進行滑塊校驗,經過判斷此驗證碼為阿里雲驗證碼,但不同於12306、淘寶的驗證碼校驗,現需要對網站滑塊進行驗證碼破解並獲取相應的cookie進行網站資料的採集,滑塊樣式如下:

1. 分析驗證碼來源


經過抓包分析驗證碼來源於案例滑塊驗證碼

2. 確認模擬滑動思路

可以採集用的方案:

  1. 通過selenium直接進行滑動
  2. 通過chrome debug模式啟動 + selenium 進行滑動
  3. 通過chrome debug模式啟動 + selenium + pupynput 進行滑動
  4. 通過ichrome直接進行滑動
  5. 通過ichrome + pupynput 進行滑動
  6. 通過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())
方案四存在的問題:

通過對上面的程式碼進行分析,雖然滑塊可以正常的滑動到正確的位置,但是由於網站一部分的校驗無法通過最終校驗,一直重複重新整理驗證碼,如果將移動滑塊進行註釋,手動進行滑動滑塊可以正常通過最終校驗,故放棄採用方案四

方案五存在的問題:

方案五隻是在方案四的基礎上改變了滑動滑塊實現的方法,經過測試依然存在於方案四相同的問題,無法通過最終校驗,故放棄採用方案五

方案六程式碼思路:
  1. 通過命令列啟動chrome debug模式
  2. 通過ichrom中的Chrome連線到debug模式的chrome例項中
  3. 通過pywin32獲取到視窗座標及視窗介面的截圖
  4. 查詢滑塊的位置
  5. 計算運動軌跡
  6. 通過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()