第八部分 驗證碼的識別(極驗驗證碼)

前言:
驗證碼是衆多網站採起的反爬措施。驗證碼的花樣也不少,主要有下面這幾種類驗證碼:
圖形驗證碼:數字、英文字母、混淆曲線組合成的驗證碼。
行爲驗證碼:識別文字,點擊與文字相符的圖片驗證碼。
交互式驗證碼:極難滑動驗證碼,滑動拼合滑塊方可完成驗證。
點觸驗證碼:點擊正確結果纔可完成驗證。
還有滑動宮格驗證碼、計算題驗證碼等。


下面涉及到的驗證碼有普通圖形驗證碼、極驗滑動驗證碼、點觸驗證碼、微博宮格驗證碼。這些驗證碼識別方式和思路各有不一樣。經過了解這幾種識別方式,可用相似方法識別其餘類型驗證碼。

1、 圖形驗證碼的識別
知網註冊頁面就有相似的圖形驗證碼:http://my.cnki.net/elibregister/commonRegister.aspx

使用 OCR 技術識別圖形驗證碼。須要安裝的庫是 tesserocr。

先到知網註冊頁面下載驗證碼圖片保存到本地,命名爲 code.jpg,進行識別測試用。

一、 識別測試
將驗證碼圖片放到程序所在的目錄,用 tesserocr 庫識別驗證碼,代碼以下:

git

1 import tesserocr 2 from PIL import Image 3 image = Image.open('code.jpg') 4 result = tesserocr.image_to_text(image) 5 print(result)

 

 

運行代碼輸出爲空,看來是沒有成功識別驗證碼。

使用 tesserocr 的一個簡單方法直接圖片文件轉爲字符串,代碼以下所示:
github

1 import tesserocr 2 print(tesserocr.file_to_text('code.jpg'))

此時識別到的結果是 SDIX,圖片實際的驗證碼是 5DtX,識別效果不理想。

二、 驗證碼處理
因爲驗證碼內有多餘的線條幹擾了圖片的識別。須要作一些額外的處理才行,如轉灰度、二值化等操做。
將圖片轉化爲灰度圖像:Image對象的 convert() 方法傳入參數 L 便可。
web

1 image = image.convert('L') 2 image.show() # 顯示圖片

傳入 1 可將圖片進行二值化處理,以下所示:
算法

1 image = image.convert('1') 2 image.show() # 顯示圖片

還能夠經過指定二值化的閾值。上面的方法是採用的默認閾值 127。這還不能直接轉化原圖,要將原圖先轉爲灰度圖像,而後再指定二值化閾值。代碼以下所示:canvas

 

 1 import tesserocr  2 from PIL import Image  3 
 4 image = Image.open('code.jpg')  5 image = image.convert('L')  6 threshold = 121
 7 table = []  8 for i in range(256):  9     if i < threshold: 10  table.append(0) 11     else: 12         table.append(1) 13 image = image.point(table, '1') 14 #image.show()
15 image.save('code3.jpg') 16 # image = image.convert('1')
17 #image.show() # 顯示圖片
18 result = tesserocr.image_to_text(image) 19 print(result)

調試各類參數,識別效果仍然不理想。

2、 檢驗滑動驗證碼的識別

極驗驗證碼:須要手動拼合滑塊來完成的驗證,相對圖形驗證碼識別難度上升了幾個等級。下面用程序識別並經過極驗驗證碼的驗證,其中有分析識別思路、識別缺口位置、生成滑塊拖動、模擬實現滑塊拼合經過驗證等步驟。

須要用到Chrome 瀏覽器,並配置 ChromeDriver ,要用到的 Python 庫是 Selenium。

一、 對極驗驗證碼瞭解
極驗驗證碼官網:http://www.geetest.com/。一個專一提供驗證安全的系統,主要驗證方式是拖動滑塊拼命圖像。若圖像徹底拼合,則驗證成功,即表單提交,不然須要從新驗證。

如今極驗驗證碼使用的企業不少,天天有超過幾億次的響應。極驗驗證碼普遍用於直播視頻、金融服務、電子商務、遊戲娛樂、政府企業等各大類網站。

二、 極驗驗證碼特色
識別難度大。首先要點擊按鈕進行智能驗證,若是驗證不經過,則會彈出滑動窗口,拖動滑塊拼合圖像進行驗證。以後三個加密參數會生成,經過表單提交到後臺,後臺還會進行一次驗證。

極驗驗證碼增長了機器學習的方法來識別手動軌跡。其官方網站的安全防禦有下面幾點說明:
三角防禦之防模擬:惡意程序模仿人類行爲軌跡對驗證碼進行識別。利用機器學習和神經網絡,構建線上線下的多重靜態、動態防護模型,識別模擬軌跡,界定人機邊界。

三角防禦之防僞造:惡意程序經過僞造設備瀏覽器環境對驗證碼進行識別。利用設備基因技術,深度分析瀏覽器的實際性能來辨識僞造信息,同時根據依靠事件不斷更新黑名單來提升防依靠能力。

三角防禦之防暴力:惡意程序在短期內進行密集的攻擊,對驗證碼進行暴力識別。爲了防暴力,極驗驗證碼有多種形態,每種形態都用神經網絡生成海量圖庫儲備,每一張圖片都是獨一無二的,且圖庫不斷更新,極大程度提升防暴力識別成本。

三、 識別思路
對於極驗驗證碼,直接模擬表單提交,加密參數構造較困難,須要分析其加密和校驗邏輯,相對煩瑣。因此直接採用模擬瀏覽器動做的方式來完成驗證。使用 Python 的 Selenium 庫模擬人的行爲方式來完成驗證,成本要相對去識別加密算法少不少。如圖2-1所示。
瀏覽器

圖2-1  極驗驗證碼實例
圖2-1 極驗驗證碼實例

先找一個帶有極驗證的網站,這裏以博客園的登陸爲例進行驗證。極驗的官方登陸網站是 https://account.geetest.com/login,也能夠在其官網上作測試。在博客園的登陸頁面點擊登陸後會出現一個極驗驗證按鈕。如圖2-2所示。
安全

圖2-2  極驗驗證按鈕
圖2-2 極驗驗證按鈕

該按鈕是智能驗證按鈕。通常來講,若是是同一個會話,一段時間內第二次點擊會直接經過驗證。若是智能識別不經過,則會彈出滑動驗證窗口,須要拖動滑塊圖像完成二步驗證。驗證成功後,驗證按鈕會提示驗證成功。接下來就是提交表單。

通過上述分析,極驗驗證須要完成下面三步:
(1)模擬點擊驗證按鈕。
(2)識別滑動缺口的位置。
(3)模擬手動滑塊。

第(1)步操做相對簡單,可以使用 Selenium 模擬點擊按鈕。
第(2)步操做識別缺口的位置很關鍵,須要用到圖像的相關處理方法。首先觀察缺口的樣子,如圖2-3所示。
網絡

圖2-3  缺口示例
圖2-3 缺口示例

缺口的四周邊緣有明顯的斷裂邊緣,邊緣與邊緣周圍有明顯的區別。可用邊緣檢測算法來找出缺口的位置。對於極驗驗證碼,能夠利用和原圖對比檢測方式識別缺口的位置,一般在沒有拖動滑塊前,缺口沒有呈現。

能夠同時獲取兩張圖片,設定一個對比閾值,而後遍歷兩張圖片,找出相同位置像素 RGB 差距超過此閾值的像素點,此像素點的位置就是缺口的位置。

第(3)步中要注意的是,極驗驗證碼增長了機器軌跡識別,勻速移動、隨機速度移動等方法都不能經過驗證,只有徹底模擬人的移動軌跡才能夠經過驗證。人的移動軌跡通常是先加速後減速,要對這個過程模擬才能成功。

四、 初始化
這裏選定的鏈接是博客園的登陸頁面 https://passport.cnblogs.com/user/signin,在這裏首先要初始化一些配置,如 Selenium 對象的初始化及一些參數的配置。以下所示:
app

 1 import time  2 from io import BytesIO  3 from PIL import Image  4 from selenium import webdriver  5 from selenium.webdriver import ActionChains  6 from selenium.webdriver.common.by import By  7 from selenium.webdriver.support.ui import WebDriverWait  8 from selenium.webdriver.support import expected_conditions as EC  9 
10 USERNAME = 'xx'
11 PASSWORD = 'xxx'
12 
13 class CrackGeetest(): 14     def __init__(self): 15         self.url = 'https://passport.cnblogs.com/user/signin'
16         self.browser = webdriver.Chrome() 17         self.wait = WebDriverWait(self.browser, 20) 18         self.username = USERNAME 19         self.password = PASSWORD 20 
21     def __del__(self): 22         self.browser.close()

五、 點擊登陸調出極驗按鈕
定義一個方法獲取登陸按鈕,由於用戶名和密碼後須要先點擊登陸才能調出極驗按鈕。代碼以下所示:
機器學習

1 def get_login_button(self): 2     """
3  獲取登陸按鈕,調出極驗驗證碼 4  :return: 登陸按鈕對象 5     """
6     button_login = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'button'))) 7     return button_login


六、 模擬點擊
模擬點擊初始的驗證按鈕,定義一個方法來獲取這個按鈕,利用顯示等待的方法來實現。以下所示:

1 def get_geetest_button(self): 2     """
3  獲取初始驗證按鈕 4  :return: 按鈕對象 5     """
6     button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_radar_tip'))) 7     return button


獲取一個 WebElement 對象,調用它的 click() 方法便可模擬點擊,代碼以下所示:
# 點擊驗證按鈕

1 button = sele.get_geetest_button() 2 button.click()

 

 

七、 識別缺口
下面識別缺口的位置。須要獲取先後兩張比對圖片,兩者不一致的地方即爲缺口,獲得其所在位置和寬高,而後獲取整個網頁的截圖,圖片裁切出來便可,代碼實現以下:

 1 def get_position(self):  2     """
 3  獲取驗證碼位置  4  :return: 驗證碼位置元組  5     """
 6     img = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_img')))  7     time.sleep(2)  8     location = img.location  9     size = img.size 10     top, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size['width'] 11     return (top, bottom, left, right) 12 
13 def get_screenshot(self): 14     """
15  獲取網頁截圖 16  :return: 截圖對象 17     """
18     screenshot = self.browser.get_screenshot_as_png() 19     screenshot = Image.open(BytesIO(screenshot)) 20     return screenshot 21 
22 def get_slider(self): 23     """
24  獲取滑塊 25  :return: 滑塊對象 26     """
27     slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_slider_button'))) 28     return slider 29 
30 def get_geetest_image(self, name='captcha.png'): 31     """
32  獲取驗證碼圖片 33  :return: 圖片對象 34     """
35     top, bottom, left, right = self.get_position() 36     print('驗證碼位置', top, bottom, left, right) 37     screenshot = self.get_screenshot() 38     captcha = screenshot.crop((left, top, right,bottom)) 39     return captcha

這裏 get_position() 函數首先獲取驗證碼圖片對象的位置和寬高,隨後返回其左上角和右下角的座標。get_screenshot() 函數獲取網頁截圖。

get_slider() 函數獲取滑塊對象,有的驗證碼是點擊這個滑塊後纔出現帶缺口的圖片,有的是直接出現帶缺口的圖片。獲取到滑塊對象後調用 click() 方法觸發點擊,可以使缺口圖片呈現出來:
# 點按呼出缺口圖片

1 slider = self.get_slider()
2 slider.click()

get_geetest_image() 方法獲取網頁截圖,調用 crop() 方法將圖片裁切出來,返回 Image 對象。

分別將不帶缺口的圖片和帶缺口的圖片賦值給變量 image1 和 image2,接下來對比圖片獲取缺口。這裏採用遍歷圖片的每一個座標點,獲取兩張圖片對應像素的 RGB 數據。若是兩者的RGB 數據差距在必定範圍內,就表明兩個像素相同,繼續比對下一個像素點。若是差距超過必定範圍,則表明像素點不一樣,當前位置即爲缺口位置,代碼實現以下:

 1 def open(self):  2     """
 3  打開網頁輸入用戶名密碼  4  :return: None  5     """
 6  self.browser.get(self.url)  7     username = self.wait.until(EC.presence_of_element_located((By.ID, 'input1')))  8     password = self.wait.until(EC.presence_of_element_located((By.ID, 'input2')))  9  username.send_keys(self.username) 10  password.send_keys(self.password) 11 
12 def get_gap(self, image1, image2): 13     """
14  獲取帶缺口的偏移量 15  :param image1: 不帶缺口的圖片 16  :param image2: 帶缺口的圖片 17  :return: 18     """
19     left = 60
20     for i in range(left, image1.size[0]): 21         for j in range(image1.size[1]): 22             if not self.is_pixel_equal(image1, image2, i, j): 23                 left = i 24                 return left 25     return left 26 
27 def is_pixel_equal(self, image1, image2, x, y): 28     """
29  判斷兩個像素是否相同 30  :param image1: 圖片1 31  :param image2: 圖片2 32  :param x: 位置x 33  :param y: 位置y 34  :return: 像素是否相同 35     """
36     # 取兩個圖片的像素點
37     pixel1 = image1.load()[x,y] 38     pixel2 = image2.load()[x,y] 39     threshold = 60
40     if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs( 41         pixel1[2] - pixel2[2]) < threshold: 42         return True 43     else: 44         return False

open() 方法是打開登陸頁面,並輸入用戶名和密碼。get_gap() 方法是獲取缺口位置的方法。此方法的參數是兩張圖片,一張是帶缺口的圖片,另外一張是不帶缺口的圖片。這裏採用遍歷兩張圖片的每一個像素,利用 is_pixel_equal() 方法判斷兩張圖片同一位置的像素是否相同。比較兩張圖 RGB 的絕對值是否均小於定義的閾值 thresold。若是絕對值均在閾值以內,則表明像素點相同,繼續遍歷。不然表明不相同的像素點,就是缺口的位置。

經過對比兩張圖片能夠發現,兩張圖片有兩處明顯不一樣的地方:一個是待拼合的滑塊,一個是缺口。滑塊的位置會出如今左邊位置,缺口會出如今與滑塊同一水平線的位置,因此缺口通常會在滑塊的右側。若是要尋找缺口,直接從滑塊右側尋找便可。這裏直接設置遍歷的起始橫座標爲60,也就是從滑塊的右側開始識別,這樣識別出的結果就是缺口的位置。

識別完缺口位置,接下來就是模擬拖動。

八、 模擬拖動
模擬拖動的坑比較多。調用拖動的相關函數將滑塊拖動到對就位置,若是是勻速運動,極驗會識別出是程序在操做,由於人不能作到徹底勻速拖動。極驗驗證碼利用機器學習模型,篩選此類數據爲機器操做,驗證碼識別失敗。

若是將拖動過程劃分幾段,每段設置一個平均速度,速度圍繞平均速度小幅度隨機拉動,這樣也不能完成驗證。使用徹底模擬加速減速的過程可經過驗證。前段滑塊作勻加速運動,後段滑塊作勻減速運動,利用物理學的加速度公式可完成驗證。

滑動滑塊的加速度用 a 表示,當前速度用 v 表示,初始速度用 v0 表示,位移用 x 表示,所須要時間用 t 表示,它們之間的關係用以下公式表達:
x = v0 * t + 0.5 * a * t * t
v = v0 + a * t
利用這兩個公式可構造軌跡移動算法,計算出先加速後減速的運動軌跡,用代碼來實現以下所示:

 1 def get_track(self, distance):  2     """
 3  根據偏移量獲取移動軌跡  4  :param distance: 偏移量  5  :return: 移動軌跡  6     """
 7     # 移動軌跡
 8     track = []  9     # 當前位移
10     current = 0 11     # 減速閾值
12     mid = distance * 4 / 5
13     # 計算間隔
14     t = 0.2
15     # 初速度
16     v = 0 17 
18     while current < distance: 19         if current < mid: 20             # 加速度爲正2
21             a = 2
22         else: 23             # 加速度爲負3
24             a = -3
25         # 初速度v0
26         v0 = v 27         # 當前速度v = v0 + a * t
28         v = v0 + a * t 29         # 移動距離 x = v0*t + 1/2 * a * t^2
30         move = v0 * t + 0.5 * a * t * t 31         # 當前位移
32         current += move 33         # 加入軌跡
34  track.append(round(move)) 35     return track

這段代碼中定義了 get_track() 方法,參數是移動的總距離,返回的是運動軌跡。運動軌跡用列表 track 表示,列表的每一個元素表明每次移動多少距離。

變量mid是減速閾值,是加速到什麼位置開始減速,這裏mid值爲 4/5,即模擬前 4/5 路是加速過程,後 1/5 路是減速過程。

當前位移距離變量 current 初始是0,進入 while 循環,條件是當前位移小於總距離。在循環裏分段定義了加速度,在加速過程的加速度定義爲 2,減速過程的加速度定義爲 -3,以後使用位移公式計算出某個時間段內的位移,將當前位移更新並記錄到軌跡裏面。直到運動軌跡達到總距離時,循環終止。最後獲得 track 記錄了每一個時間間隔移動了多少位移,這樣就獲得滑塊的運動軌跡。最後按照運動軌跡拖動滑塊便可,代碼以下所示:

 1 def move_to_gap(self, slider, track):  2     """
 3  拖動滑塊到缺口處  4  :param slider: 滑塊  5  :param track: 軌跡  6  :return:  7     """
 8  ActionChains(self.browser).click_and_hold(slider).perform()  9     for x in track: 10         ActionChains(self.browser).move_by_offset(xoffset=x, yoffset=0).perform() 11     time.sleep(0.5) 12     ActionChains(self.browser).release().perform()

這裏傳入的參數爲滑塊對象和運動軌跡。先調用 ActionChains 的 click_and_hold() 方法按住拖動底部滑塊,遍歷運行軌跡獲取每小段位移距離,調用 move_by_offset() 方法移動此位移,最後調用 release()方法鬆開鼠標。

接着還須要完善表單,模擬點擊登陸按鈕,成功登陸後跳轉到後臺。最終的完整代碼以下所示:

 1 import time  2 from io import BytesIO  3 from PIL import Image  4 from selenium import webdriver  5 from selenium.webdriver import ActionChains  6 from selenium.webdriver.common.by import By  7 from selenium.webdriver.support.ui import WebDriverWait  8 from selenium.webdriver.support import expected_conditions as EC  9 
 10 USERNAME = 'xx'
 11 PASSWORD = 'xxx'
 12 BORDER = 6
 13 
 14 class CrackGeetest():  15     def __init__(self):  16         self.url = 'https://passport.cnblogs.com/user/signin'
 17         self.browser = webdriver.Chrome()  18         self.wait = WebDriverWait(self.browser, 20)  19         self.username = USERNAME  20         self.password = PASSWORD  21 
 22     def __del__(self):  23  self.browser.close()  24 
 25     def get_login_button(self):  26         """
 27  獲取登陸按鈕,調出極驗驗證碼  28  :return: 登陸按鈕對象  29         """
 30         #button_login = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'button')))
 31         button_login = self.wait.until(EC.element_to_be_clickable((By.ID, 'signin')))  32         return button_login  33 
 34     def get_geetest_button(self):  35         """
 36  獲取初始驗證按鈕,即點擊按鈕進行驗證  37  :return: 按鈕對象  38         """
 39         button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_radar_tip')))  40         return button  41 
 42     def get_position(self):  43         """
 44  獲取驗證碼位置  45  :return: 驗證碼位置元組  46         """
 47         img = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_img')))  48         time.sleep(2)  49         location = img.location  50         size = img.size  51         top, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size['width']  52         return (top, bottom, left, right)  53 
 54     def get_screenshot(self):  55         """
 56  獲取網頁截圖  57  :return: 截圖對象  58         """
 59         screenshot = self.browser.get_screenshot_as_png()  60         screenshot = Image.open(BytesIO(screenshot))  61         return screenshot  62 
 63     def get_slider(self):  64         """
 65  獲取滑塊  66  :return: 滑塊對象  67         """
 68         slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_slider_button')))  69         return slider  70 
 71     def get_geetest_image(self, name='captcha.png'):  72         """
 73  獲取驗證碼圖片  74  :return: 圖片對象  75         """
 76         top, bottom, left, right = self.get_position()  77         print('驗證碼位置', top, bottom, left, right)  78         screenshot = self.get_screenshot()  79         captcha = screenshot.crop((left, top, right,bottom))  80  captcha.save(name)  81         return captcha  82 
 83     def open(self):  84         """
 85  打開網頁輸入用戶名密碼  86  :return: None  87         """
 88  self.browser.get(self.url)  89         username = self.wait.until(EC.presence_of_element_located((By.ID, 'input1')))  90         password = self.wait.until(EC.presence_of_element_located((By.ID, 'input2')))  91  username.send_keys(self.username)  92  password.send_keys(self.password)  93 
 94     def get_gap(self, image1, image2):  95         """
 96  獲取帶缺口的偏移量  97  :param image1: 不帶缺口的圖片  98  :param image2: 帶缺口的圖片  99  :return: 100         """
101         left = 60
102         for i in range(left, image1.size[0]): 103             for j in range(image1.size[1]): 104                 if not self.is_pixel_equal(image1, image2, i, j): 105                     left = i 106                     return left 107         return left 108 
109     def is_pixel_equal(self, image1, image2, x, y): 110         """
111  判斷兩個像素是否相同 112  :param image1: 圖片1 113  :param image2: 圖片2 114  :param x: 位置x 115  :param y: 位置y 116  :return: 像素是否相同 117         """
118         # 取兩個圖片的像素點
119         pixel1 = image1.load()[x,y] 120         pixel2 = image2.load()[x,y] 121         threshold = 60
122         if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs( 123             pixel1[2] - pixel2[2]) < threshold: 124             return True 125         else: 126             return False 127 
128     def get_track(self, distance): 129         """
130  根據偏移量獲取移動軌跡 131  :param distance: 偏移量 132  :return: 移動軌跡 133         """
134         # 移動軌跡
135         track = [] 136         # 當前位移
137         current = 0 138         # 減速閾值
139         mid = distance * 4 / 5
140         # 計算間隔
141         t = 0.2
142         # 初速度
143         v = 0 144 
145         while current < distance: 146             if current < mid: 147                 # 加速度爲正2
148                 a = 2
149             else: 150                 # 加速度爲負3
151                 a = -3
152             # 初速度v0
153             v0 = v 154             # 當前速度v = v0 + a * t
155             v = v0 + a * t 156             # 移動距離 x = v0*t + 1/2 * a * t^2
157             move = v0 * t + 0.5 * a * t * t 158             # 當前位移
159             current += move 160             # 加入軌跡
161  track.append(round(move)) 162         return track 163 
164     def move_to_gap(self, slider, track): 165         """
166  拖動滑塊到缺口處 167  :param slider: 滑塊 168  :param track: 軌跡 169  :return: 170         """
171  ActionChains(self.browser).click_and_hold(slider).perform() 172         for x in track: 173             ActionChains(self.browser).move_by_offset(xoffset=x, yoffset=0).perform() 174         time.sleep(0.5) 175  ActionChains(self.browser).release().perform() 176 
177     def login(self): 178         """
179  登陸 180  :return: None 181         """
182         submit = self.wait.until(EC.element_to_be_clickable((By.ID, 'signin'))) 183  submit.click() 184         time.sleep(10) 185         print('登陸成功') 186 
187     def crack(self): 188         # 輸入用戶名和密碼
189  self.open() 190         # 點擊登陸按鈕,調出驗證按鈕
191         login_button = self.get_login_button() 192  login_button.click() 193         # 點擊驗證按鈕
194         button = self.get_geetest_button() 195  button.click() 196         # 獲取驗證碼圖片
197         image1 = self.get_geetest_image('captcha1.png') 198         # 點按呼出缺口
199         slider = self.get_slider() 200  slider.click() 201         # 獲取帶缺口的驗證碼圖片
202         image2 = self.get_geetest_image('captcha2.png') 203         # 獲取缺口位置
204         gap = self.get_gap(image1, image2) 205         print('缺口位置', gap) 206         # 減去缺口位移
207         gap -= BORDER 208         # 獲取移動軌跡
209         track = self.get_track(gap) 210         print('滑動軌跡', track) 211         # 拖動滑塊
212  self.move_to_gap(slider, track) 213 
214         success = self.wait.until( 215             EC.text_to_be_present_in_element((By.CLASS_NAME, 'geetest_success_radar_tip_content'), '驗證成功')) 216         print(success) 217 
218         # 失敗後重試
219         if not success: 220  self.crack() 221         else: 222  self.login() 223 
224 if __name__ == '__main__': 225     crack = CrackGeetest() 226     crack.crack()

通過上述學習,要掌握極驗驗證碼的識別思路,如何識別缺口位置、如何生成運行軌跡等。有相似原理的驗證碼,可利用這個思路完成識別過程。

最新代碼地址:https://github.com/cc55michael/GetWebPageData/blob/master/crack-geetest.py

相關文章
相關標籤/搜索