前言:
驗證碼是衆多網站採起的反爬措施。驗證碼的花樣也不少,主要有下面這幾種類驗證碼:
圖形驗證碼:數字、英文字母、混淆曲線組合成的驗證碼。
行爲驗證碼:識別文字,點擊與文字相符的圖片驗證碼。
交互式驗證碼:極難滑動驗證碼,滑動拼合滑塊方可完成驗證。
點觸驗證碼:點擊正確結果纔可完成驗證。
還有滑動宮格驗證碼、計算題驗證碼等。
下面涉及到的驗證碼有普通圖形驗證碼、極驗滑動驗證碼、點觸驗證碼、微博宮格驗證碼。這些驗證碼識別方式和思路各有不一樣。經過了解這幾種識別方式,可用相似方法識別其餘類型驗證碼。
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 極驗驗證碼實例
先找一個帶有極驗證的網站,這裏以博客園的登陸爲例進行驗證。極驗的官方登陸網站是 https://account.geetest.com/login,也能夠在其官網上作測試。在博客園的登陸頁面點擊登陸後會出現一個極驗驗證按鈕。如圖2-2所示。安全
圖2-2 極驗驗證按鈕
該按鈕是智能驗證按鈕。通常來講,若是是同一個會話,一段時間內第二次點擊會直接經過驗證。若是智能識別不經過,則會彈出滑動驗證窗口,須要拖動滑塊圖像完成二步驗證。驗證成功後,驗證按鈕會提示驗證成功。接下來就是提交表單。
通過上述分析,極驗驗證須要完成下面三步:
(1)模擬點擊驗證按鈕。
(2)識別滑動缺口的位置。
(3)模擬手動滑塊。
第(1)步操做相對簡單,可以使用 Selenium 模擬點擊按鈕。
第(2)步操做識別缺口的位置很關鍵,須要用到圖像的相關處理方法。首先觀察缺口的樣子,如圖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