1. 程式人生 > 實用技巧 >Python爬蟲反爬手段講解

Python爬蟲反爬手段講解

反爬方式的種類

1、判斷請求頭來進行反爬

這是很早期的網站進行的反爬方式

  • User-Agent 使用者代理
  • referer 請求來自哪裡
  • cookie 也可以用來做訪問憑證

解決辦法:請求頭裡面新增對應的引數(複製瀏覽器裡面的資料)

2、根據使用者行為來進行反爬

  • 請求頻率過高,伺服器設定規定時間之內的請求閾值
    解決辦法:降低請求頻率或者使用代理(IP代理)
  • 網頁中設定一些陷阱(正常使用者訪問不到但是爬蟲可以訪問到)
    解決辦法:分析網頁,避開這些特殊陷阱
  • 請求間隔太短,返回相同的資料
    解決辦法:增加請求間隔

3、js加密

反爬方式中較為難處理的一類。
js加密的原理:伺服器響應給瀏覽器的js檔案,可以動態的生成一些加密引數,瀏覽器會根據js的計算 得到這些引數,在請求中帶入進來,如果請求中沒有這些引數,那麼伺服器就任務請求無效。

4、字型加密

字型反爬,是一種常見的反爬技術,網站採用了自定義的字型檔案,在瀏覽器上正常顯示,但是爬蟲抓取下來的資料要麼就是亂碼,要麼就是變成其他字元。採用自定義字型檔案是CSS3的新特性,熟悉前端的同學可能知道,就是font-face屬性。

5、登入驗證碼

使用Python爬取網頁內容時往往會遇到使用驗證碼登陸才能訪問其網站,不同網站的使用的驗證碼也不同,在最開始使用簡單驗證碼,識別數字,但是隨著反爬的不斷髮展,慢慢設計出了更多複雜的驗證碼,比如:內容驗證碼、滑動驗證碼、圖片拼接驗證碼等等。
網上有很多打碼平臺,通過註冊賬號,呼叫平臺介面,進行驗證碼的驗證。

6、md5相關知識

MD5,訊息摘要演算法,一種被廣泛使用的密碼雜湊函式,可以產生出一個128位(16位元組)的雜湊值(hash value),用於確保資訊傳輸完整一致。MD5是最常見的摘要演算法,速度很快,生成結果是固定的128 bit位元組,通常用一個32位的16進位制字串表示。MD5的特點:

1.不可逆:不能從密文推匯出明文。
2.不管明文長度為多少,密文的長度都固定。
3.密文之間不會重複。

import hashlib
print(hashlib.md5('python'.encode()).hexdigest())

字串python加密後的結果:

23eeeb4347bdd26bfc6b7ee9a3b755dd

7、base64

Base64是網路上最常見的用於傳輸8Bit位元組碼的編碼方式之一,Base64就是一種基於64個可列印字元來表示二進位制資料的方法。Base64編碼是從二進位制到字元的過程,可用於在HTTP環境下傳遞較長的標識資訊。採用Base64編碼具有不可讀性,需要解碼後才能閱讀。

import base64

#python中base64的加密
print(base64.b64encode('python'.encode()).decode())
#python中base64的解密
print(base64.b64decode('Y2hpbmE='.encode()).decode())

結果:

cHl0aG9u
china

二、驗證碼驗證

自己動手看驗證碼(古詩詞網)

import requests

url = "gushiwen.org"

session = requests.Session()

text = session.get(url).text

#  解析響應,找到驗證碼的圖片地址,
#  下載驗證碼圖片,儲存
with open('code.jpg', 'wb')as f:
    f.write('驗證碼的url地址'.encode())

code = input('驗證碼是: ')

login_url = "login.com"

data = {
    "username": 'xx',
    "password": 'xx',
    "code": code
}
requests.post(url, data=data)

使用打碼平臺(圖鑑)

新建一個captcha_api.py

import json
import requests
import base64
from io import BytesIO
from PIL import Image
from sys import version_info


def base64_api(uname, pwd, img):
    img = img.convert('RGB')
    buffered = BytesIO()
    img.save(buffered, format="JPEG")
    if version_info.major >= 3:
        b64 = str(base64.b64encode(buffered.getvalue()), encoding='utf-8')
    else:
        b64 = str(base64.b64encode(buffered.getvalue()))
    data = {"username": uname, "password": pwd, "image": b64}
    result = json.loads(requests.post("http://api.ttshitu.com/base64", json=data).text)
    if result['success']:
        return result["data"]["result"]
    else:
        return result["message"]
    return ""


def request_captcha(uname, pwd, img_path):
    img_path = img_path  # 待驗證的驗證碼路徑
    img = Image.open(img_path)
    result = base64_api(uname, pwd, img)
    #  傳入賬號 密碼 和圖片
    print(result)

新建use_code.py,呼叫介面

img_path = '圖片路徑'

from captcha_api import request_captcha

ret = request_captcha("賬號", "密碼", img_path)