防止爬蟲被反爬的幾個主要策略

QLZhangXian發表於2021-12-15

爬蟲採整合為很多公司企業個人的需求,但正因為如此,反爬蟲的技術也層出不窮,像時間限制、IP限制、驗證碼限制等等,都可能會導致爬蟲無法進行。所以以下是一些防止爬蟲被反爬的幾個主要策略。
• 動態設定User-Agent(隨機切換User-Agent,模擬不同使用者的瀏覽器資訊,可以使用元件scrapy-random-useragent)
• 禁用Cookies(對於簡單網站可以不啟用cookies middleware,不向Server傳送cookies,有些網站通過cookie的使用發現爬蟲行為)可以通過COOKIES_ENABLED 控制 CookiesMiddleware 開啟或關閉
• 啟用Cookies(對於複雜網站,需要使用無頭瀏覽器scrapy-splash獲取js生成的複雜cookies
• 設定延遲下載(防止訪問過於頻繁,設定為 2秒 或更高)
• Google Cache 和 Baidu Cache:如果可能的話,使用谷歌/百度等搜尋引擎伺服器頁面快取獲取頁面資料。
• Referer 使用假的來源,比如百度帶關鍵詞的連結
• 使用IP地址池:現在大部分網站都是根據IP來ban的,可以通過億牛雲海量定製代理理池突破
• 使用 億牛雲爬蟲代理元件程式碼。

#! -- encoding:utf-8 --
import base64
import sys
import random
PY3 = sys.version_info[0] >= 3
def base64ify(bytes_or_str):
if PY3 and isinstance(bytes_or_str, str):
input_bytes = bytes_or_str.encode(‘utf8’)
else:
input_bytes = bytes_or_str
output_bytes = base64.urlsafe_b64encode(input_bytes)
if PY3:
return output_bytes.decode(‘ascii’)
else:
return output_bytes
class ProxyMiddleware(object):
def process_request(self, request, spider):

            # 代理伺服器(產品官網 [www.16yun.cn](http://www.16yun.cn/))
            proxyHost = "t.16yun.cn"
            proxyPort = "31111"
            # 代理隧道驗證資訊
            proxyUser = "username"
            proxyPass = "password"
            request.meta['proxy'] = "http://{0}:{1}".format(proxyHost,proxyPort)
            # 新增驗證頭
            encoded_user_pass = base64ify(proxyUser + ":" + proxyPass)
            request.headers['Proxy-Authorization'] = 'Basic ' + encoded_user_pass                    
            # 設定IP切換頭(根據需求)
            tunnel = random.randint(1,10000)
            request.headers['Proxy-Tunnel'] = str(tunnel)

修改專案配置檔案 (./專案名/settings.py)
DOWNLOADER_MIDDLEWARES = {
‘scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware’: 110,
‘專案名.middlewares.ProxyMiddleware’: 100,
}
設定下載中介軟體(Downloader Middlewares)
下載中介軟體是處於引擎(crawler.engine)和下載器(crawler.engine.download())之間的一層元件,可以有多個下載中介軟體被載入執行。
1. 當引擎傳遞請求給下載器的過程中,下載中介軟體可以對請求進行處理 (例如增加http header資訊,增加proxy資訊等);
2. 在下載器完成http請求,傳遞響應給引擎的過程中, 下載中介軟體可以對響應進行處理(例如進行gzip的解壓等)
要啟用下載器中介軟體元件,將其加入到 DOWNLOADER_MIDDLEWARES 設定中。 該設定是一個字典(dict),鍵為中介軟體類的路徑,值為其中介軟體的順序(order)。
這裡是一個例子:
DOWNLOADER_MIDDLEWARES = {
‘mySpider.middlewares.MyDownloaderMiddleware’: 543,
}
編寫下載器中介軟體十分簡單。每個中介軟體元件是一個定義了以下一個或多個方法的Python類:
class scrapy.contrib.downloadermiddleware.DownloaderMiddleware
process_request(self, request, spider)
• 當每個request通過下載中介軟體時,該方法被呼叫。
• process_request() 必須返回以下其中之一:一個 None 、一個 Response 物件、一個 Request 物件或raise IgnoreRequest:
• 如果其返回 None ,Scrapy將繼續處理該request,執行其他的中介軟體的相應方法,直到合適的下載器處理函式(download handler)被呼叫, 該request被執行(其response被下載)。
• 如果其返回 Response 物件,Scrapy將不會呼叫 任何 其他的 process_request() 或
process_exception() 方法,或相應地下載函式; 其將返回該response。 已安裝的中介軟體的
process_response() 方法則會在每個response返回時被呼叫。
• 如果其返回 Request 物件,Scrapy則停止呼叫
process_request方法並重新排程返回的request。當新返回的request被執行後,
相應地中介軟體鏈將會根據下載的response被呼叫。
• 如果其raise一個 IgnoreRequest 異常,則安裝的下載中介軟體的 process_exception() 方法會被呼叫。如果沒有任何一個方法處理該異常, 則request的errback(Request.errback)方法會被呼叫。如果沒有程式碼處理丟擲的異常, 則該異常被忽略且不記錄(不同於其他異常那樣)。
• 引數:
• request (Request 物件) – 處理的request
• spider (Spider 物件) – 該request對應的spider
process_response(self, request, response, spider)
當下載器完成http請求,傳遞響應給引擎的時候呼叫
• process_request() 必須返回以下其中之一: 返回一個 Response 物件、 返回一個 Request 物件或raise一個 IgnoreRequest 異常。
• 如果其返回一個 Response (可以與傳入的response相同,也可以是全新的物件), 該response會被在鏈中的其他中介軟體的 process_response() 方法處理。
• 如果其返回一個 Request 物件,則中介軟體鏈停止, 返回的request會被重新排程下載。處理類似於 process_request() 返回request所做的那樣。
• 如果其丟擲一個 IgnoreRequest 異常,則呼叫request的errback(Request.errback)。 如果沒有程式碼處理丟擲的異常,則該異常被忽略且不記錄(不同於其他異常那樣)。
• 引數:
• request (Request 物件) – response所對應的request
• response (Response 物件) – 被處理的response
• spider (Spider 物件) – response所對應的spider
使用案例:
1. 建立middlewares.py檔案。
Scrapy代理IP、Uesr-Agent的切換都是通過DOWNLOADER_MIDDLEWARES進行控制,我們在settings.py同級目錄下建立middlewares.py檔案,包裝所有請求。

#!/usr/bin/env python

import random
import base64
from settings import USER_AGENTS
from settings import PROXIES

class RandomUserAgent(object):
def process_request(self, request, spider):
useragent = random.choice(USER_AGENTS)
request.headers.setdefault(“User-Agent”, useragent)
class RandomProxy(object):
def process_request(self, request, spider):
proxy = random.choice(PROXIES)
if proxy[‘user_passwd’] is None:

        # 沒有代理賬戶驗證的代理使用方式
        request.meta['proxy'] = "http://" + proxy['ip_port']
    else:
        # 對賬戶密碼進行base64編碼轉換
        base64_userpasswd = base64.b64encode(proxy['user_passwd'])
        # 對應到代理伺服器的信令格式裡
        request.headers['Proxy-Authorization'] = 'Basic ' + base64_userpasswd
        request.meta['proxy'] = "http://" + proxy['ip_port']

為什麼HTTP代理要使用base64編碼:
HTTP代理的原理很簡單,就是通過HTTP協議與代理伺服器建立連線,協議信令中包含要連線到的遠端主機的IP和埠號,如果有需要身份驗證的話還需要加上授權資訊,伺服器收到信令後首先進行身份驗證,通過後便與遠端主機建立連線,連線成功之後會返回給客戶端200,表示驗證通過,就這麼簡單,下面是具體的信令格式:
CONNECT 59.64.128.198:21 HTTP/1.1
Host: 59.64.128.198:21
Proxy-Authorization: Basic bGV2I1TU5OTIz
User-Agent: OpenFetion
其中Proxy-Authorization是身份驗證資訊,Basic後面的字串是使用者名稱和密碼組合後進行base64編碼的結果,也就是對username:password進行base64編碼。
HTTP/1.0 200 Connection established
OK,客戶端收到收面的信令後表示成功建立連線,接下來要傳送給遠端主機的資料就可以傳送給代理伺服器了,代理伺服器建立連線後會在根據IP地址和埠號對應的連線放入快取,收到信令後再根據IP地址和埠號從快取中找到對應的連線,將資料通過該連線轉發出去。
2. 修改settings.py配置USER_AGENTS和PROXIES
• 新增USER_AGENTS:
USER_AGENTS = [
“Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)”,
“Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)”,
“Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)”,
“Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)”,
“Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6”,
“Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1”,
“Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0”,
“Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5”
]
• 新增代理IP設定PROXIES:
代理IP可以購買億牛雲的爬蟲代理IP:
PROXIES = [
{‘ip_port’: ‘t.16yun.cn:31111’, ‘user_passwd’: ‘16yun:16yun’},
{‘ip_port’: ‘t.16yun.cn:31112’, ‘user_passwd’: ‘16yun:16yun’}
]
• 除非特殊需要,禁用cookies,防止某些網站根據Cookie來封鎖爬蟲。COOKIES_ENABLED = False
• 設定下載延遲DOWNLOAD_DELAY = 3
• 最後設定setting.py裡的DOWNLOADER_MIDDLEWARES,新增自己編寫的下載中介軟體類。
DOWNLOADER_MIDDLEWARES = {

        #'mySpider.middlewares.MyCustomDownloaderMiddleware': 543,
    'mySpider.middlewares.RandomUserAgent': 1,
    'mySpider.middlewares.ProxyMiddleware': 100
}

有防護需求或者等保合規業務可以與我聯絡電/微信 18039632519
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章