天天看點

Scrapy 爬蟲架構五—— 常見的反爬蟲技術

爬蟲的本質就是“抓取”第二方網站中有價值的資料,是以,每個網站都會或多或少地采用一些反爬蟲技術來防範爬蟲。比如前面介紹的通過 User-Agent 請求頭驗證是否為浏覽器、使用 JavaScript 動态加載資源等,這些都是正常的反爬蟲手段。

下面針對更強的反爬蟲技術提供一些解決方案。

IP 位址驗證

有些網站會使用 IP 位址驗證進行反爬蟲處理,程式會檢查用戶端的 IP 位址,如果發現同一個 IP 位址的用戶端頻繁地請求資料, 該網站就會判斷該用戶端是爬蟲程式。

針對這種情況,我們可以讓 Scrapy 不斷地随機更換代理伺服器的 IP 位址,這樣就可以欺騙目标網站了。

為了讓 Scrapy 能随機更換代理伺服器,可以自定義一個下載下傳中間件,讓該下載下傳中間件随機更換代理伺服器即可。

Scrapy 随機更換代理伺服器隻要兩步:

  1. 打開 Scrapy 項目下的 middlewares.py 檔案,在該檔案中增加定義如下類:
class RandomProxyMiddleware (object) :
#動态設定代理伺服器的IP 位址
    def process request (self, request, spider):
        # get_random_proxy() 函數随機傳回代理伺服器的IP 位址和端口
        request.meta["proxy"] = get_random_proxy()
           
  1. 上面程式通過自定義的下載下傳中間件為 Scrapy 設定了代理伺服器。程式中的 get_random_proxy() 函數需要能随機傳回代理伺服器的 IP 位址和端口,這就需要開發者事先準備好一系列代理伺服器,該函數能随機從這些代理伺服器中選擇一個。
  2. 通過 settings.py 檔案設定啟用自定義的下載下傳中間件。在 settings.py 檔案中增加如下配置代碼:
#配置自定義的下載下傳中間件
DOWNLOADER MIDDLEWARES = {
    'ZhipinSpider.middlewares.RandomProxyMiddleware': 543,
}
           

禁用Cookie

有些網站可以通過跟蹤 Cookie 來識别是否是同一個用戶端。Scrapy 預設開啟了 Cookie,這樣目标網站就可以根據 Cookie 來識别爬蟲程式是同一個用戶端。

目标網站可以判斷,如果同一個用戶端在機關時間内的請求過于頻繁,則基本可以斷定這個用戶端不是正常使用者,很有可能是程式操作(比如爬蟲),此時目标網站就可以禁用該用戶端的通路。

針對這種情況,可以讓 Scrapy 禁用 Cookie(Scrapy 不需要登入時才可禁用 Cookie)。在 settings.py 檔案中取消如下代碼的注釋即可禁用 Cookie:

COOKIES_ENABLED = False
           

違反爬蟲規則檔案

在很多 Web 站點目錄下都會提供一個 robots.txt 檔案,在該檔案中制定了一系列爬蟲規則。例如,http://Weibo.com 網站下的 robots.txt 檔案的内容如下:

Sitemap: http://weibo.com/sitemap.xml User-Agent: Baiduspider Disallow : User-agent : 360Spider Disallow : User-agent : Googlebot Disallow : User-agent : Sogou web spider Disallow : User-agent:bingbot Disallow : User-agent : smspider Disallow : User-ageηt : HaosouSpider Disallow : User-agent : YisouSpider Disallow : User-agent : * Disallow : /

該規則檔案指定該站點隻接受 Baidu 的網絡爬蟲,不接受其他爬蟲程式。

為了讓爬蟲程式違反爬蟲規則檔案的限制,強行爬取站點資訊,可以在 settings 檔案中取消如下代碼的注釋來違反站點制定的爬蟲規則:

#指定不遵守爬蟲規則

ROBOTSTXT OBEY = False

限制通路頻率

正如前面所提到的,當同一個 IP 位址、同一個用戶端通路目标網站過于頻繁時(正常使用者的通路速度沒那麼快),其很可能會被當成機器程式(比如爬蟲)禁止通路。

為了更好地模拟正常使用者的通路速度,可以限制 Scrapy 的通路頻率。在 settings 檔案中取消如下代碼的注釋即可限制 Scrapy 的通路頻率:

#開啟通路頻率限制
AUTOTHROTTLE ENABLED = True
#設定通路開始的延遲
AUTOTHROTTLE START DELAY = 5
#設定通路之間的最大延遲
AUTOTHROTTLE MAX DELAY = 60
#設定Scrapy 并行發給每台遠端伺服器的請求數量
AUTOTHROTTLE TARGET CONCURRENCY= 1.0
#設定下裁之後的自動延遲
DOWNLOAD DELAY = 3
           

圖形驗證碼

有些網站為了防止機器程式通路,會做一些很“變态”的設計,它會記錄同一個用戶端、同一個IP位址的通路次數,隻要達到一定的通路次數(不管你是正常使用者,還是機器程式),目标網站就會彈出一個圖形驗證碼讓你輸入,隻有成功輸入了圖形驗證碼才能繼續通路。

為了讓機器識别這些圖形驗證碼,通常有兩種解決方式:

  1. 使用 PIL、Libsvrn 等庫自己開發程式來識别圖形驗證碼。這種方式具有最大的靈活性,隻是需要開發人員自己編碼實作。
  2. 通過第三方識别。有不少圖形驗證碼的線上識别網站,它們的識别率基本可以做到 90% 以上。但是識别率高的線上識别網站通常都要收費,而免費的往往識别率不高,還不如自己寫程式來識别。

針對 cloudflare 的政策

  1. 針對非 Scrapy 架構,可借助 cloudscraper 庫。先 pip install cloudscraper
import cloudscraper
from lxml.html import fromstring

scraper = cloudscraper.create_scraper()
resp = scraper.get('https://opensea.io/assets?search[query]=cryptopunks').text
selector = fromstring(resp)
title = selector.xpath('//h1/text()')
print(title)
           

2. 針對 Scrapy 架構

scrapy 原生對 cloudscraper的相容性差,而開源的 AroayCloudScraper 便做二次開發調整,才能提高相容性,github位址

超級簡單的使用方式(參考作者的文檔)

settings 設定:
# 預設日志級别
AROAY_CLOUDSCRAPER_LOGGING_LEVEL = logging.DEBUG(可調整)

預設逾時
AROAY_CLOUDSCRAPER_DOWNLOAD_TIMEOUT = 30

# 預設延遲
AROAY_CLOUDSCRAPER_DELAY = 1

#必須設定,否則報錯
COMPRESSION_ENABLED = False

RETRY_ENABLED: True
RETRY_TIMES: 3


DOWNLOADER_MIDDLEWARES = {
    'aroay_cloudscraper.downloadermiddlewares.CloudScraperMiddleware': 543,
}
           

使用如下 :

def start_requests(self):
        for page in range(1, 2):
            yield CloudScraperRequest(self.base_url, callback=self.parse_index, dont_filter=True, proxy={
                "http": "http://username:[email protected]:port",
                "https": "http://username:pas[email protected]:port",
            },cookies={"over18":"1"},timeout=5)