跳到主要內容

詳解Python網頁爬蟲下載網頁驗證碼圖片(Captcha)的系統化作法

python_selenium_download_captcha_image

相信大家平常在瀏覽網頁的過程中,都有看過文字驗證碼(Captcha),要使用者輸入正確的英文數字才可以繼續操作,那要通過這種反爬蟲機制,就是要先把文字驗證碼(Captcha)的圖片下載下來,再進行後續的辨識動作。

這時候如果你使用圖片的src屬性來下載文字驗證碼(Captcha)圖片,會發現下載下來的圖片和網頁上的不一樣,是因為當我們發送請求到圖片的來源網址時,等於又再打開一次網頁的意思,它就會再次產生不一樣的文字驗證碼,導致下載下來的圖片會不一樣,解決方案就是使用Selenium套件來下載文字驗證碼(Captcha)圖片,這篇文章我就用博客來網站為例,來示範其中的實作方式。

  • 初始化Selenium動態網頁爬蟲專案
  • 使用Selenium下載文字驗證碼(Captcha)圖片
  • 儲存文字驗證碼(Captcha)圖片

一、初始化Selenium動態網頁爬蟲專案

首先,前往博客來網站,點擊「會員登入」,如下:

python_selenium_download_captcha_image

截取自博客來網路書店官網

複製登入頁面的網址,如下:

python_selenium_download_captcha_image

截取自博客來網路書店登入畫面

接著,建立Python網頁爬蟲檔案,引用Selenium相關的模組,如下:

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
import time
import base64

其中,各個模組的引用時機及原因可以參考我之前寫的全面掌握Selenium建置動態網頁爬蟲的步驟與重要模組文章。

再來,就可以建立瀏覽器驅動物件,發送請求到博客來網站的登入頁面,如下範例第8~9行:

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
import time
import base64


browser = webdriver.Chrome(ChromeDriverManager().install())
browser.get('https://cart.books.com.tw/member/login')

二、Selenium下載文字驗證碼(Captcha)圖片

回到博客來網站,在文字驗證碼(Captcha)圖片的地方點擊滑鼠右鍵,選擇「檢查」,可以看到它的網頁原始碼如下:

python_selenium_download_captcha_image

點擊滑鼠右鍵,選擇「Copy / Copy XPath」,使用XPath的方式來定位網頁圖片,如下:

python_selenium_download_captcha_image

開啟Python網頁爬蟲檔案,利用time模組等待5秒的時間,讓網頁載入文字驗證碼(Captcha)圖片完成後,就可以透過Selenium套件的execute_script()方法,執行擷取網頁圖片的JavaScript程式碼,如下範例:

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
import time
import base64


browser = webdriver.Chrome(ChromeDriverManager().install())
browser.get('https://cart.books.com.tw/member/login')

time.sleep(5)

img_base64 = browser.execute_script("""
    var ele = arguments[0];
    var cnv = document.createElement('canvas');
    cnv.width = ele.width; cnv.height = ele.height;
    cnv.getContext('2d').drawImage(ele, 0, 0);
    return cnv.toDataURL('image/jpeg').substring(22);    
    """, browser.find_element(By.XPATH, "//*[@id='captcha_img']/img"))

第13~19行的JavaScript程式碼簡單來說,就是先定位畫面上的文字驗證碼(Captcha)圖片,接著,建立一個畫布(canvas),將文字驗證碼(Captcha)繪製上去後,並且進行base64編碼。

三、儲存文字驗證碼(Captcha)圖片

有了文字驗證碼(Captcha)圖片的base64編碼之後,就可以利用base64模組的b64decode()方法解碼,寫入本地端的圖片檔(captcha_login.png)來進行儲存的動作,如下範例第21~22行:

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
import time
import base64


browser = webdriver.Chrome(ChromeDriverManager().install())
browser.get('https://cart.books.com.tw/member/login')

time.sleep(10)

img_base64 = browser.execute_script("""
    var ele = arguments[0];
    var cnv = document.createElement('canvas');
    cnv.width = ele.width; cnv.height = ele.height;
    cnv.getContext('2d').drawImage(ele, 0, 0);
    return cnv.toDataURL('image/jpeg').substring(22);    
    """, browser.find_element(By.XPATH, "//*[@id='captcha_img']/img"))

with open("captcha_login.png", 'wb') as image:
    image.write(base64.b64decode(img_base64))

執行之後就可以看到下載下來的文字驗證碼(Captcha)圖片,跟網頁上的是一樣的。

四、小結

這邊文章教大家學會使用Selenium套件動態下載網頁上的文字驗證碼(Captcha)圖片,接下來,就可以參考Selenium動態網頁爬蟲通過Captcha驗證碼的實用技巧文章,串接驗證碼辨識的服務,回填正確的文字驗證碼,通過反爬蟲機制,爬取想要的網頁資料。

你可能有興趣的文章










留言