摘要:下面我們便來講種驗證碼的識別方式和一些思路。哈哈庫其實,驗證碼識別歸根到底還是對各種各樣圖片的識別和操作,中有很對圖像處理的庫,其中就是其中之一。所以在處理驗證碼識別之前,必須先了解庫和。第五步,按照規定軌跡進行拖動,完成驗證。
寫在前面
現在,很多網站采取各種各樣的措施來反爬蟲,其中之一就是使用驗證碼。當我們訪問網頁時,必須先通過驗證碼才能夠訪問頁面。下面我們便來講2種驗證碼的識別方式和一些思路。當然我們也可以直接使用付費的打碼平臺,那樣可以增加識別的準確度,畢竟出了錢的嘛。哈哈!
PIL庫其實,驗證碼識別歸根到底還是對各種各樣圖片的識別和操作,python中有很對圖像處理的庫,其中PIL就是其中之一。 所以在處理驗證碼識別之前,必須先了解PIL庫和tesserocr。 下面附上其API源碼地址,以及對應的學習博客。
源碼地址:https://pillow-cn.readthedocs.io/zh_CN/latest/reference/index.html
參考博客:https://blog.csdn.net/louishao/article/details/69879981
下面我們就開始驗證碼識別之路了。
以中國知網為例:
首先,我們先拿到上圖中綠線標記的驗證碼,下載到本地項目文件中,
然后,編寫如下代碼:
import tesserocr from PIL import Image image = Image.open("image.png") res = tesserocr.image_to_text(image) print(res) # F8BS
輸出結果為:F8BS, 可是實際圖片為F8B8,這是因為驗證碼內多余線條干擾了圖片的識別,像這類情況,還需要做出額外的處理,比如轉灰度,二值化等。當然,實際處理中并不是這樣,一般我們會先對模糊圖片進行灰度處理后,再設定二值化的閾值,實際處理如下:
import tesserocr from PIL import Image image = Image.open("code.jpg") # 創建image對象 image = image.convert("L") threshold = 150 # 指定二值化閾值 table = [] for i in range(256): if i < threshold: table.append(0) else: table.append(1) image = image.point(table, "1") image.show() res = tesserocr.image_to_text(image) print(res)
輸出結果:F8B8
進行識別時,先設定好二值化閾值threshold,進行適當調試,直到圖片能正常識別為止。
過程分析:
滑動驗證碼主要的驗證方式是拖動滑塊,拼合圖像;如圖象完全拼合,則驗證成功,即表單提交成功,否則需要重新驗證。
如圖:
下面,我們就以極驗的驗證碼為例,來講訴一下識別方法。
因為極驗的驗證碼在拖動驗證碼后會生成一個加密的表單提交到后臺,所有為了避免麻煩我們直接用selenium模擬瀏覽器行為來完成驗證。
登陸網站:極驗官網
目標站點:https://account.geetest.com/l...
首先,我們發現登陸界面有個智能按鈕,一般來說,在輸入郵箱之后,點擊按鈕就會彈出滑動驗證窗口,然后我們在拖動驗證碼完成圖像拼接,完成驗證。
所以,滑塊驗證識別需要完成以下步驟:
模擬點擊驗證按鈕
識別滑塊的缺口位置
模擬拖動滑塊
如何實現以上步驟呢?我們先需要將任務進行分解,看似只有三大步驟,其實里面坑還有很多的,稍后會做解釋。
第一步,輸入賬號,獲取智能按鈕,使用selenium模擬點擊,獲取帶有缺口的圖片。
第二步,獲取上面缺口圖片中的完整圖片。這里有個地方要注意,正常情況下我們在網頁源代碼里是找不到完整圖的,因為它被隱藏了,必須執行javascript語句才能出現完整圖。
我們將display參數改為block,opacity參數改為1,然后進行截圖,就可以拿到完整的驗證碼圖片了。
第三步,對比兩張圖片的所有RGB像素點,得到缺口位置。
第四步,模擬人的拖動習慣,這里也有坑,極驗的驗證碼增加了機器軌跡識別,勻速移動,或者隨機速度移動滑塊都不能通過驗證,所以我們將需要拖動的總位移分成一段一段小的軌跡,先勻加速拖動后勻減速拖動。
第五步,按照規定軌跡進行拖動,完成驗證。
第六步,完成賬號登陸。
過程分析完了,下面我們就來寫代碼試一下:
首先,我們先將整個代碼的一個邏輯思路做一個大致的概括吧。
def main(): """主函數""" # 獲取帶缺口驗證碼圖片image1, 傳入的參數后綴為: .png image1 = get_unFull_captcha("unfull_captcha.png") # print(image1.load()[12,25]) # 獲取完整驗證碼圖片image2 image2 = get_full_captcha("full_captcha.png") # 對比上述圖片像素點,獲取缺口位置,得到偏移距離 distance = get_quekou_distance(image1, image2) print("缺口偏移量:", distance) # 獲取滑塊的移動軌跡 track = get_track(distance) # 模擬人的行為,拖動滑塊,完成驗證 slider = get_slider() move(slider, track) success = wait.until(EC.text_to_be_present_in_element((By.CLASS_NAME, "geetest_success_radar_tip_content"), "驗證成功")) print(success) if success: login() else: main()
接下來,我們便來逐一完成main函數里要實現的功能了。
代碼示例:
通過以上代碼我們便拿到了完整的驗證碼和帶有缺口的驗證碼。
缺口圖片:
def get_unFull_captcha(name): """ 獲取帶缺口驗證碼圖片 :return: unfull captcha """ top, bottom, left, right = get_captcha_position("geetest_canvas_slice") print("驗證碼1位置:", top, bottom, left, right) screenshot = get_screenshot() unfull_captcha = screenshot.crop((left, top, right, bottom)) # 按圖片位置裁剪 unfull_captcha.save(name) # 這里傳入的name要以xxx.png命名 return unfull_captcha
完整圖片:
def get_full_captcha(name): """ 獲取完整驗證碼圖片 :return: full_captcha """ # 這里要執行JavaScript腳本才能拿到完整圖片的截圖 show_Full_img1= "document.getElementsByClassName("geetest_canvas_fullbg")[0].style.display="block"" browser.execute_script(show_Full_img1) show_Full_img2 = "document.getElementsByClassName("geetest_canvas_fullbg")[0].style.opacity=1" browser.execute_script(show_Full_img2) # 等待完整圖片加載 time.sleep(2) top, bottom, left, right = get_captcha_position("geetest_canvas_fullbg") print("驗證碼2位置:", top, bottom, left, right) screenshot = get_screenshot() full_captcha = screenshot.crop((left, top, right, bottom)) # 同上 full_captcha.save(name) return full_captcha
這里我在調試的時候碰到一個坑,因為chrome中,location方法不滾動,直接返回相對整個html的坐標,我的電腦是15.6寸的,顯示設置上布局的縮放大小被放大到1.25倍,導致location返回的坐標與驗證碼的坐標有誤差。修改布局為100%后就解決了。 下面便是對比圖片找出缺口位置。這里我們需要遍歷圖片的坐標點,獲取像素點的RGB數據。
代碼示例
def get_quekou_distance(image1, image2): """ 對比像素點,獲取缺口位置 :param image1: 缺口圖片 :param image2: 完整圖片 :return: 缺口的偏移距離 """ # 缺口在滑塊右側,設定遍歷初始橫坐標left為59 left = 60 # 像素對比閾值 threshold = 60 for i in range(left, image2.size[0]): for j in range(image2.size[1]): rgb1 = image1.load()[i, j] rgb2 = image2.load()[i, j] res1 = abs(rgb2[0] - rgb1[0]) res2 = abs(rgb2[1] - rgb1[1]) res3 = abs(rgb2[2] - rgb1[2]) if not (res1 < threshold and res2 < threshold and res3 < threshold): return i-7 # 返回缺口偏移距離,這里需測試幾次
接下來就是獲取滑塊的移動路徑和模擬拖動行為了。
執行代碼:
def get_track(distance): """ 獲取移動路徑 :param distance: 偏移量 :return: track:移動軌跡 """ # 存放移動軌跡 track = [] # 當前位置 current = 0 # 設定加速段和減速段臨界點為路徑的3/4處 mid = distance*4/5 # 時間間隔time, 取0.2~0.3之間隨機數,避免被網站識別出來 t = random.randint(2, 3)/10 # 初速度 v = 0 while current < distance: if current < mid: # 勻加速移動,加速度a a = 2 else: a = -3 # 初速度 v0 = v # 當前速度 v = v0 + a*t # 移動距離 s = v0*t + 1/2 * a * t*t # 當前位移 current += s # 加入到移動軌跡 track.append(round(s)) return track def move(slider, track): """ 模擬鼠標操作,點擊,移動滑塊按鈕 :param: 滑塊 :param: 軌跡 :return: """ ActionChains(browser).click_and_hold(slider).perform() # 操作鼠標按軌跡移動 for x in track: ActionChains(browser).move_by_offset(xoffset=x, yoffset=0).perform() time.sleep(0.3) # 松開 ActionChains(browser).release().perform()
最后終于成功了,踩了這么多坑,終于完成了滑塊驗證碼的破解。。。現在已經實現功能,因為還可能出現其他情況,接下來我們還需要完善一下代碼,其實也可封裝成一個類,測試的時候我們會發現,圖片會彈出小怪獸被吃了,那是因為系統識別我們是機器行為,所以不通過,這里我們需要修改加速度參數,再增加一個回調。
這樣我們就成功破解驗證碼,并登陸到網頁界面了。。。忙活了一上午,吃飯去了。
好像現在極驗官網改了, 但是滑動驗證碼思路基本上就是這樣的...
源碼地址:https://github.com/appleguardu/spider_projects/tree/master/Captcha
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/43522.html
摘要:可惜收費的,今天要介紹的完美驗證碼識別系統是類似的免費產品。調用函數相當簡單的,對比復雜的參數,這個識別是相當的快捷。 此文已由作者徐迪授權網易云社區發布。 歡迎訪問網易云社區,了解更多網易技術產品運營經驗。 講到驗證碼識別,大家第一個可能想到tesseract。誠然,對于OCR而言,tesseract確實很強大,自帶的字模能識別絕大多數規整的中英文。但是驗證碼畢竟不是OCR。對于現在...
摘要:圖片驗證碼是目前最常用的一種。神經網絡以上驗證碼識別都依賴于字符切分,切分的好壞幾乎直接決定識別的準確程度。目前驗證碼識別最先進的是谷歌在識別街景圖像中門牌號碼中使用的一套的算法。 全自動區分計算機和人類的圖靈測試(Completely Automated Public Turing test to tell Computers and Humans Apart,簡稱CAPTCHA),...
摘要:為了應付這種情況,很多網站加大驗證碼識別難度,復雜的驗證碼甚至讓用戶都很難識別了,這種方式劣勢十分明顯,糟糕的用戶體驗最終會讓網站流失用戶,這便是為什么有人吐槽網站的驗證碼的原因了。 歡迎訪問網易云社區,了解更多網易技術產品運營經驗。 首先來談談驗證碼的機制,驗證碼作為一種人機識別手段,其終極目的,就是區分正常人和機器的操作。而對于沒有驗證碼的場景,比如用戶登陸,則機器可以同時、大批量...
閱讀 1181·2023-04-26 02:42
閱讀 1633·2021-11-12 10:36
閱讀 1780·2021-10-25 09:47
閱讀 1262·2021-08-18 10:22
閱讀 1801·2019-08-30 15:52
閱讀 1213·2019-08-30 10:54
閱讀 2635·2019-08-29 18:46
閱讀 3496·2019-08-26 18:27