2022 年Python3 爬蟲教程 - OCR 識別圖形驗證碼

      網友投稿 1025 2025-03-31

      各類網站采用了各種各樣的措施來反爬蟲,其中一個措施便是使用驗證碼。隨著技術的發展,驗證碼的花樣越來越多。驗證碼最初是幾個數字組合的簡單的圖形,后來加入了英文字母和混淆曲線。還有一些網站使用了中文字符驗證碼,這使得識別愈發困難。

      12306 驗證碼的出現使得行為驗證碼開始發展起來,用過 12306 的用戶肯定多少為它的驗證碼頭疼過,我們需要識別文字,點擊與文字描述相符的圖片,驗證碼完全正確,驗證才能通過。隨著技術的發展,現在這種交互式驗證碼越來越多,如滑動驗證碼需要將對應的滑塊拖動到指定位置才能完成驗證,點選驗證碼則需要點擊正確的圖形或文字才能通過驗證。

      驗證碼變得越來越復雜,爬蟲的工作也變得越發艱難,有時候我們必須通過驗證碼的驗證才可以訪問頁面。

      本章就針對驗證碼的識別進行統一講解,涉及的驗證碼有普通圖形驗證碼、滑動驗證碼、點選驗證碼、手機驗證碼等,這些驗證碼識別的方式和思路各有不同,有直接使用圖像處理庫完成的,有的則是借助于深度學習技術完成的,有的則是借助于一些工具和平臺完成的。雖然說技術各有不同,但了解這些驗證碼的識別方式之后,我們可以舉一反三,用類似的方法識別其他類型驗證碼。

      我們首先來看最簡單的一種驗證碼,即圖形驗證碼,這種驗證碼最早出現,現在依然也很常見,一般由 4 位左右字母或者數字組成。

      例如這個案例網站 https://captcha7.scrape.center/ 就可以看到類似的驗證碼,如圖所示:

      這類驗證碼整體上比較規整,沒有過多干擾線和干擾點,且文字沒有大幅度的變形和旋轉。

      對于這一類的驗證碼我們就可以使用 OCR 技術來進行識別。

      1. OCR 技術

      OCR,即 Optical Character Recognition,中文翻譯叫做光學字符識別。它是指電子設備(例如掃描儀或數碼相機)檢查紙上打印的字符,通過檢測暗、亮的模式確定其形狀,然后用字符識別方法將形狀翻譯成計算機文字的過程。OCR 現在已經廣泛應用于生產生活中,如文檔識別、證件識別、字幕識別、文檔檢索等等。當然對于本節所述的圖形驗證碼的識別也沒有問題。

      本節我們會以當前示例網站的驗證碼為例來講解利用 OCR 來識別圖形驗證碼的流程,輸入上是一上圖驗證碼的圖片,輸出就是驗證碼識別結果。

      2. 準備工作

      識別圖形驗證碼需要 Tesserocr 庫,本庫的安裝相對沒有那么簡單,可以參考 https://setup.scrape.center/tesserocr

      另外在本節學習過程中還需要安裝 Selenium、Pillow、Numpy,Retrying 庫用作模擬登錄、圖像處理和操作重試,我們可以使用 pip3 來進行安裝:

      1

      pip3 install selenium pillow numpy retrying

      如果某個庫安裝有問題,可以參考如下鏈接:

      Selenium:https://setup.scrape.center/selenium

      Pillow:https://setup.scrape.center/pillow

      Numpy:https://setup.scrape.center/numpy

      retrying:https://setup.scrape.center/retrying

      安裝好了如上庫之后,我們就可以開始本節的學習了。

      3. 獲取驗證碼

      為了便于實驗,我們先將驗證碼的圖片保存到本地。

      我們可以在瀏覽器中打開上述示例網站,然后右鍵點擊這張驗證碼圖片,將其保存到本地,命名為 captcha.png,示例如圖所示:

      這樣我們就可以得到一張驗證碼圖片,以供測試識別使用。

      4. 識別測試

      接下來新建一個項目,將驗證碼圖片放到項目根目錄下,用 tesserocr 庫識別該驗證碼,代碼如下所示:

      1

      2

      3

      4

      5

      6

      import tesserocr

      from PIL import Image

      image = Image.open('captcha.png')

      result = tesserocr.image_to_text(image)

      print(result)

      在這里我們新建了一個 Image 對象,調用了 tesserocr 的 image_to_text 方法。傳入該 Image 對象即可完成識別,實現過程非常簡單,結果如下所示:

      1

      d241

      另外,tesserocr 還有一個更加簡單的方法,這個方法可直接將圖片文件轉為字符串,代碼如下所示:

      1

      2

      import tesserocr

      print(tesserocr.file_to_text('captcha.png'))

      可以得到同樣的輸出結果。

      這時候我們可以看到,通過 OCR 技術我們便可以成功識別出驗證碼的內容了。

      5. 驗證碼處理

      接下來我們換一個驗證碼,將其命名為 captcha2.png,如圖所示。

      重新用下面的代碼來測試:

      1

      2

      3

      4

      5

      6

      import tesserocr

      from PIL import Image

      image = Image.open('captcha2.png')

      result = tesserocr.image_to_text(image)

      print(result)

      可以看到如下輸出結果:

      1

      -b32d

      這次識別和實際結果有偏差,多了一些干擾結果,這是因為驗證碼內的多余的點干擾了圖像的識別,導致出現了一些多余的內容。

      對于這種情況,我們可以需要做一下額外的處理,把一些干擾信息去掉。

      這里觀察到圖片里面其實有一些雜亂的點,而這些點的顏色大都比文本更淺一點,因此我們可以做一些預處理,將干擾的點通過顏色來排除掉。

      我們可以首先將原來的圖像轉化為數組看下維度:

      1

      2

      3

      4

      5

      6

      7

      import tesserocr

      from PIL import Image

      import numpy as np

      image = Image.open('captcha2.png')

      print(np.array(image).shape)

      print(image.mode)

      運行結果如下:

      1

      2

      (38, 112, 4)

      RGBA

      可以發現這個圖片其實是一個三維數組,前兩維 38 和 112 代表其高和寬,最后一維 4 則是每個像素點的表示向量。為什么是 4 呢,因為最后一維是一個長度為 4 的數組,分別代表 R(紅色)、G(綠色)、B(藍色)、A(透明度),即一個像素點有四個數字表示。那為什么是 RGBA 四個數字而不是 RGB 或其他呢?這是因為 image 的模式 mode 是 RGBA,即有透明通道的真彩色,我們看到第二行輸出也印證了這一點。

      模式 mode 定義了圖像的類型和像素的位寬,一共有 9 種類型:

      1:像素用 1 位表示,Python 中表示為 True 或 False,即二值化。

      L:像素用 8 位表示,取值 0-255,表示灰度圖像,數字越小,顏色越黑。

      P:像素用 8 位表示,即調色板數據。

      RGB:像素用 3x8 位表示,即真彩色。

      RGBA:像素用 4x8 位表示,即有透明通道的真彩色。

      CMYK:像素用 4x8 位表示,即印刷四色模式。

      YCbCr:像素用 3x8 位表示,即彩-格式。

      I:像素用 32 位整型表示。

      F:像素用 32 位浮點型表示。

      為了方便處理,我們可以將 RGBA 模式轉為更簡單的 L 模式,即灰度圖像。

      我們可以利用 Image 對象的 convert 方法參數傳入 L,即可將圖片轉化為灰度圖像,代碼如下所示:

      1

      2

      image = image.convert('L')

      image.show()

      或者傳入 1 即可將圖片進行二值化處理,如下所示:

      1

      2

      image = image.convert('1')

      image.show()

      在這里我們就轉為灰度圖像,然后根據閾值篩選掉圖片中的干擾點,代碼如下:

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      from PIL import Image

      import numpy as np

      image = Image.open('captcha2.png')

      image = image.convert('L')

      threshold = 50

      array = np.array(image)

      array = np.where(array > threshold, 255, 0)

      image = Image.fromarray(array.astype('uint8'))

      image.show()

      在這里,變量 threshold 代表灰度的閾值,這里設置為 50。接著我們將圖片 image 轉化為了 Numpy 數組,接著利用 Numpy 的 where 方法對數組進行篩選和處理,這里指定了大于閾值的就設置為 255,即白色,否則就是 0,即黑色。

      最后看下圖片處理完之后是什么結果:

      我們發現原來驗證碼中的很多點已經被去掉了,整個驗證碼變得黑白分明。這時重新識別驗證碼,代碼如下所示:

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      import tesserocr

      from PIL import Image

      import numpy as np

      image = Image.open('captcha2.png')

      image = image.convert('L')

      threshold = 50

      array = np.array(image)

      array = np.where(array > threshold, 255, 0)

      image = Image.fromarray(array.astype('uint8'))

      print(tesserocr.image_to_text(image))

      即可發現運行結果變成如下所示:

      1

      b32d

      所以,針對一些有干擾的圖片,我們可以做一些去噪處理,這會提高圖片識別的正確率。

      6. 識別實戰

      最后,我們可以來嘗試下用自動化的方式來對案例進行驗證碼識別處理,這里我們使用 Selenium 來完成這個操作,代碼如下:

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      import time

      import re

      import tesserocr

      from selenium import webdriver

      from io import BytesIO

      from PIL import Image

      from retrying import retry

      from selenium.webdriver.support.wait import WebDriverWait

      from selenium.webdriver.support import expected_conditions as EC

      from selenium.webdriver.common.by import By

      from selenium.common.exceptions import TimeoutException

      import numpy as np

      def preprocess(image):

      image = image.convert('L')

      array = np.array(image)

      array = np.where(array > 50, 255, 0)

      image = Image.fromarray(array.astype('uint8'))

      return image

      @retry(stop_max_attempt_number=10, retry_on_result=lambda x: x is False)

      def login():

      【2022 年】Python3 爬蟲教程 - OCR 識別圖形驗證碼

      browser.get('https://captcha7.scrape.center/')

      browser.find_element_by_css_selector('.username input[type="text"]').send_keys('admin')

      browser.find_element_by_css_selector('.password input[type="password"]').send_keys('admin')

      captcha = browser.find_element_by_css_selector('#captcha')

      image = Image.open(BytesIO(captcha.screenshot_as_png))

      image = preprocess(image)

      captcha = tesserocr.image_to_text(image)

      captcha = re.sub('[^A-Za-z0-9]', '', captcha)

      browser.find_element_by_css_selector('.captcha input[type="text"]').send_keys(captcha)

      browser.find_element_by_css_selector('.login').click()

      try:

      WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.XPATH, '//h2[contains(., "登錄成功")]')))

      time.sleep(10)

      browser.close()

      return True

      except TimeoutException:

      return False

      if __name__ == '__main__':

      browser = webdriver.Chrome()

      login()

      在這里我們首先定義了一個 preprocess 方法,用于驗證碼的噪聲處理,邏輯就和前面說的是一樣的。

      接著我們定義了一個 login 方法,其邏輯執行步驟是:

      打開樣例網站

      找到用戶名輸入框,輸入用戶名

      找到密碼輸入框,輸入密碼

      找到驗證碼圖片并截取,轉化為 Image 對象

      預處理驗證碼,去除噪聲

      對驗證碼進行識別,得到識別結果

      識別結果去除一些非字母和數字字符

      找到驗證碼輸入框,輸入驗證碼結果

      點擊登錄按鈕

      等待「登錄成功」字樣的出現,如果出現則證明登錄成功,否則重復以上步驟重試。

      在這里我們還用到了 retrying 來指定了重試條件和重試次數,以保證在識別出錯的情況下反復重試,增加總的成功概率。

      運行代碼我們可以觀察到瀏覽器彈出并執行以上流程,可能重試幾次后得到登錄成功的頁面,運行過程如圖所示:

      登錄成功后的結果如圖所示:

      到這里,我們就能成功通過 OCR 技術識別成功驗證碼,并將其應用到模擬登錄的過程中了。

      7. 總結

      本節我們了解了利用 Tesserocr 識別驗證碼的過程并將其應用于實戰案例中實現了模擬登錄。為了提高 Tesserocr 的識別準確率,我們可以對驗證碼圖像進行預處理去除一些干擾,識別準確率會大大提高。但總歸來說 Tesserocr 識別驗證碼的準確率并不是很高,下一節我們來介紹其他識別驗證碼的方案。

      本節代碼:https://github.com/Python3WebSpider/CrackImageCaptcha

      本文參考資料:

      文檔 - OCR - 百度百科:https://baike.baidu.com/item/OCR

      OCR Python

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:excel求和不對是怎么回事
      下一篇:微軟發布的新版OneNote,免費、開放、全平臺覆蓋(Microsoft onenote)
      相關文章
      亚洲av无码av在线播放| 亚洲综合精品一二三区在线| 亚洲福利电影一区二区?| 亚洲av无码潮喷在线观看| 亚洲老妈激情一区二区三区| 久久久久亚洲精品无码网址| 亚洲一区二区三区免费| 精品亚洲视频在线观看 | 亚洲国产精品国产自在在线| 国产AV日韩A∨亚洲AV电影 | 婷婷亚洲综合一区二区| 日韩在线视精品在亚洲| 亚洲?V乱码久久精品蜜桃| 亚洲国产免费综合| 久久久久亚洲精品无码网址 | 久久精品亚洲AV久久久无码| 2020天堂在线亚洲精品专区| 亚洲日韩国产AV无码无码精品| 亚洲日本VA午夜在线影院| 亚洲AV色欲色欲WWW| 亚洲av无码乱码在线观看野外 | 亚洲人成电影网站| 亚洲熟妇无码AV不卡在线播放| 亚洲国产高清国产拍精品| www国产亚洲精品久久久日本| 亚洲国产午夜福利在线播放| 国产亚洲欧洲Aⅴ综合一区| 国产亚洲人成无码网在线观看| 婷婷亚洲综合五月天小说| 亚洲精彩视频在线观看| 国产婷婷综合丁香亚洲欧洲| 色偷偷尼玛图亚洲综合| 国产成人精品日本亚洲专区| 国产亚洲一区二区手机在线观看| 久久亚洲美女精品国产精品| 亚洲av无码一区二区三区天堂古代| 亚洲精品无码久久久久YW| 亚洲福利在线播放| 亚洲国产第一站精品蜜芽| 亚洲蜜芽在线精品一区| 亚洲色大成网站www永久男同|