Python新版極驗驗證碼識別驗證碼教程詳解
前言
(結(jié)尾有彩蛋歐)
目前,許多網(wǎng)站采取各種各樣的措施來反爬蟲,其中一個措施便是使用驗證碼。隨著技術(shù)的發(fā)展,驗證碼的花樣越來越多。驗證碼最初是幾個數(shù)字組合的簡單的圖形驗證碼,后來加入了英文字母和混淆曲線。有的網(wǎng)站還可能看到中文字符的驗證碼,這使得識別愈發(fā)困難。
后來 12306 驗證碼的出現(xiàn)使得行為驗證碼開始發(fā)展起來,用過 12306 的用戶肯定多少為它的驗證碼頭疼過。我們需要識別文字,點擊與文字描述相符的圖片,驗證碼完全正確,驗證才能通過?,F(xiàn)在這種交互式驗證碼越來越多,如極驗滑動驗證碼需要滑動拼合滑塊才可以完成驗證,點觸驗證碼需要完全點擊正確結(jié)果才可以完成驗證,另外還有滑動宮格驗證碼、計算題驗證碼等。
驗證碼變得越來越復(fù)雜,爬蟲的工作也變得愈發(fā)艱難。有時候我們必須通過驗證碼的驗證才可以訪問頁面。本章就專門針對驗證碼的識別做統(tǒng)一講解。
接下來會涉及的驗證碼有普通圖形驗證碼、極驗滑動驗證碼、點觸驗證碼、微博宮格驗證碼,這些驗證碼識別的方式和思路各有不同。了解這幾個驗證碼的識別方式之后,我們可以舉一反三,用類似的方法識別其他類型驗證碼。
環(huán)境使用
- python 3.9
- pycharm
上節(jié)回顧
上節(jié)我們了解了可以直接利用 tesserocr 來識別簡單的圖形驗證碼。近幾年出現(xiàn)了一些新型驗證碼,其中比較有代表性的就是極驗驗證碼,它需要拖動拼合滑塊才可以完成驗證,相對圖形驗證碼來說識別難度上升了幾個等級。本節(jié)將講解極驗驗證碼的識別過程。
本節(jié)目標(biāo)
我們的目標(biāo)是用程序來識別并通過極驗驗證碼的驗證,包括分析識別思路、識別缺口位置、生成滑塊拖動路徑、模擬實現(xiàn)滑塊 拼合通過驗證等步驟。
準(zhǔn)備工作
本次我們使用的 Python 庫是 Selenium,瀏覽器為 Chrome。請確保已經(jīng)正確安裝 Selenium 庫、Chrome 瀏覽器, 并配置 ChromeDriver,相關(guān)流程可以參考我寫的其他博文說明。
了解極驗驗證碼
現(xiàn)在極驗驗證碼已經(jīng)更新到 3.0 版本。全球有 16 萬家企業(yè)使用極驗,每天服務(wù)響應(yīng)超過 4 億次。極驗驗證碼廣泛應(yīng)用于直播視頻、金融服務(wù)、電子商務(wù)、游戲娛樂、企業(yè)等各大類型網(wǎng)站。下面圖中是斗魚、魅族的登錄頁面,它們都對接了極驗驗證碼。
極驗驗證碼的特點
極驗驗證碼相較于圖形驗證碼來說識別難度更大。對于極驗驗證碼 3.0 版本,我們首先點擊按鈕進行智能驗證。如果驗證不通過,則會彈出滑動驗證的窗口,拖動滑塊拼合圖像進行驗證。之后三個加密參數(shù)會生成,通過表單提交到后臺,后臺還會進行一次驗證。
極驗驗證碼還增加了機器學(xué)習(xí)的方法來識別拖動軌跡。官方網(wǎng)站的安全防護有如下幾點說明。
三角防護之防模擬
惡意程序模仿人類行為軌跡對驗證碼進行識別。針對模擬,極驗擁有超過 4000 萬人機行為樣本的海量數(shù)據(jù)。利用機器學(xué)習(xí)和神經(jīng)網(wǎng)絡(luò)構(gòu)建線上線下的多重靜態(tài)、動態(tài)防御模型。識別模擬軌跡,界定人機邊界。
三角防護之防偽造
惡意程序通過偽造設(shè)備瀏覽器環(huán)境對驗證碼進行識別。針對偽造,極驗利用設(shè)備基因技術(shù)。深度分析瀏覽器的實際性能來辨識偽造信息。同時根據(jù)偽造事件不斷更新黑名單,大幅提高防偽造能力。
三角防護之防暴力
惡意程序短時間內(nèi)進行密集的攻擊,對驗證碼進行暴力識別 針對暴力,極驗擁有多種驗證形態(tài),每一種驗證形態(tài)都有利用神經(jīng)網(wǎng)絡(luò)生成的海量圖庫儲備,每一張圖片都是獨一無二的,且圖庫不斷更新,極大程度提高了暴力識別的成本。
識別思路
對于應(yīng)用了極驗驗證碼的網(wǎng)站,如果我們直接模擬表單提交,加密參數(shù)的構(gòu)造是個問題,需要分析其加密和校驗邏輯,相對煩瑣。所以我們采用直接模擬瀏覽器動作的方式來完成驗證。在 Python 中,我們可以使用 Selenium 來完全模擬人的行為的方式來完成驗證,此驗證成本相比直接去識別加密算法少很多。
首先我們找到一個帶有極驗驗證的網(wǎng)站,最合適的當(dāng)然為極驗官方后臺了。此按鈕為智能驗證按鈕。一般來說,如果是同一個會話,一段時間內(nèi)第二次點擊會直接通過驗證。如果智能識別不通過,則會彈出滑動驗證窗口,我們要拖動滑塊拼合圖像完成二步驗證,驗證成功后,驗證按鈕變成如圖所示的狀態(tài)。
接下來,我們便可以提交表單了。
所以,識別驗證需要完成如下三步。
- 模擬點擊驗證按鈕
- 識別滑動缺口的位置
- 模擬拖動滑塊
擬點擊驗證按鈕
第一步操作是最簡單的,我們可以直接用 Selenium 模擬點擊按鈕即可。
識別滑動缺口的位置
第二步操作識別缺口的位置比較關(guān)鍵,這里需要用到圖像的相關(guān)處理方法。首先觀察缺口的樣子,缺口的四周邊緣有明顯的斷裂邊緣,邊緣和邊緣周圍有明顯的區(qū)別。我們可以實現(xiàn)一個邊緣檢測算法來找出缺口的位置。對于極驗驗證碼來說,我們可以利用和原圖對比檢測的方式來識別缺口的位置,因為在沒有滑動滑塊之前,缺口并沒有呈現(xiàn)。
我們可以同時獲取兩張圖片。設(shè)定一個對比閾值,然后遍歷兩張圖片,找出相同位置像素 RGB 差距超過此閾值的像素點,那么此像素點的位置就是缺口的位置。
模擬拖動滑塊
第3步操作看似簡單,但其中的坑比較多。極驗驗證碼增加了機器軌跡識別,勻速移動、隨機速度移動等方法都不能通過驗證,只有完全模擬人的移動軌跡才可以通過驗證。人的移動軌跡一般是先加速后減速,我們需要模擬這個過程才能成功。
有了基本的思路之后,我們就用程序來實現(xiàn)極驗驗證碼的識別過程吧。
模擬點擊
首先,我們先模擬登錄,其中 admin 和 PASSWORD 就是登錄極驗需要的用戶名和密碼,如果沒有的話可以先注冊一下。
admin = '[賬號]' PASSWORD = '[密碼]' class CrackGeetest(): def __init__(self): self.url = 'https://account.geetest.com/login' self.browser = webdriver.Chrome() self.wait = WebDriverWait(self.browser, 20) self.email = EMAIL self.password = PASSWORD
實現(xiàn)第一步的操作,也就是模擬點擊初始的驗證按鈕。我們定義一個方法來獲取這個按鈕,利用顯式等待的方法來實現(xiàn),如下所示:
def get_geetest_button(self): """ 獲取初始驗證按鈕 :return: 按鈕對象 """ button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_radar_tip'))) return button # 點擊驗證按鈕 button = self.get_geetest_button() button.click()
識別缺口
接下來識別缺口的位置。首先獲取前后兩張比對圖片,二者不一致的地方即為缺口。獲取不帶缺口的圖片,利用 Selenium 選取圖片元素,得到其所在位置和寬高,然后獲取整個網(wǎng)頁的截圖,圖片裁切出來即可,代碼實現(xiàn)如下:
def get_position(self): img = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_img'))) time.sleep(2) location = img.location size = img.size top, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size['width'] return (top, bottom, left, right) def get_geetest_image(self, name='captcha.png'): top, bottom, left, right = self.get_position() print(' 驗證碼位置 ', top, bottom, left, right) screenshot = self.get_screenshot() captcha = screenshot.crop((left, top, right, bottom)) return captcha
這里 get_position() 函數(shù)首先獲取圖片對象,獲取它的位置和寬高,隨后返回其左上角和右下角的坐標(biāo)。get_geetest_image() 方法獲取網(wǎng)頁截圖,調(diào)用了 crop() 方法將圖片裁切出來,返回的是 Image 對象。
接下來我們需要獲取第二張圖片,也就是帶缺口的圖片。要使得圖片出現(xiàn)缺口,只需要點擊下方的滑塊即可。這個動作觸發(fā)之后,圖片中的缺口就會顯現(xiàn),如下所示:
def get_slider(self): slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_slider_button'))) return slider slider = self.get_slider() slider.click()
調(diào)用 get_geetest_image() 方法將第二張圖片獲取下來即可。
現(xiàn)在我們已經(jīng)得到兩張圖片對象,分別賦值給變量 image1 和 image2。接下來對比圖片獲取缺口。我們在這里遍歷圖片的每個坐標(biāo)點,獲取兩張圖片對應(yīng)像素點的 RGB 數(shù)據(jù)。如果二者的 RGB 數(shù)據(jù)差距在一定范圍內(nèi),那就代表兩個像素相同,繼續(xù)比對下一個像素點。如果差距超過一定范圍,則代表像素點不同,當(dāng)前位置即為缺口位置,代碼實現(xiàn)如下:
def is_pixel_equal(self, image1, image2, x, y): pixel1 = image1.load()[x, y] pixel2 = image2.load()[x, y] threshold = 60 if abs(pixel1[0] - pixel2[0]) <threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs(pixel1[2] - pixel2[2]) < threshold: return True else: return False def get_gap(self, image1, image2): left = 60 for i in range(left, image1.size[0]): for j in range(image1.size[1]): if not self.is_pixel_equal(image1, image2, i, j): left = i return left return left
get_gap() 方法即獲取缺口位置的方法。此方法的參數(shù)是兩張圖片,一張為帶缺口圖片,另一張為不帶缺口圖片。這里遍歷兩張圖片的每個像素,利用 is_pixel_equal() 方法判斷兩張圖片同一位置的像素是否相同。比較兩張圖 RGB 的絕對值是否均小于定義的閾值 threshold。如果絕對值均在閾值之內(nèi),則代表像素點相同,繼續(xù)遍歷。否則代表不相同的像素點,即缺口的位置。
兩張圖片有兩處明顯不同的地方:一個就是待拼合的滑塊,一個就是缺口?;瑝K的位置會出現(xiàn)在左邊位置,缺口會出現(xiàn)在與滑塊同一水平線的位置,所以缺口一般會在滑塊的右側(cè)。如果要尋找缺口,直接從滑塊右側(cè)尋找即可。我們直接設(shè)置遍歷的起始橫坐標(biāo)為 60,也就是從滑塊的右側(cè)開始識別,這樣識別出的結(jié)果就是缺口的位置。
現(xiàn)在,我們獲取了缺口的位置。完成驗證還剩下最后一步 —— 模擬拖動。
模擬拖動
到這里,會有一個小問題。如果是勻速拖動,極驗必然會識別出它是程序的操作,因為人無法做到完全勻速拖動。極驗驗證碼利用機器學(xué)習(xí)模型,篩選此類數(shù)據(jù)為機器操作,驗證碼識別失敗。我們嘗試分段模擬,將拖動過程劃分幾段,每段設(shè)置一個平均速度,速度圍繞該平均速度小幅度隨機抖動,這樣也無法完成驗證。那怎么辦呢?
我們可以完全模擬加速減速的過程通過了驗證。即前段滑塊做勻加速運動,后段滑塊做勻減速運動,利用物理學(xué)的加速度公式即可完成驗證。接下來我們就可以構(gòu)造軌跡移動算法,計算出先加速后減速的運動軌跡,最后按照該運動軌跡拖動滑塊即可,方法實現(xiàn)如下所示:
def move_to_gap(self, slider, tracks): ActionChains(self.browser).click_and_hold(slider).perform() for x in tracks: ActionChains(self.browser).move_by_offset(xoffset=x, yoffset=0).perform() time.sleep(0.5) ActionChains(self.browser).release().perform()
最后經(jīng)過測試,驗證通過,識別完成。
到此這篇關(guān)于Python新版極驗驗證碼識別驗證碼教程詳解的文章就介紹到這了,更多相關(guān)Python極驗驗證碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python GUI庫圖形界面開發(fā)之PyQt5線程類QThread詳細(xì)使用方法
這篇文章主要介紹了python GUI庫圖形界面開發(fā)之PyQt5線程QThread類詳細(xì)使用方法,需要的朋友可以參考下2020-02-02淺談在django中使用filter()(即對QuerySet操作)時踩的坑
這篇文章主要介紹了淺談在django中使用filter()(即對QuerySet操作)時踩的坑,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03networkx庫繪制帶權(quán)圖給無權(quán)圖加權(quán)重輸出
這篇文章主要為大家介紹了Python?networkx庫繪制帶權(quán)圖給無權(quán)圖加權(quán)重并輸出權(quán)重的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05Pandas數(shù)據(jù)類型自行變換及數(shù)據(jù)類型轉(zhuǎn)換失敗問題分析與解決
這篇文章主要介紹了Pandas數(shù)據(jù)類型自行變換及數(shù)據(jù)類型轉(zhuǎn)換失敗問題分析與解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06