Python網絡爬蟲之如何用代碼識別圖片驗證碼

驗證碼

當我們在爬取某些網站的時候,對於一些頻繁請求,網站會識別你是機器還是人。如果是機器,直接不允許你訪問這個網站了,直接返回404或者禁止訪問。


最常見的方式就是驗證碼。驗證碼的主要功能就是區分當前訪問網站的是人還是代碼。越難識別或者越模糊的驗證碼區分能力卻強。網站想方設法的搞一些手段來對付技術,就是想讓服務器不用承受代碼大量訪問的壓力,這樣就能夠為正常用戶提供流暢的服務了。


但是,技術又能對付人們的想法。一來一去,就有了各種各樣的變態驗證碼,也有了各種各樣的應對方式。


常見的驗證碼有這麼幾種:

  • 圖像驗證
  • 語音驗證
  • 短信驗證
  • 極驗驗證
  • 點擊驗證

如何識別圖像驗證碼

來看看這些圖片驗證碼:

Python網絡爬蟲之如何用代碼識別圖片驗證碼

這些驗證碼大多是數字和字母組成,然後在此之上再添加一些模糊的噪點或者橫線豎線,或者把這些字符扭曲一下,增加識別難度。


接下來我們思考一下,我們要識別這類驗證碼要怎麼做呢?

首先要處理一下驗證碼圖片,什麼亂七八糟的噪點都儘量把它們去掉,讓圖片儘量黑白,儘量只剩下字符本身,然後再用 python 強大的 OCR 工具:

<code>Python-tesseract/<code>

來識別我們優化好的圖片,這樣正確率就會大大的提高。


我們用 python 搞幾張識別難度不同的驗證碼:

第一張

Python網絡爬蟲之如何用代碼識別圖片驗證碼

難度係數: ★,一顆星

第二張

Python網絡爬蟲之如何用代碼識別圖片驗證碼

難度係數: ★★,兩顆星

第三張

Python網絡爬蟲之如何用代碼識別圖片驗證碼

難度係數: ★★★,三顆星

第四張

Python網絡爬蟲之如何用代碼識別圖片驗證碼

難度係數: ★★★★,四顆星

第五張

Python網絡爬蟲之如何用代碼識別圖片驗證碼

難度係數 : ★★★★★,五顆星


先對第一張進行識別。第一張看起來比較清晰,識別起來沒有難度。


先安裝一下 pytesseract :

<code>pip install pytesseract/<code>

接著安裝一下 tesseract-ocr:

如果是 ubuntu 系統可以直接使用如下命令安裝:

<code>sudo apt install tesseract-ocr/<code>

如果是 win 系統自行百度一下安裝 tesseract-ocr 以及環境變量配置。


完了之後就導入相關模塊到代碼文件中:

<code>try:
from PIL import Image
except ImportError:
import Image
import pytesseract/<code>

接著打開第一張圖片,使用 pytesseract 識別,打印出結果:

<code>captcha = Image.open("captcha1.png")
result = pytesseract.image_to_string(captcha)
print(result)/<code>

結果:

Python網絡爬蟲之如何用代碼識別圖片驗證碼

識別成功!


接著來識別第 2 張:

Python網絡爬蟲之如何用代碼識別圖片驗證碼

<code>captcha = Image.open("claptcha2.png")
result = pytesseract.image_to_string(captcha)
print(result)/<code>

結果是

Python網絡爬蟲之如何用代碼識別圖片驗證碼


1924,結果有誤!pytesseract 準確率沒那麼高,沒辦法識別太多噪點的圖片。如果這個圖片再加上一點彩色背景如下圖:

Python網絡爬蟲之如何用代碼識別圖片驗證碼

對 pytesseract 來說更有難度。

所以我們先對這張圖片灰度處理一下:

<code>captcha = Image.open("captcha2.png")
result = captcha.convert('L')
result.show()/<code>

圖片就變成灰了:

Python網絡爬蟲之如何用代碼識別圖片驗證碼


雖然灰了,但是還不夠。除了處理灰度還需要對其進行“二值化”:

<code>def convert_img(img,threshold):
img = img.convert("L") # 處理灰度
pixels = img.load()
for x in range(img.width):
for y in range(img.height):
if pixels[x, y] > threshold:
pixels[x, y] = 255
else:
pixels[x, y] = 0
return img/<code>

調用一下:

<code>convert_img(captcha,150)/<code>

圖片就變成了:


Python網絡爬蟲之如何用代碼識別圖片驗證碼

非常清晰!

這時候對這張圖片識別一下:

<code># 識別一下
result = pytesseract.image_to_string(result)
print(result)/<code>

成功識別!

Python網絡爬蟲之如何用代碼識別圖片驗證碼


Python網絡爬蟲之如何用代碼識別圖片驗證碼

這時候直接去識別是識別不出來的。所以還是老辦法,先處理灰度,再進行“二值化”。這次再降一下噪:

<code>data = img.getdata()
w,h = img.size
count = 0
for x in range(1,h-1):
for y in range(1, h - 1):
# 找出各個像素方向
mid_pixel = data[w * y + x]
if mid_pixel == 0:
top_pixel = data[w * (y - 1) + x]
left_pixel = data[w * y + (x - 1)]
down_pixel = data[w * (y + 1) + x]
right_pixel = data[w * y + (x + 1)]

if top_pixel == 0:
count += 1
if left_pixel == 0:
count += 1
if down_pixel == 0:
count += 1
if right_pixel == 0:
count += 1
if count > 4:
img.putpixel((x, y), 0)/<code>

圖片變成這樣了:


Python網絡爬蟲之如何用代碼識別圖片驗證碼

再識別一下:

Python網絡爬蟲之如何用代碼識別圖片驗證碼


不過,pytesseract 不是萬能的,對於稍微複雜一點的就識別不出來了。至於這張:

Python網絡爬蟲之如何用代碼識別圖片驗證碼

我們肉眼都很難看出它是 1l1l0oO0,更不要說用代碼去識別了,所以 pytesseract 也識別不了。


對於一些簡單的驗證碼,使用 pytesseract 還是可以的。如果我們想提高 pytesseract 識別率,還可以去搞些圖片去訓練一下 tesseract-ocr。這樣,當我們遇到一些登錄需要驗證碼的網站時,直接引入本文識別驗證碼的方法就可以繼續爬數據了。


分享到:


相關文章: