爬蟲開發者必學:讓 Python 讀懂「滑動驗證碼」
常見的網頁驗證碼類型與原理
你在瀏覽網頁的時候,有看過這些驗證機制嗎?網頁驗證碼的專業術語稱為「CAPTCHA 」(全名是 Completely Automated Public Turing test to tell Computers and Humans Apart 自動判別電腦與人類的公開圖靈測試),是目前在網頁當中常見的一種驗證機制,用來判斷惡意的使用者干擾與攻擊。目前常見的 CAPTCHA 方法有以下幾種:
- 信件驗證碼/簡訊驗證碼
- 圖形驗證碼
- 問題驗證碼
- 行為驗證碼
reCAPTCHA 計畫目前是由 Google 主要發展的驗證機制,最早是由 CMU 發起的 。reCAPTCHA 透過不同的情境讓人類回答,並藉此來幫助幫助文件數位化的進行。這個計畫將紙本掃描後無法被辨識文字顯示在問題中,讓人類在回答問題也能加以利用。
利用 Python 處理「滑動程式碼」的思路
而在「圖形驗證碼」當中,有一種常見的變形稱為「滑動驗證碼」。滑動驗證碼會動態的更新圖片與缺塊,並且要求使用者將缺塊移動到圖片中的特定位置才能通過判斷,如圖所示:
對於爬蟲的開發者而言,滑動驗證碼的確是一個蠻大的門檻。如何爬蟲程式可以讀得懂驗證碼,並且進一步模擬其行為都需要對網頁運作有一定的熟悉程度才行。接下來,就讓我們透過實作範例一起來體驗滑動程式碼的解決思路,我們可以分成兩個大區塊:
① 利用 Python + opencv 拆解缺塊位置
② 利用 Python + Selenium 模擬滑動行為
① 利用 Python + opencv 拆解缺塊位置
先手動把「背景圖」下載到本地端電腦,再試著利用圖像識別的方法試著找出位置。
(1)利用 cv2 將圖片讀取到程式中
OpenCV(Open Source Computer Vision Library)是用於電腦視覺的處理套件,在 Python 可以使用 opencv-python 與 cv2 進行安裝/載入。第一步,我們先利用 cv2.imread(…) 把圖片讀到程式中,並且利用 cv2.cvtColor 進行顏色轉換(原始圖片有誤差):
(2)判斷圖片中的物體邊緣輪廓
Canny 是圖形識別中用來作邊緣偵測(Edge Detection)的方法,細節的參數細節可以看官方文件。Canny 方法能將原始圖片轉成灰階之後,輸出包含邊緣範圍的黑白影像:
可以從結果中看到除了區塊之後,也包含很多小的零散的區塊部分:
(3)取出缺塊所在的位置
接下來利用 cv2.findContours() 找出圖片中所有偵測到的區塊,把他標記成藍色的部分畫出來。從長度(w)跟寬度(h)可以判斷出哪一個區塊是圖片中真正的區塊,但圖片顏色太接近的情況下會增加判斷的難度。
最終就可以得到缺塊所在的位置是 dx 和 dy 兩個變數:
以這個例子來說,我們就可以得知缺塊距離最左邊距離 202 px 的偏移量。
② 利用 Python + Selenium 模擬滑動行為
第二段,我們會利用 Selenium 瀏覽器測試工具幫助我們「模擬使用者移動方塊」的行為。關於 Selenium 的動態網頁模擬,之前也有寫過這一篇分享文。
(1)打開瀏覽器前往網頁,下載原始圖片
先觀察一下網頁的組成,發現給定的範例網站是利用 Canvas 動態載入圖片實現滑動驗證碼的效果的:
接下來利用 Selenium 打開瀏覽器跳轉到網頁中,利用 JavaScript 的先將 Canvas 轉成圖片後再進行下載 。
這麼做就可以把原始圖片下載下來,搭配「① 利用 Python + opencv 拆解缺塊位置」可以得知需要移動的偏移量。
找出按鈕元素
透過觀察網頁的結構,可以明確的找出需要被移動的方塊是位在 class = jigsaw__slider–ihcNg 的 div 元素(具體的找法,可以參考這一篇文章):
使用 Selenium 輕鬆選取:
(2)模擬使用者拖拉方塊行為
最後一步,就可以利用剛剛找出來缺塊的位置及瀏覽器模擬的工具,把方塊移動到指定的偏移位置:
實戰!讓 Python 爬蟲也能讀得懂「滑動驗證碼」
在這個例子當中,除了實作滑動驗證碼的爬蟲之外,也弄了一個簡單的滑動驗證碼作為標的。最後的成果大概像這樣,從「打開網頁」 → 「下載圖片」 → 「解析位置」 → 「模擬滑動」的整個過程:
網頁爬蟲是資料收集的一種手法,不過面對於網頁技術的變化,爬蟲程式也有不同的應對策略。
Reference
[1] 驗證碼
[2] Captcha验证码有哪些分类?有什么作用?
[3] 使用 Python + Selenium 破解滑块验证码