Python爬蟲:Cookie保存和加載

來源:公衆號【很酷的程序員/RealCoolEngineer】

自動登錄網站後,可以保存cookie,在有效期內可以直接加載cookie保持登錄狀態,而無需使用登錄api重新進行登錄。

本文主要介紹cookie的保存和加載,是上一篇文章:Python爬蟲:自動登錄下載實踐 的擴展,後續示例代碼基於這篇文章已有內容修改。

一 HTTP客戶端Cookie處理庫

Python3中Cookie處理使用的庫爲http.cookiejar,處理Cookie相關的常用的幾個類如下:

其中MozillaCookieJarLWPCookieJar都是對FileCookieJar的封裝,提供對不同標準的兼容而已,按需使用即可。

二 使用Cookie保持登錄狀態

使用Cookie保持登錄實現比較簡單:

  1. 在初次登錄成功後,將Cookie保存下來
  2. 再次登錄時,直接加載Cookie,如果Cookie沒有過期,直接返回即可;否則重新登錄

1 實現分析

因爲不同用戶的Cookie信息不同,後續可能需要自動登錄多個用戶,同時抓取多個用戶的信息,所以要將不同用戶的Cookie分開保存。所以可以初步設計爲:

  1. 將Cookie統一保存在系統用戶目錄下:~/.polar_spider/
  2. 將用戶的賬號郵箱或者用戶ID作爲次級目錄保存每個用戶各自的信息;
  3. 將緩存保存爲文件.cookie

對於requests.sessions.Session類,Cookie保存在cookies屬性中,源碼如下:

class Session(SessionRedirectMixin):
    ...
    def __init__(self):
        ...
        #: A CookieJar containing all currently outstanding cookies set on this
        #: session. By default it is a
        #: :class:`RequestsCookieJar <requests.cookies.RequestsCookieJar>`, but
        #: may be any other ``cookielib.CookieJar`` compatible object.
        self.cookies = cookiejar_from_dict({})

所以可以創建一個CookieJar對象覆蓋默認值,Session對象會自己解析登錄請求響應中的Cookie信息。

具體怎麼從HTTP響應中提取Cookie這裏暫不展開,感興趣可以查看requests的源碼。

2 實現

基於前面的分析設計,重構登錄的邏輯,Cookie處理這裏使用LWPCookieJar,核心代碼:

# 創建CookieJar對象
cookies = LWPCookieJar(filename=cookie_file)
# 保存Cookie
cookies.save()
# 加載Cookie
cookies.load()

修改後的登錄邏輯如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: Farmer Li,公衆號:很酷的程序員(RealCoolEngineer)
# @Date: 2021-04-06

from http.cookiejar import LWPCookieJar
import json
from pathlib import Path

import click
from requests.sessions import Session

USER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36'

DEAFULT_DOWNLOAD_DIR = Path.home() / 'Downloads/polar/'
DEFAULT_CACHE_DIR = Path.home() / '.polar_spider/'


class PolarSpider:
    def __init__(self, cache_dir: Path = DEFAULT_CACHE_DIR) -> None:
        self._session = Session()
        self._cache_dir: Path = cache_dir
        if not self._cache_dir.exists():
            self._cache_dir.mkdir(parents=True)

    def login(self, email, password):
        print("Login Polar Flow")
        url = "https://flow.polar.com/login"
        header = {
            'Referer': 'https://flow.polar.com/',
            'Rser-Agent': USER_AGENT
        }
        postData = {
            'returnUrl': '/',
            "email": email,
            "password": password,
        }

        cookie_file: Path = self._cache_dir / email / '.cookie'
        if not cookie_file.parent.exists():
            cookie_file.parent.mkdir(parents=True)
        self._session.cookies = LWPCookieJar(filename=cookie_file)
        if cookie_file.exists():
            self._session.cookies.load()
            # 判斷緩存是否過期
            expired = False
            for cookie in self._session.cookies:
                expired = cookie.is_expired()
                if expired:
                    break
            if not expired:
                print('Cookie is not expired, not need to login again')
                return True

            # 或者檢查登錄後才能訪問的API是否可以正常訪問,如果可以則表示Cookie沒有過期
            # if self.get_user_id() > 0:
            #     return True

        res = self._session.post(url, data=postData, headers=header)
        if res.status_code == 200:
            print('Login succeed')
            # 登錄成功保存Cookie
            self._session.cookies.save()
            return True
        else:
            print(f"statusCode = {res.status_code}")
            return False

注意這裏判斷Cookie是否過期的方式,對於不同的網站,Cookie的具體形式可能有所不同,所這個方式可能並不適用於所有的網站,需要根據具體情況分析。

在上一篇文章中,創建Session對象使用的是requests.session(),但是因爲這個函數是已經棄用了的,所以本篇文章修正爲直接使用requests.sessions.Session進行實例化。

以上便是Cookie保存和加載的一個示例,對於Cookie的操作還有一系列的api支持,在使用的過程中按實際需求查閱官方文檔即可。

其他相關細節,可以閱讀上一篇文章:
Python爬蟲:自動登錄下載實踐

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章