動態解析521響應Cookie失效後,爬蟲如何繼續?

畢小寶發表於2020-12-16

背景

前面章節介紹了爬蟲的目標網站使用了兩次 JS 混淆反爬技術,模擬請求流程得到的動態 Cookie 資訊,遺憾的是,它的有效期是一個小時。Cookie 失效後,WebMagic 後面依舊是 521 響應碼。

本文探討的問題是:動態解析到的 Cookie 失效後,WebMagic 如何動態修改 Cookie 資訊呢?Site 類的 addHeader 和 addCookie ,哪個是決定最終請求頭域的要素呢?跟蹤了一遍 Spider 類的原始碼,找到了答案。

原始碼分析

第一,爬蟲的核心是使用 HttpClient 的 API 發起 HTTP 請求,頁面下載的方法是這個 download.
在這裡插入圖片描述
第二,它使用 HttpClient 爬蟲時,會快取 HttpClient 物件,看看它的類定義:

public class HttpClientDownloader extends AbstractDownloader {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private final Map<String, CloseableHttpClient> httpClients = new HashMap<String, CloseableHttpClient>();

    private HttpClientGenerator httpClientGenerator = new HttpClientGenerator();

    private HttpUriRequestConverter httpUriRequestConverter = new HttpUriRequestConverter();
    }

每次執行下載操作時,先從快取中獲取 HttpClient 物件,以 domain 為 Key,也就是說相同 domain 爬蟲時,都是用的同一個 HttpClient 物件:
在這裡插入圖片描述
第三,它通過 HttpClientGenerator 的 getClient 生成包含 Site 的 Cookie 的 HttpClient 物件,Cookie 資訊只在新建時使用一次,後面即使 Site 的 Cookie 資訊發生變化,也不生效:
在這裡插入圖片描述

真正請求時的頭域和 Cookie 來源

下載函式中,使用 HttpClient 傳送請求的程式碼
在這裡插入圖片描述
它的定義是:
在這裡插入圖片描述
convertHttpUrlRequest 方法,會真正使用 Site 的頭域資訊
在這裡插入圖片描述
因此,如果想讓爬蟲請求的頭域資訊動態變化,有兩種方式:

  1. 修改 Site 物件的 Header ,使用 addHeader(“cookie”,cookie) 修改頭域;這個比較容易。
  2. new Request 新請求時,為其設定 Cookie ,比較麻煩,所有涉及到新建請求的地方都需要。

對 Spider 重新獲取 Cookie

最後來回答,如何重新設定的 Cookie 的問題。 WebMagic 使用了執行緒池,當 Cookie 過期時,所有執行緒都會再次遭遇 521 ,此時只需要由一個執行緒執行 Cookie 重新獲取操作。

Process 處理 Page 時,判斷響應碼,如果是 521 使用多執行緒同步,保證只有一個執行緒更新 Cookie:
在這裡插入圖片描述
refreshCookie 就是上一節介紹的解析兩次 521 動態 JS 得到新的 Cookie ,然後重新設定到 Site 中:
在這裡插入圖片描述

啟示錄

再總結下動態反扒的核心:

  • userAgent 頭域,必須一致,且是某一個固定有效的值
  • 使用 Site 的 setHeader 方式設定 Cookie 資訊
  • Cookie 失效再次 521 後,控制同步流程,利用 flag 標識和時間保證只重新獲取一次

相關文章