Python爬蟲爬取B站up主所有動態內容

qiao39gs發表於2024-05-08

請注意,爬蟲的使用應遵守網站的爬蟲政策和法律法規,不要對網站造成不必要的負擔或違反服務條款。


透過瀏覽器審查元素檢視網路日誌,發現每次獲取動態資訊的請求地址都相同,首次載入時offset為空:

https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space?host_mid=25470223&offset=

隨著網頁的不斷下拉,offset引數無規律變換,第二次及以後的offset就在上一次次請求返回的json裡的"offset"中,將"offset"的值帶入下一次請求的引數中即可迴圈爬取。動態下拉到頭時,json中"has_more"會由true變為false,可以以此判斷是否結尾。此時的程式碼如下:

def fetch_data(offset):

    # 請求的URL
    url = "https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space"

    # 請求引數
    params = {
        "offset": offset,
        "host_mid": 25470223
    }

    # 傳送請求
    response = requests.get(url, params=params, headers=headers)

    # 解析JSON資料
    data = response.json()
    print(data) # 自行處理json物件

    # 檢查是否還有更多資料
    if data['data']['has_more']:
        # 如果有更多資料,使用新的offset發起新的請求
        fetch_data(data['data']['offset'])

# 從offset為空開始
fetch_data("")

直接爬取時,無法直接獲取到資料,經網上查詢為鑑權錯誤
{"code":-352,"message":"-352","ttl":1}

這時需要新增請求頭及必要的cookie,新增後可以正常爬取,"response.text"即為響應json字串,可自行儲存後單獨處理。並新增延時引數防止以後都逛不了B站:

import json
import time
import requests

# 新增請求頭
headers = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36',
    'Cookie':'buvid3=...; b_nut=...; _uuid=...; buvid4=...;' # up主動態頁審查元素自行獲取,必傳
}

def fetch_data(offset):

    # 每次請求時延時0.1秒
    time.sleep(0.1)

    # 請求的URL
    url = "https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space"

    # 請求引數
    params = {
        "offset": offset,
        "host_mid": 25470223 # up主id,up主動態頁審查元素自行獲取
    }

    # 傳送請求
    response = requests.get(url, params=params, headers=headers)

    # 解析JSON資料
    data = response.json()
    print(data) # 自行處理json物件

    # 檢查是否還有更多資料
    if data['data']['has_more']:
        # 如果有更多資料,使用新的offset發起新的請求
        fetch_data(data['data']['offset'])

# 從offset為空開始
fetch_data("")

相關文章