目錄
一、引言
二、滑動驗證碼原理與反爬機制
2.1 驗證碼原理
2.2 反爬機制
三、工程實戰:滑動驗證碼識別全流程
3.1 工程準備
3.1.1 環境依賴
3.1.2 目標網站與驗證碼識別案例
3.2 核心破解流程
3.2.1 自動化打開網頁與登錄
3.2.2 獲取驗證碼圖片(適配縮放)
3.2.3 識別缺口左邊緣
3.2.4 計算滑動距離(左邊緣對齊)
3.2.5 生成自然滑動軌跡與回彈
3.2.6 按軌跡移動滑塊
3.2.7 主流程整合
結語
🎬 攻城獅7號:個人主頁
🔥 個人專欄:?《python爬蟲教程》
?? 君子慎獨!
?🌈 大家好,歡迎來訪我的博客!
?? 此篇文章主要介紹 滑動驗證碼 的識別
📚 本期文章收錄在《python爬蟲教程》,大家有興趣可以自行查看!
?? 歡迎各位 ?? 點贊 👍 收藏 ?留言 📝!
一、引言
????????隨著互聯網安全需求的提升,滑動驗證碼(Slider Captcha)已成為各大網站防止自動化攻擊和惡意爬蟲的主流手段之一。相比傳統的字符型驗證碼,滑動驗證碼通過人機交互和行為軌跡分析,大幅提升了破解難度。對于自動化測試、數據采集和安全研究者來說,如何精準識別和模擬滑動驗證碼,是一項極具挑戰性的工程任務。
??????? 本章將以實際工程代碼為主線,系統講解結合Selenium知識進行滑動驗證碼的識別與破解流程(不懂Selenium的請自行學習前面章節),涵蓋原理分析、反爬機制、核心代碼實現、調試技巧、常見問題與工程實戰經驗,幫助讀者掌握滑動驗證碼自動化識別的全流程。
二、滑動驗證碼原理與反爬機制
2.1 驗證碼原理
滑動驗證碼的基本流程是:
????????(1)用戶在頁面上看到一張帶有缺口的圖片和一個可拖動的滑塊。
????????(2)用戶需要按住滑塊,將其拖動到缺口處,使圖片拼合完整。
????????(3)系統通過前端和后端雙重校驗,判斷滑塊是否準確對齊缺口,并分析拖動軌跡是否自然。
滑動驗證碼的常見類型有:
????????- 拼圖型滑動驗證碼:最常見,用戶需將滑塊拖到缺口處。
????????- 軌跡型滑動驗證碼:要求用戶沿特定軌跡拖動滑塊。
????????- 多步驗證型:滑動后還需輸入字符或完成其他操作。
2.2 反爬機制
滑動驗證碼的反爬機制主要包括:
????????- 軌跡分析:檢測滑塊移動軌跡是否自然(加速度、抖動、停頓等)。
????????- 環境檢測:檢測瀏覽器指紋、User-Agent、Cookie、Referer 等參數。
????????- 圖片混淆:驗證碼圖片可能經過切片、加密、canvas 繪制等處理。
????????- 行為識別:分析鼠標事件、點擊頻率、頁面交互等行為特征。
破解滑動驗證碼的難點在于:
????????- 缺口識別:需精準定位缺口左邊緣,避免陰影、邊框等干擾。
????????- 軌跡模擬:需生成近似人類的加速-減速軌跡,并加入微小抖動和回彈。
????????- 環境偽裝:需偽裝瀏覽器指紋、請求頭等,防止被反爬機制識別。
三、工程實戰:滑動驗證碼識別全流程
????????接下來詳細講解滑動驗證碼識別與破解的完整工程流程。
3.1 工程準備
3.1.1 環境依賴
- Python 3.x
- Selenium
- Pillow (PIL)
- Chrome 瀏覽器及 ChromeDriver
安裝依賴:
pip install selenium pillow
3.1.2 目標網站與驗證碼識別案例
????????以保險公司產品查詢系統(?財產保險公司自主注冊產品查詢V1.0.0? )為例,登錄頁面集成了典型的拼圖型滑動驗證碼。驗證碼區域如圖所示:
下面是實現滑動驗證碼識別的動圖(滑動的速度可以自行調整):
??????? 那么我們是如何實現的呢,那請看下面內容分析
3.2 核心破解流程
3.2.1 自動化打開網頁與登錄
????????首先,使用 Selenium 自動化打開目標網頁,隨便輸入用戶名和密碼,點擊登錄按鈕,觸發滑動驗證碼彈窗。下面是定位用戶名密碼框輸入模擬登錄操作
from selenium import webdriver # 導入Selenium庫,用于自動化瀏覽器操作from selenium.webdriver.common.by import By # 用于元素定位from selenium.webdriver.support.ui import WebDriverWait # 顯式等待,確保元素加載完成from selenium.webdriver.support import expected_conditions as EC # 等待條件from selenium.webdriver import ActionChains # 用于模擬鼠標拖動等復雜操作from PIL import Image, ImageDraw # 圖像處理庫,用于截圖和畫輔助線import time # 時間控制class CrackSlider():def __init__(self):self.url = "https://cxcx.iachina.cn/" # 目標網站self.chrome_options = webdriver.ChromeOptions() # 創建Chrome配置對象self.chrome_options.add_experimental_option('excludeSwitches', ['enable-automation']) # 隱藏自動化標識,降低被檢測風險self.browser = webdriver.Chrome(options=self.chrome_options) # 啟動Chrome瀏覽器self.browser.maximize_window() # 最大化窗口,防止截圖區域不全self.wait = 2 # 默認等待時間(秒)def open(self):self.browser.get(self.url) # 打開目標網頁time.sleep(self.wait) # 等待頁面加載def input_login_info(self):myname = self.browser.find_element(By.XPATH, "/html/body/form/div/div[2]/div[1]/input[1]") # 定位用戶名輸入框myname.send_keys("1111") # 輸入用戶名mycode = self.browser.find_element(By.XPATH, '//*[@id="passWord"]') # 定位密碼輸入框mycode.send_keys("1111") # 輸入密碼time.sleep(2) # 等待輸入完成def click_login(self):button = self.browser.find_element(By.XPATH, '/html/body/form/div/div[3]/input[5]') # 定位登錄按鈕button.click() # 點擊登錄time.sleep(2) # 等待滑動驗證碼彈出
實現思路與設計原因:
????????- 采用Selenium自動化瀏覽器,能夠真實模擬用戶操作,繞過大部分前端反爬機制。
????????- 顯式等待和sleep結合,確保頁面元素加載和渲染完成,避免截圖黑屏或元素未找到。
????????- 最大化窗口和隱藏自動化標識,有助于提升截圖準確性和通過率。
3.2.2 獲取驗證碼圖片(適配縮放)
????????驗證碼圖片通常經過縮放或高分屏渲染,需獲取 devicePixelRatio 并裁剪出驗證碼區域。
screenshot_all.png?
def get_captcha_image(self, filename):wait = WebDriverWait(self.browser, 10) # 顯式等待,確保驗證碼圖片元素可見element = wait.until(EC.visibility_of_element_located((By.XPATH, '//*[@id="slideBar"]/div/div[1]/div[2]/div[2]/div[1]')))time.sleep(2) # 等待圖片渲染,防止截圖為黑色self.device_pixel_ratio = self.browser.execute_script('return window.devicePixelRatio') # 獲取瀏覽器縮放比例location = element.location # 獲取驗證碼圖片左上角坐標(頁面坐標)size = element.size # 獲取驗證碼圖片寬高left = location['x'] * self.device_pixel_ratio # 左坐標(頁面坐標*縮放)top = location['y'] * self.device_pixel_ratio # 上坐標right = left + size['width'] * self.device_pixel_ratio # 右坐標bottom = top + size['height'] * self.device_pixel_ratio # 下坐標self.browser.save_screenshot("screenshot_all.png") # 截取全屏im = Image.open("screenshot_all.png") # 打開截圖img = im.crop((left, top, right, bottom)) # 裁剪驗證碼區域img.save(filename) # 保存驗證碼圖片return img # 返回PIL.Image對象
實現思路與設計原因:
????????- 通過顯式等待和sleep,確保驗證碼圖片已完全渲染,避免截圖黑屏。
????????- 獲取devicePixelRatio,適配高分屏和瀏覽器縮放,保證裁剪區域與實際驗證碼一致。
????????- 先全屏截圖再裁剪,兼容所有瀏覽器和頁面布局。
3.2.3 識別缺口左邊緣
????????通過對比"無缺口"和"有缺口"兩張圖片,遍歷像素,找出差異最大的區域,確定缺口左邊緣。
def get_gap(self, image1, image2):beforecode = image1.convert("L") # 轉為灰度圖,簡化像素對比aftercode = image2.convert("L") # 轉為灰度圖threshold = 60 # 像素差閾值,調節靈敏度width = beforecode.size[0] # 圖片寬度height = beforecode.size[1] # 圖片高度diff_w = [] # 存儲所有差異點的橫坐標for h in range(0, height): # 遍歷每一行for w in range(int(round(width/3,0)), width): # 從1/3寬度開始,避開左側干擾beforepixel = beforecode.getpixel((w,h)) # 獲取無缺口像素afterpixel = aftercode.getpixel((w,h)) # 獲取有缺口像素if abs(beforepixel - afterpixel) > threshold: # 差異大于閾值diff_w.append(w) # 記錄差異點橫坐標if diff_w:gap_left = min(diff_w) # 差異區間左邊界gap_right = max(diff_w) # 差異區間右邊界gap_center = (gap_left + gap_right) // 2 # 取中心點return gap_left, gap_center # 返回左邊緣和中心return 0, 0 # 未找到則返回0
實現思路與設計原因:
????????- 灰度化處理簡化像素對比,提升識別速度和魯棒性。
????????- 只遍歷右側2/3區域,避開左側logo或干擾元素。
????????- 統計所有差異點,取最左為gap_left,最右為gap_right,中心為gap_center。
????????- 返回gap_left用于滑塊左邊緣對齊,gap_center用于調試和可視化。
3.2.4 計算滑動距離(左邊緣對齊)
????????滑塊左邊緣應對齊缺口左邊緣,滑動距離為:
gap_left, gap_center = self.get_gap(image1, image2) # 獲取缺口左邊緣和中心captcha_left = captcha_element.location['x'] * self.device_pixel_ratio # 驗證碼圖片左上角頁面坐標gap_left_page = captcha_left + gap_left # 缺口左邊緣頁面坐標slider_left = slider_location['x'] * self.device_pixel_ratio # 滑塊左邊緣頁面坐標move_distance = gap_left_page - slider_left # 實際需要滑動的距離
實現思路與設計原因:
????????- 所有坐標都統一為頁面坐標并乘以devicePixelRatio,避免縮放誤差。
????????- 滑塊左邊緣對齊缺口左邊緣,符合大多數滑動驗證碼的判定邏輯。
????????- move_distance為正,表示向右滑動。
3.2.5 生成自然滑動軌跡與回彈
????????軌跡需模擬人類加速-減速運動,并在末尾加入回彈和微小抖動。
def get_track(self, distance):if distance <= 0:return [0] # 距離為0直接返回track = [] # 存儲每次移動的距離current = 0 # 當前位移mid = distance * 4 / 5 # 前4/5為加速,后1/5為減速t = 0.2 # 時間間隔v = 0 # 初速度while current < distance: # 未到目標距離if current < mid:a = 2 # 加速階段else:a = -3 # 減速階段v0 = v # 初速度v = v0 + a * t # 當前速度move = v0 * t + 1 / 2 * a * t * t # 位移current += move # 累加位移track.append(round(move)) # 記錄本次移動if len(track) > 0:track[-1] = int(round(distance - sum(track[:-1]))) # 修正最后一步if abs(sum(track) - distance) > 1:track.append(int(distance - sum(track))) # 再次修正return track
實現思路與設計原因:
????????- 軌跡分為加速和減速兩段,模擬人手自然運動。
????????- 每步位移用物理公式計算,提升軌跡真實性。
????????- 最后一步修正,確保總距離精確。
????????- 可在軌跡末尾加微小抖動和回彈,進一步提升"人味"。
軌跡末尾加回彈:
track = self.get_track(move_distance) # 生成主軌跡
track.extend([3, -2, 1, -1]) # 加入回彈和微調
3.2.6 按軌跡移動滑塊
def move_to_gap(self, slider, tracks):actions = ActionChains(self.browser) # 創建動作鏈actions.click_and_hold(slider).perform() # 按住滑塊for x in tracks:actions.move_by_offset(xoffset=x, yoffset=0).perform() # 拖動滑塊time.sleep(1) # 停頓,模擬人類松手前的停留actions.release().perform() # 松開滑塊,完成驗證
實現思路與設計原因:
????????- 使用ActionChains模擬鼠標按住、拖動、松開全過程。
????????- 每步移動后立即執行,模擬真實鼠標拖動。
????????- 松手前適當停頓,提升通過率。
3.2.7 主流程整合
beforecode.png(獲取的無缺口圖片)
?aftercode.png(獲取的缺口圖片)
def crack(self):self.open() # 打開網頁self.input_login_info() # 輸入用戶名和密碼self.click_login() # 點擊登錄,彈出驗證碼image1 = self.get_captcha_image('beforecode.png') # 獲取無缺口圖片slider = self.get_slider() # 獲取滑塊元素slider.click() # 點擊滑塊,顯示缺口time.sleep(3) # 等待缺口圖片渲染image2 = self.get_captcha_image('aftercode.png') # 獲取帶缺口圖片gap_left, gap_center = self.get_gap(image1, image2) # 識別缺口左邊緣和中心captcha_element = self.browser.find_element(By.XPATH, '//*[@id="slideBar"]/div/div[1]/div[2]/div[2]/div[1]') # 驗證碼元素captcha_left = captcha_element.location['x'] * self.device_pixel_ratio # 驗證碼左上角頁面坐標gap_left_page = captcha_left + gap_left # 缺口左邊緣頁面坐標slider_location = slider.location # 滑塊左上角頁面坐標slider_size = slider.size # 滑塊寬高slider_left = slider_location['x'] * self.device_pixel_ratio # 滑塊左邊緣頁面坐標slider_center = slider_left + slider_size['width'] * self.device_pixel_ratio / 2 # 滑塊中心頁面坐標move_distance = gap_left_page - slider_left # 需要滑動的距離print(f"gap_left (in image): {gap_left}")print(f"gap_center (in image): {gap_center}")print(f"captcha_left (page): {captcha_left}")print(f"gap_left_page: {gap_left_page}")print(f"slider_left: {slider_left}")print(f"slider_center: {slider_center}")print(f"move_distance (left edge align): {move_distance}")img1_debug = image1.copy() # 調試用圖片img2_debug = image2.copy()self.draw_debug_line(img1_debug, gap_left, 'green', 'beforecode_debug.png') # 畫缺口左邊緣self.draw_debug_line(img1_debug, gap_center, 'red', 'beforecode_debug.png') # 畫缺口中心self.draw_debug_line(img2_debug, gap_left, 'green', 'aftercode_debug.png')self.draw_debug_line(img2_debug, gap_center, 'red', 'aftercode_debug.png')slider_center_in_img = int(slider_center - captcha_left) # 滑塊中心在圖片內的橫坐標self.draw_debug_line(img1_debug, slider_center_in_img, 'blue', 'beforecode_debug.png') # 畫滑塊中心track = self.get_track(move_distance) # 生成軌跡track.extend([3, -2, 1, -1]) # 加入回彈print(f"track: {track}")print(f"track sum: {sum(track)}")self.move_to_gap(slider, track) # 拖動滑塊time.sleep(2) # 等待驗證結果self.browser.close() # 關閉瀏覽器
實現思路與設計原因:
????????- 主流程串聯所有步驟,自動化完成驗證碼識別與破解。
????????- 關鍵變量和調試圖片便于排查問題和優化算法。
????????- 結構清晰,便于擴展和維護。
結語
????????滑動驗證碼的自動識別與破解,是自動化測試、數據采集和安全攻防領域的經典難題。本文以實際工程代碼為主線,系統梳理了滑動驗證碼的原理、反爬機制、識別與破解流程、核心算法實現、調試技巧與工程經驗。通過對缺口識別、軌跡生成、滑塊模擬等關鍵環節的逐步剖析,我們不僅掌握了破解滑動驗證碼的技術細節,也深入理解了背后的安全邏輯與攻防博弈。
????????在實際工程中,滑動驗證碼的樣式和反爬機制會不斷演化,破解方法也需靈活調整。面對更復雜的驗證碼(如canvas繪制、AI行為識別、圖片加密等),我們可以結合深度學習、圖像處理、瀏覽器指紋偽裝等多種手段,不斷提升自動化能力。
????????滑動驗證碼的研究,不僅有助于提升自動化測試和數據采集的效率,更有助于理解Web安全、反爬機制和人機交互的前沿發展。希望本章內容能為你的工程實踐和技術探索提供有力參考。未來,隨著AI與安全技術的持續進步,滑動驗證碼的攻防也將更加精彩,期待你在實踐中不斷創新、持續精進!
看到這里了還不給博主點一個:
?? 點贊
??收藏
?? 關注
!
💛 💙 💜 ?? 💚💓 💗 💕 💞 💘 💖
再次感謝大家的支持!
你們的點贊就是博主更新最大的動力!