Bilibili 爬取歷史彈幕


查詢歷史彈幕 https://api.bilibili.com/x/v2/dm/history 時返回的是 ProtoBuf 格式的數據,需要用 protoc 和 google.protobuf 解析。

流程

首次使用,需要下載安裝。https://github.com/protocolbuffers/protobuf/releases 筆者在 Windows 下,下載安裝 win64 版本 protoc,並下載 python 版 protobuf 並編譯。中間有個小坑是 Win10 自帶的 python 在最后 install 步驟時會出現權限問題,加上 -user 即可。

先寫一個 dm.proto

syntax = "proto3";

package dm;

message DmSegMobileReply{
    repeated DanmakuElem elems=1;
}
message DanmakuElem{
    int64 id = 1;
    int32 progress = 2;
    int32 mode = 3;
    int32 fontsize = 4;
    uint32 color = 5;
    string midHash = 6;
    string content = 7;
    int64 ctime = 8;
    int32 weight = 9;
    string action = 10;
    int32 pool = 11;
    string idStr = 12;
}

利用 protoc 編譯為 python 解析文件 protoc --python_out=./ ./dm.proto

最后我們引用它來解析那些獲取到的 req.content 中的二進制流數據,得到一個 JSON 的形式。

Code

from google.protobuf.json_format import MessageToJson, Parse
import datetime
import requests
from bs4 import BeautifulSoup
import pandas as pd
import json
import csv
import dm_pb2
import myhtml

def createDatalist(datestart, dateend=None):
    if dateend is None:
        dateend = datetime.datetime.now().strftime('%Y-%m-%d')
    datestart = datetime.datetime.strptime(datestart, '%Y-%m-%d')
    dateend = datetime.datetime.strptime(dateend, '%Y-%m-%d')
    date_list = []
    date_list.append(datestart.strftime('%Y-%m-%d'))
    while datestart < dateend:
        datestart += datetime.timedelta(days=+1)
        date_list.append(datestart.strftime('%Y-%m-%d'))
    return date_list

headers = {
    'User-Agent': ?
    'Cookie': ?
}

def getDanmuHistory(url):
    try:
        danmu = requests.get(url, headers=headers)
        DM = dm_pb2.DmSegMobileReply()
        DM.ParseFromString(danmu.content)
        danmu = MessageToJson(DM)
        danmuobj = json.loads(danmu)
        return danmuobj
    except all:
        return []


def getDanmuHistoryRange(cid, start):
    ans = []
    for time in createDatalist(start):
        url = 'https://api.bilibili.com/x/v2/dm/web/history/seg.so?type=1&oid='+cid+'&date='+time
        ans += getDanmuHistory(url)
        print(time)
    return ans


def getCidByBid(queryBid):
    urlGetCid = "https://api.bilibili.com/x/player/pagelist?bvid=" + \
        queryBid + "&jsonp=jsonp"
    strCidJson = myhtml.getRequestsContentUtf8(urlGetCid)
    jsonCid = json.loads(strCidJson)
    print(jsonCid["data"])
    return str(jsonCid["data"][0]["cid"])


if __name__ == '__main__':
    bid = "BV16K4y1h7eq"
    cid = getCidByBid(bid)
    ans = getDanmuHistoryRange(cid, '2021-05-01')
    with open("output.json","w") as f:
        f.write(json.dumps(ans))

References

Bilibili_解析ProtoBuf格式的彈幕 - 軒_雨 - 博客園 (cnblogs.com)

(65條消息) 用python自動生成出生日期_zhplz123的博客-CSDN博客


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM