反爬與反反爬

JJJhr發表於2024-07-05

反爬原因

反爬(Anti-Scraping)機制是網站為防止自動化程式(爬蟲)過度抓取或惡意訪問而採取的保護措施。反爬的主要原因包括:

  1. 保護網站資源:大量的自動化訪問會消耗伺服器資源,影響正常使用者的訪問體驗。
  2. 保護資料隱私:一些網站的資料具有商業價值,網站希望保護這些資料不被自動化程式大量獲取。
  3. 防止惡意行為:防止垃圾郵件、資料盜竊、資料篡改等惡意行為。
  4. 維護使用者體驗:確保網站的正常運作,防止因爬蟲行為導致的頁面載入緩慢或崩潰。

什麼樣的爬蟲會被反

以下型別的爬蟲容易被反爬機制檢測並阻止:

  1. 高頻率請求的爬蟲:短時間內傳送大量請求,會觸發網站的頻率限制。
  2. 不遵守 robots.txt 檔案的爬蟲:無視網站的爬取規則和限制。
  3. 沒有模擬人類行為的爬蟲:請求頭中缺少常見的瀏覽器標識(如 User-Agent),沒有模擬滑鼠和鍵盤操作。
  4. 固定 IP 地址的爬蟲:長時間使用同一 IP 地址,容易被網站檢測並封禁。
  5. 沒有處理 JavaScript 的爬蟲:很多現代網站依賴 JavaScript 載入內容,無法處理這些內容的爬蟲容易被檢測。

常見概念與反爬方向

以下是一些常見的反爬概念和技術:

  1. robots.txt 檔案:網站透過 robots.txt 檔案指定哪些頁面允許爬取,哪些頁面禁止爬取。
  2. User-Agent:請求頭中的 User-Agent 標識可以表明請求來自哪種瀏覽器或爬蟲,很多網站會根據 User-Agent 做出反爬判斷。
  3. IP 封禁:網站可以檢測到來自同一 IP 地址的大量請求,並採取封禁措施。
  4. 驗證碼(CAPTCHA):在使用者登入、提交表單等關鍵操作時,透過驗證碼驗證使用者是否為機器人。
  5. Cookies 和會話:透過檢測請求中的 Cookies 和會話資訊來判斷請求是否正常。
  6. 頻率限制:限制單位時間內來自同一 IP 地址或會話的請求數量。
  7. JavaScript 檢測:使用複雜的 JavaScript 載入頁面內容,檢測使用者是否能夠執行 JavaScript。
  8. 行為分析:透過分析使用者的行為(如滑鼠移動、點選、滾動等)來判斷請求是否來自人類。

基於身份識別的反爬

這種反爬策略透過識別請求來源的身份特徵來檢測並阻止爬蟲。常見的方法包括檢查 IP 地址、User-Agent、Cookies 等。

常見方法

  1. IP 封禁:透過檢測同一 IP 地址的高頻請求來封禁 IP。
  2. User-Agent 檢查:檢查請求頭中的 User-Agent 欄位,識別常見的爬蟲標識。
  3. Cookies 和會話:透過設定和檢查 Cookies 來追蹤使用者會話,防止異常請求。

應對策略

  1. IP 輪換

    • 使用代理池定期更換 IP 地址。
    • 使用旋轉代理服務,如 ProxyMesh 或 Bright Data。
  2. 偽裝 User-Agent

    • 隨機選擇不同的 User-Agent 模擬不同的瀏覽器和裝置。
    • 使用真實的瀏覽器指紋。
  3. 處理 Cookies

    • 模擬登入過程獲取並使用有效的 Cookies。
    • 定期更新和維護 Cookies。
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options

# 使用代理池和隨機 User-Agent
proxy = "http://your_proxy_ip:port"
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"

# 配置 ChromeOptions
chrome_options = Options()
chrome_options.add_argument(f'--proxy-server={proxy}')
chrome_options.add_argument(f'user-agent={user_agent}')

# 例項化帶有配置物件的 ChromeDriver 物件
driver_path = 'path/to/chromedriver'
service = Service(driver_path)
driver = webdriver.Chrome(service=service, options=chrome_options)

# 開啟一個網站並獲取 Cookies
url = 'http://www.example.com'
driver.get(url)
cookies = driver.get_cookies()
print("Cookies:", cookies)

# 關閉瀏覽器
driver.quit()

基於爬蟲行為的反爬

這種反爬策略透過檢測請求行為模式來識別爬蟲。常見的方法包括頻率限制、行為分析等。

常見方法

  1. 頻率限制:限制單位時間內的請求數量。
  2. 行為分析:透過分析使用者行為(如滑鼠移動、點選、滾動等)來識別異常模式。
  3. JavaScript 檢測:使用複雜的 JavaScript 載入內容,檢測使用者是否能夠執行這些指令碼。

應對策略

  1. 模擬人類行為

    • 設定合理的請求間隔,避免高頻率訪問。
    • 使用像 Selenium 這樣的工具,模擬滑鼠移動、點選、滾動等操作。
  2. 處理 JavaScript

    • 使用無頭瀏覽器(Headless Browser)如 Headless Chrome、PhantomJS。
    • 執行頁面上的 JavaScript,確保載入完整內容。
from selenium import webdriver
from selenium.webdriver.common.by import By
import time

# 配置 ChromeOptions
chrome_options = Options()
chrome_options.add_argument("--headless")  # 無介面模式
chrome_options.add_argument("--disable-gpu")  # 禁用 GPU 加速

# 例項化帶有配置物件的 ChromeDriver 物件
driver_path = 'path/to/chromedriver'
service = Service(driver_path)
driver = webdriver.Chrome(service=service, options=chrome_options)

# 開啟一個網站
url = 'http://www.example.com'
driver.get(url)

# 模擬人類行為
time.sleep(2)  # 等待頁面載入
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")  # 滾動到底部
time.sleep(2)

# 查詢元素並點選
element = driver.find_element(By.ID, 'element_id')
element.click()
time.sleep(2)

# 關閉瀏覽器
driver.quit()

基於資料加密進行反爬

這種反爬策略透過對網站資料進行加密,使得抓取到的資料無法直接解析和使用。

常見方法

  1. 內容加密:對網頁內容進行加密,客戶端需要特定的解密方法才能讀取。
  2. 引數加密:對請求引數進行加密,防止爬蟲直接使用 URL 引數進行請求。
  3. 動態資料載入:透過 Ajax 或其他動態載入方式獲取資料,確保資料只在特定操作後才載入。

應對策略

  1. 分析和逆向工程

    • 使用瀏覽器開發者工具(如 Chrome DevTools)分析請求和響應。
    • 研究解密演算法,編寫相應的解密程式碼。
  2. 執行 JavaScript

    • 使用 Selenium 執行頁面上的 JavaScript,確保完整載入和解密資料。
    • 模擬所有必要的使用者操作。
from selenium import webdriver
from selenium.webdriver.common.by import By
import time

# 配置 ChromeOptions
chrome_options = Options()
chrome_options.add_argument("--headless")  # 無介面模式
chrome_options.add_argument("--disable-gpu")  # 禁用 GPU 加速

# 例項化帶有配置物件的 ChromeDriver 物件
driver_path = 'path/to/chromedriver'
service = Service(driver_path)
driver = webdriver.Chrome(service=service, options=chrome_options)

# 開啟一個網站
url = 'http://www.example.com'
driver.get(url)

# 等待動態資料載入
time.sleep(5)

# 獲取加密內容並解密
encrypted_element = driver.find_element(By.ID, 'encrypted_element_id')
encrypted_data = encrypted_element.text
# 假設你已經知道解密方法
decrypted_data = decrypt(encrypted_data)  # 使用自定義解密方法
print("Decrypted data:", decrypted_data)

# 關閉瀏覽器
driver.quit()

驗證碼-驗證碼的知識

驗證碼(Completely Automated Public Turing test to tell Computers and Humans Apart,CAPTCHA)是一種用於區分使用者是計算機還是人類的安全機制,常用於防止惡意自動化操作,如垃圾註冊、評論灌水等。常見的驗證碼型別有:

  1. 文字驗證碼:使用者需要輸入影像中的字元。
  2. 影像驗證碼:使用者需要選擇特定的影像或解決拼圖。
  3. 音訊驗證碼:使用者需要聽取音訊並輸入其中的字元。
  4. 行為驗證碼:使用者需要完成拖動滑塊、點選特定區域等操作。

驗證碼的反制措施

反制驗證碼通常需要透過以下幾種方法:

  1. 手動識別:人類使用者手動輸入驗證碼,適用於少量驗證碼。
  2. OCR(光學字元識別):使用OCR技術自動識別文字驗證碼。
  3. 打碼平臺:使用第三方打碼服務,由人工或自動系統識別驗證碼。
  4. 影像識別引擎:使用深度學習和計算機視覺技術識別複雜影像驗證碼。

驗證碼-影像識別引擎

影像識別引擎利用計算機視覺和深度學習技術自動識別驗證碼影像。常見的方法包括:

  1. 傳統影像處理:使用影像處理技術(如閾值處理、邊緣檢測、形態學操作等)提取驗證碼中的字元,然後使用OCR技術識別字元。
  2. 深度學習:使用卷積神經網路(CNN)等深度學習模型訓練一個影像識別引擎,能夠自動識別複雜的影像驗證碼。

影像處理和 OCR 識別

import cv2
import pytesseract

# 載入影像
image_path = 'captcha_image.png'
image = cv2.imread(image_path)

# 轉為灰度影像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 二值化處理
_, binary_image = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY_INV)

# 使用 OCR 識別文字
text = pytesseract.image_to_string(binary_image, config='--psm 7')
print("識別結果:", text)

使用深度學習識別驗證碼

訓練一個卷積神經網路(CNN)模型來識別驗證碼需要以下步驟:

  1. 資料收集:收集大量驗證碼影像及其對應的標籤。
  2. 資料預處理:對影像進行歸一化、分割等預處理操作。
  3. 模型訓練:使用深度學習框架(如 TensorFlow、Keras)訓練 CNN 模型。
  4. 模型評估和最佳化:評估模型效能,並進行最佳化。

以下是一個簡化的例子,展示如何使用 Keras 訓練一個 CNN 模型來識別驗證碼:

import numpy as np
import tensorflow as tf
from tensorflow.keras import layers, models
from tensorflow.keras.preprocessing.image import ImageDataGenerator

# 載入和預處理資料
# 假設我們有一個函式 load_data() 返回訓練和驗證資料
(X_train, y_train), (X_val, y_val) = load_data()

# 建立資料生成器
datagen = ImageDataGenerator(rescale=1.0/255.0)

# 構建 CNN 模型
model = models.Sequential([
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(height, width, channels)),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.Flatten(),
    layers.Dense(128, activation='relu'),
    layers.Dense(num_classes, activation='softmax')
])

# 編譯模型
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

# 訓練模型
model.fit(datagen.flow(X_train, y_train, batch_size=32), epochs=10, validation_data=(X_val, y_val))

# 評估模型
loss, accuracy = model.evaluate(X_val, y_val)
print("驗證集準確率:", accuracy)

JavaScript (JS) 是現代網頁中廣泛使用的指令碼語言,用於實現動態互動效果。爬取含有大量 JS 動態內容的網站時,通常需要解析和執行 JS 程式碼。以下是如何定位 JS 檔案、分析 JS 程式碼,以及使用 js2py 解析和執行 JS 程式碼的具體方法。

js解析-定位js檔案

定位 JS 檔案通常可以使用瀏覽器的開發者工具。以下是具體步驟:

  1. 開啟瀏覽器開發者工具:在 Chrome 中,可以按 F12Ctrl+Shift+I 開啟開發者工具。
  2. 檢視網路請求:切換到 “Network” 皮膚,重新整理頁面,檢視所有載入的資源。
  3. 過濾 JS 檔案:在過濾欄中輸入 *.js 或選擇 “JS” 過濾器,檢視載入的 JS 檔案。
  4. 檢視原始碼:點選任意 JS 檔案,可以檢視其原始碼。

js解析-js程式碼分析

分析 JS 程式碼可以幫助我們瞭解其功能、變數和函式的使用。常見的方法包括:

  1. 閱讀和理解程式碼:理解程式碼的邏輯、結構和變數作用範圍。
  2. 查詢關鍵函式:查詢頁面中關鍵功能(如資料載入、使用者互動)的實現函式。
  3. 分析 AJAX 請求:查詢和分析頁面中所有的 AJAX 請求,瞭解資料是如何載入和更新的。
  4. 除錯和斷點:在瀏覽器開發者工具中設定斷點,逐步除錯程式碼,瞭解其執行過程。

js解析-js2py使用

js2py 是一個 Python 庫,用於在 Python 環境中解析和執行 JS 程式碼。以下是安裝和使用 js2py 的具體方法:

安裝 js2py

pip install js2py

使用 js2py 解析和執行 JS 程式碼

以下是一個簡單的示例程式碼,展示如何使用 js2py 解析和執行 JS 程式碼:

import js2py

# 定義 JS 程式碼
js_code = """
function add(a, b) {
    return a + b;
}
"""

# 解析並執行 JS 程式碼
context = js2py.EvalJs()
context.execute(js_code)

# 呼叫 JS 函式
result = context.add(3, 4)
print("結果:", result)

解析和執行復雜的 JS 程式碼

如果需要解析和執行更復雜的 JS 程式碼,可以使用 js2py.translate_filejs2py.eval_js

import js2py

# 從檔案中載入 JS 程式碼
js_file_path = 'path/to/your_js_file.js'
context = js2py.EvalJs()
context.execute(open(js_file_path).read())

# 呼叫檔案中定義的 JS 函式
result = context.your_js_function()
print("結果:", result)

處理帶有 this 關鍵字的 JS 程式碼

js2py 也支援處理帶有 this 關鍵字的 JS 程式碼:

import js2py

# 定義 JS 類
js_code = """
class Calculator {
    constructor() {
        this.result = 0;
    }

    add(a, b) {
        this.result = a + b;
    }

    getResult() {
        return this.result;
    }
}
"""

# 解析並執行 JS 程式碼
context = js2py.EvalJs()
context.execute(js_code)

# 建立 JS 類的例項並呼叫方法
calculator = context.Calculator()
calculator.add(3, 4)
result = calculator.getResult()
print("結果:", result)

示例:解析和執行動態載入資料的 JS 程式碼

假設我們有一個網頁,其中包含透過 JS 動態載入資料的程式碼,我們可以使用 js2py 解析和執行這些程式碼,以獲取動態資料。以下是一個示例:

import requests
import js2py

# 獲取網頁內容
url = 'http://www.example.com'
response = requests.get(url)
html_content = response.text

# 提取並執行 JS 程式碼
js_code = """
function fetchData() {
    return "Dynamic data from JS";
}
"""

# 解析並執行 JS 程式碼
context = js2py.EvalJs()
context.execute(js_code)

# 呼叫 JS 函式獲取動態資料
dynamic_data = context.fetchData()
print("動態資料:", dynamic_data)

hashlib的使用

hashlib 是 Python 標準庫中的一個模組,提供了常見的雜湊演算法,如 MD5、SHA-1、SHA-256 等。它可以用於生成字串或檔案的雜湊值,常用於資料完整性校驗和密碼儲存。

常見雜湊演算法

以下是一些常見的雜湊演算法及其用途:

  • MD5:生成 128 位雜湊值,速度快,但已被證明不安全,適用於校驗檔案完整性等場景。
  • SHA-1:生成 160 位雜湊值,比 MD5 更安全,但也已被證明存在安全漏洞。
  • SHA-256:生成 256 位雜湊值,安全性高,適用於密碼儲存等安全要求高的場景。

示例程式碼

以下是使用 hashlib 生成字串和檔案雜湊值的示例程式碼:

import hashlib

# 生成字串的 MD5 雜湊值
def md5_hash(text):
    return hashlib.md5(text.encode()).hexdigest()

# 生成字串的 SHA-256 雜湊值
def sha256_hash(text):
    return hashlib.sha256(text.encode()).hexdigest()

# 生成檔案的 SHA-256 雜湊值
def sha256_file_hash(file_path):
    sha256 = hashlib.sha256()
    with open(file_path, 'rb') as f:
        while chunk := f.read(8192):
            sha256.update(chunk)
    return sha256.hexdigest()

# 示例使用
text = "Hello, World!"
print("MD5 雜湊值:", md5_hash(text))
print("SHA-256 雜湊值:", sha256_hash(text))

file_path = 'path/to/your/file.txt'
print("檔案的 SHA-256 雜湊值:", sha256_file_hash(file_path))

selenium使用代理ip

配置 Chrome 瀏覽器使用代理 IP

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options

# 配置代理 IP
proxy = "http://your_proxy_ip:port"

# 配置 ChromeOptions
chrome_options = Options()
chrome_options.add_argument(f'--proxy-server={proxy}')

# 例項化帶有配置物件的 ChromeDriver 物件
driver_path = 'path/to/chromedriver'
service = Service(driver_path)
driver = webdriver.Chrome(service=service, options=chrome_options)

# 開啟一個網站
url = 'http://www.example.com'
driver.get(url)

# 關閉瀏覽器
driver.quit()

相關文章