自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

拒絕反爬蟲!教你搞定爬蟲驗(yàn)證碼

開發(fā) 前端
隨著技術(shù)的發(fā)展,驗(yàn)證碼的花樣越來越多。驗(yàn)證碼最初是幾個(gè)數(shù)字組合的簡(jiǎn)單的圖形驗(yàn)證碼,后來加入了英文字母和混淆曲線。有的網(wǎng)站還可能看到中文字符的驗(yàn)證碼,這使得識(shí)別越發(fā)困難。

[[405061]]

本文轉(zhuǎn)載自微信公眾號(hào)「數(shù)倉(cāng)寶貝庫(kù)」,作者趙國(guó)生,王健。轉(zhuǎn)載本文請(qǐng)聯(lián)系數(shù)倉(cāng)寶貝庫(kù)公眾號(hào)。

目前,許多網(wǎng)站采取各種各樣的措施來反爬蟲,其中一個(gè)措施便是使用驗(yàn)證碼。隨著技術(shù)的發(fā)展,驗(yàn)證碼的花樣越來越多。驗(yàn)證碼最初是幾個(gè)數(shù)字組合的簡(jiǎn)單的圖形驗(yàn)證碼,后來加入了英文字母和混淆曲線。有的網(wǎng)站還可能看到中文字符的驗(yàn)證碼,這使得識(shí)別越發(fā)困難。

使用驗(yàn)證碼可以防止應(yīng)用或者網(wǎng)站被惡意注冊(cè)、攻擊,對(duì)于網(wǎng)站、APP而言,大量的無(wú)效注冊(cè)、重復(fù)注冊(cè)甚至是惡意攻擊很令人頭痛。使用驗(yàn)證碼能夠很大程度上減少這些惡意操作。驗(yàn)證碼變得越來越復(fù)雜,爬蟲的工作也變得越發(fā)艱難。有時(shí)候我們必須通過驗(yàn)證碼的驗(yàn)證才能夠訪問頁(yè)面(如圖1所示)。

圖1 驗(yàn)證碼界面

目前主流的 4 種驗(yàn)證碼為輸入式驗(yàn)證碼、滑動(dòng)式驗(yàn)證碼、宮格式驗(yàn)證碼和點(diǎn)擊式的圖文驗(yàn)證,下面我們來分別講解它們的解決思路。

4種驗(yàn)證碼的解決思路

01 輸入式驗(yàn)證碼

這種驗(yàn)證碼主要是通過用戶輸入圖片中的字母、數(shù)字、漢字等進(jìn)行驗(yàn)證,如圖2所示。

圖2 輸入式驗(yàn)證碼

解決思路:這是最簡(jiǎn)單的一種驗(yàn)證碼,只要識(shí)別出里面的內(nèi)容,然后填入輸入框中即可。這種識(shí)別技術(shù)叫OCR,這里推薦使用 Python 的第三方庫(kù) tesserocr。tesserocr 與 pytesseract 是 Python 的一個(gè) OCR 識(shí)別庫(kù),但其實(shí)是對(duì) Tesseract 做的一層 Python API 封裝,pytesseract 是 Google 的 Tesseract-OCR 引擎包裝器;所以它們的核心是 Tesseract。對(duì)于沒有什么背景影響的驗(yàn)證碼,直接通過這個(gè)庫(kù)來識(shí)別就可以。但是對(duì)于有嘈雜的背景的驗(yàn)證碼,直接識(shí)別的識(shí)別率會(huì)很低,遇到這種驗(yàn)證碼需要先對(duì)圖片進(jìn)行灰度化,然后再進(jìn)行二值化,再去識(shí)別,這樣識(shí)別率會(huì)大大提高。

02 滑動(dòng)式驗(yàn)證碼

這種是將備選碎片直線滑動(dòng)到正確的位置,如圖3所示。

圖3 滑動(dòng)式驗(yàn)證碼

解決思路:對(duì)于這種驗(yàn)證碼就比較復(fù)雜一點(diǎn),但也是有相應(yīng)的辦法。我們直接想到的就是模擬人去拖動(dòng)驗(yàn)證碼的行為,點(diǎn)擊按鈕,然后看到了缺口的位置,最后把拼圖拖到缺口位置處完成驗(yàn)證。

第一步:點(diǎn)擊按鈕。當(dāng)沒有點(diǎn)擊按鈕的時(shí)候圖片中的缺口和拼圖是沒有出現(xiàn)的,點(diǎn)擊后才出現(xiàn),這為我們找到缺口的位置提供了靈感。

第二步:拖到缺口位置。我們知道拼圖應(yīng)該拖到缺口處,但是這個(gè)距離如何用數(shù)值來表 示?通過第一步觀察到的現(xiàn)象,我們可以找到缺口的位置。這里我們可以比較兩張圖的像素, 設(shè)置一個(gè)基準(zhǔn)值,如果某個(gè)位置的差值超過了基準(zhǔn)值,那我們就找到了這兩張圖片不一樣的位置,當(dāng)然我們是從那塊拼圖的右側(cè)開始并且從左到右,找到第一個(gè)不一樣的位置時(shí)就結(jié)束,這時(shí)的位置應(yīng)該是缺口的 left,所以我們使用 selenium 拖到這個(gè)位置即可。這里還有個(gè)疑問,就 是如何能自動(dòng)保存這兩張圖?我們可以先找到這個(gè)標(biāo)簽,然后獲取它的 location 和 size,接著 是 top = int(location['y'])、bottom = int(location['y'] + size['height'])、left = int(location['x']) 以及right = int(location['x'] + size['width']),然后截圖,最后摳圖填入這四個(gè)位置就行。具體的使用 可以查看 selenium 文檔,點(diǎn)擊按鈕前摳一張圖,點(diǎn)擊后再摳一張圖。最后拖動(dòng)時(shí)需要模擬人的 行為,先加速然后減速。因?yàn)檫@種驗(yàn)證碼有行為特征檢測(cè),人是不可能做到一直勻速的,否則 它就判定為是機(jī)器在拖動(dòng),這樣就無(wú)法通過驗(yàn)證了。

03 宮格驗(yàn)證碼

如圖4所示的驗(yàn)證碼,爬蟲難度比較大,每一次出現(xiàn)的都不一樣,就算出現(xiàn)一樣的,其拖動(dòng)順序也不相同。但是,我們發(fā)現(xiàn)不一樣的驗(yàn)證碼個(gè)數(shù)是有限的,這里采用模版匹配的方 法,把所有出現(xiàn)的驗(yàn)證碼保存下來,然后挑出不一樣的驗(yàn)證碼,按照拖動(dòng)順序命名。我們從 左到右從上到下,將其分別設(shè)為 1、2、3、4。上圖的滑動(dòng)順序?yàn)? 4→3→2→1,所以我們命名 4_3_2_1.png。當(dāng)驗(yàn)證碼出現(xiàn)的時(shí)候,用我們保存的圖片一一枚舉,與出現(xiàn)的這種來比較像素, 方法見“滑動(dòng)式驗(yàn)證碼”部分。如果匹配上了,拖動(dòng)順序就為 4→3→2→1。然后使用 selenium 模擬即可。

圖4 宮格驗(yàn)證碼

04 點(diǎn)擊式的圖文驗(yàn)證和圖標(biāo)選擇

1)圖文驗(yàn)證:通過文字提醒用戶點(diǎn)擊圖中相同字的位置從而進(jìn)行驗(yàn)證。

2)圖標(biāo)選擇:給出一組圖片,按要求點(diǎn)擊其中一張或多張。借用萬(wàn)物識(shí)別的難度阻擋 機(jī)器。這兩種原理相似,只不過一個(gè)是給出文字,點(diǎn)擊圖片中的文字,而一個(gè)是給出圖片,點(diǎn) 出內(nèi)容相同的圖片。這兩種都沒有特別好的方法,只能借助第三方識(shí)別接口來識(shí)別出相同的內(nèi) 容。推薦一個(gè)方法,把驗(yàn)證碼發(fā)過去,會(huì)返回相應(yīng)的點(diǎn)擊坐標(biāo),然后再使用 selenium 模擬點(diǎn)擊即可。

OCR驗(yàn)證碼

圖片

OCR(Optical Character Recognition,光學(xué)字符識(shí)別)是指電子設(shè)備(例如掃描儀或數(shù)碼相機(jī))檢查紙上打印的字符,通過檢測(cè)暗、亮的模式來確定其形狀,然后用字符識(shí)別方法將形狀翻譯成計(jì)算機(jī)文字的過程,下面介紹使用這種圖像識(shí)別技術(shù)輸入驗(yàn)證碼的方法。

驗(yàn)證碼識(shí)別基本步驟:

1)預(yù)處理

2)灰度化

3)二值化

4)去噪

5)分割

6)識(shí)別

在使用pytesseract之前,必須安裝 Tesseract-OCR,因?yàn)閜ytesserat 依賴于 Tesseract-OCR, 若未安裝則無(wú)法使用。首先使用 pytesseract 將彩色的圖像轉(zhuǎn)化為灰色的圖像。

  1. # 使用路徑導(dǎo)入圖片 
  2. im = Image.open(imgimgName)  
  3. # 使用byte流導(dǎo)入圖片  
  4. # im = Image.open(io.BytesIO(b))  
  5. # 轉(zhuǎn)化到灰度圖 
  6. imgry = im.convert('L')  
  7. # 保存圖像 
  8. imgry.save('gray-'+imgName) 

灰度化的圖像如圖5所示。

圖5 灰度化圖像

緊接著將所得的圖像二值化,將圖片處理為只有黑白兩色的圖片,利于后面的圖像處理和識(shí)別。

  1. # 二值化,采用閾值分割法,threshold為分割點(diǎn)  
  2. Threshold = 140  
  3. Table = [ ] 
  4. For j in range(256):  
  5. If j < threshold:  
  6. Table.append(0)  
  7. Else:  
  8. Table.append(1)  
  9. Out = imgry.point(table,'1')  
  10. Out.save('b'+imgName) 

二值化的圖像如圖 6 所示。

圖6 二值化圖像

最后進(jìn)行識(shí)別,得到的結(jié)果如圖7所示。

圖7 識(shí)別結(jié)果

  1. # 識(shí)別  
  2. Text = pytesseract.image_to_string(out)  
  3. Print(“識(shí)別結(jié)果:" +text) 

實(shí)戰(zhàn)案例

目前,很多網(wǎng)站為了防止爬蟲肆意模擬瀏覽器登錄,采用增加驗(yàn)證碼的方式來攔截爬蟲。驗(yàn)證碼的形式有多種,最常見的就是圖片驗(yàn)證碼。

1 基本識(shí)別原理概述

1)每一幅圖像在結(jié)構(gòu)上,都是由一個(gè)個(gè)像素組成的矩陣,每一個(gè)像素都為單元格。

2)彩色圖像的像素由三原色(紅、綠、藍(lán))構(gòu)成 元組,灰度圖像的像素是一個(gè)單值,每個(gè)像素的值范圍為(0, 255)。

某系統(tǒng)門戶登錄界面中的驗(yàn)證碼如圖8所示, 現(xiàn)在我們要實(shí)現(xiàn)自動(dòng)的驗(yàn)證碼識(shí)別。

圖8 驗(yàn)證碼

2 圖像特征

首先,我們仔細(xì)觀察一下這個(gè)驗(yàn)證碼圖像,可以發(fā)現(xiàn)一些如圖9所示的固定特征。

1)驗(yàn)證碼中的字符數(shù)始終為 6,并且是灰度圖像。

2)字符間的間隔看起來每次都一樣。

3)每個(gè)字符都是完全定義的。

4)圖像有許多雜散的黑暗像素,以及穿過圖像的線條作為干擾因素。

圖9 固定特征

3 圖像分析

使用一個(gè)工具(binary-image)以二進(jìn)制形式可視化圖像(0 表示黑色像素,1 表示白色像 素)。圖像尺寸為 45×180,每個(gè)字符分配 30 個(gè)像素的空間來進(jìn)行適配,從而使它們的間隔比 較均勻。因此,取得了驗(yàn)證碼識(shí)別路上的第一步。如圖10所示的結(jié)果:把圖像裁剪成 6 個(gè)不同的部分,每個(gè)部分的寬度均為 30 像素。

圖10 二進(jìn)制可視化圖像

4 字符部分裁剪

圖像裁剪的語(yǔ)法如下:

  1. from PIL import Image  
  2. image = Image.open("filename.png")  
  3. cropped_image = image.crop((leftupperrightlower

比如要裁剪第一個(gè)字符:

  1. from PIL import Image  
  2. image = Image.open("captcha.png").convert("L")  
  3. cropped_image = image.crop((0, 0, 30, 45)) 
  4. cropped_image.save("cropped_image.png"

得到的圖像如圖11所示。

圖11 結(jié)果圖像

將其打包到一個(gè)循環(huán)中,編寫了一個(gè)簡(jiǎn)單的腳本,從該站點(diǎn)獲取 500 個(gè)驗(yàn)證碼圖像,并將所有裁剪后的字符保存到一個(gè)文件夾中。

5 圖像去雜

為了“清理”圖像中的干擾因素(刪除不必要的線和點(diǎn)),我們可以使用一個(gè)很簡(jiǎn)單的算法:字符中的所有像素都是純黑色(0)。如果它不是完全黑色的,則將它當(dāng)成白色的。因此,對(duì)于值大于0的每個(gè)像素,將給其重新賦值為255。使用 load() 函數(shù)將圖像轉(zhuǎn)換為 45×180 數(shù)字矩陣,然后對(duì)其進(jìn)行處理。

  1. pixel_matrix = cropped_image.load()  
  2. for col in range(0, cropped_image.height):  
  3. for row in range(0, cropped_image.width): 
  4. if pixel_matrix[row, col] != 0:  
  5. pixel_matrix[row, col] = 255 
  6. image.save("thresholded_image.png" 

為了清晰起見,將代碼應(yīng)用于原始圖像。原始圖像如圖12所示。

圖12 原始圖像

矯正后的圖像如圖13所示。

圖13 矯正后的圖像

可以看到,并非完全黑暗的所有像素都被刪除了,比如通過圖像的線。上述方法在圖像處理 中的專業(yè)術(shù)語(yǔ)叫作閾值處理,當(dāng)然還有很多其他的處理方法,閾值處理只是最簡(jiǎn)單實(shí)用的方法。

6 去除圖像中的黑點(diǎn)

圖像中有許多雜散的黑暗像素作為干擾因子。循環(huán)遍歷圖像矩陣,如果相鄰像素是白色的,并且與相鄰像素相對(duì)的像素也是白色的,而中心像素是黑色的,則設(shè)定中心像素為白色。

  1. for column in range(1, image.height - 1): 
  2. for row in range(1, image.width - 1): 
  3. if pi xel_matrix[row, column] == 0 and pixel_matrix[row, column - 1] == 255 and 
  4. pixel_matrix[row, column + 1] == 255: 
  5. pixel_matrix[row, column] = 255 
  6. if pi xel_matrix[row, column] == 0 and pixel_matrix[row - 1, column] == 255 and 
  7. pixel_matrix[row + 1, column] == 255: 
  8. pixel_matrix[row, column] = 25 

處理后的結(jié)果如圖14所示。

圖14 處理后的結(jié)果

經(jīng)過以上步驟的處理,圖像已經(jīng)只剩下字符框架了。雖然有些字符已經(jīng)丟失了一些基礎(chǔ)像 素,但是每個(gè)字符的圖像骨架基本上都完備。當(dāng)然這個(gè)是必需的,我們進(jìn)行這么多處理的主要 目的就是為每個(gè)可能的字符都截取生成合適的字符圖。

7 構(gòu)建字符圖庫(kù)

將上述算法裁剪得到的所有字符圖像都存儲(chǔ)于文件夾下。下一個(gè)任務(wù)是為屬于“ A-Z0-9” 的每個(gè)字符找到至少一個(gè)樣本圖像(如圖15所示)。這一步就像“訓(xùn)練”步驟,手動(dòng)為每個(gè) 字符選擇了一個(gè)字符圖像并對(duì)其更名。

圖15 樣本圖像

8 選擇最優(yōu)的字符圖

運(yùn)行其他幾個(gè)腳本,以確保每個(gè)字符的圖像中都有最佳的圖像,例如,如果有 20 個(gè)“ A” 的字符圖像,那么暗色數(shù)量最少的圖像顯然是噪聲最少的圖像,因此最適合作為骨架圖像。選擇的原則如下:

1)一個(gè)按照字符排序的相似圖像(約束條件:黑色像素?cái)?shù)量大小,并且相似度 > = 90%~95%)。

2)一個(gè)從每個(gè)分組字符獲得的最佳圖像。因此,到目前為止,我們生成了一個(gè)像素圖像庫(kù)。我們將其轉(zhuǎn)換為像素矩陣,并將位圖字符圖轉(zhuǎn)為數(shù)字點(diǎn)陣 JSON 文件。

9 識(shí)別算法

最后是獲取任何新的驗(yàn)證碼圖像的算法:使用相同的算法盡量減少新圖像中不必要的干擾因子。對(duì)于新驗(yàn)證碼圖片中的每個(gè)字符,強(qiáng)制通過與生成的 JSON 文件的像素矩陣來匹配,基 于相應(yīng)的黑色像素匹配來計(jì)算相似度。如果一個(gè)像素是黑色的,其在圖像中的位置恰好是待破 解的驗(yàn)證碼,并且此像素位于字符庫(kù)中的骨架圖像 / 位圖內(nèi)的相同位置處,則計(jì)數(shù)會(huì)遞增 1。與骨架圖像中黑色像素的數(shù)量進(jìn)行對(duì)比,計(jì)算匹配百分比,選擇具有最高匹配百分比的字符就是識(shí)別結(jié)果的字符。

最終結(jié)果如圖16所示,若得到的字符為 Z5M3MQ,則驗(yàn)證碼被成功識(shí)別出來了。

 

圖16 識(shí)別結(jié)果

 

責(zé)任編輯:武曉燕 來源: 數(shù)倉(cāng)寶貝庫(kù)
相關(guān)推薦

2021-08-02 12:29:15

Python爬蟲網(wǎng)站

2017-05-18 09:36:11

大數(shù)據(jù)爬蟲驗(yàn)證碼

2022-11-24 10:24:32

2020-11-16 07:28:53

驗(yàn)證碼

2022-09-14 23:06:45

2009-08-12 11:05:00

2016-10-13 15:51:50

2009-08-19 10:34:16

反爬蟲

2020-02-12 10:29:53

Python爬蟲公眾號(hào)

2022-09-20 07:02:20

網(wǎng)絡(luò)爬蟲反爬蟲

2020-10-28 09:44:22

Pythonn爬蟲代碼

2021-06-16 06:58:09

TensorFlow識(shí)別驗(yàn)證碼

2018-01-29 09:28:44

2013-06-19 10:19:59

2020-06-22 07:55:28

接口爬蟲

2016-10-14 16:35:39

2023-04-04 09:13:15

2024-06-07 08:56:43

HTTPPythonSelenium

2021-06-06 19:53:05

爬蟲處理字體反爬
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)