[Python] Python を単純なクローラーとして使用して B ステーションのコメントをクロールする

目次

I.はじめに

2. Webページを分析する

3. コード

1.頭

2. ルートコメントの取得

3. 子供のコメントを取得する

4、合計コード

V. まとめ


I.はじめに

        Bilibiliコメントには検索機能がないので、Bilibiliコメントをクロールしてローカルテキストに保存するクローラーを作成しました。

        まず、Python の request ライブラリと beautifulsoup ライブラリをインストールする必要があります

pipインストールリクエスト

pip インストール bs4

        「成功」と表示された場合は、インストールが成功したことを意味します

        必要なライブラリはすべてここにあります

import requests
from bs4 import BeautifulSoup
import re
import json
from pprint import pprint
import time

2. Webページを分析する

        Web ページの例        Lanyin「Exploring the Window」BV18T411G7xJ

        ページのソース コードを確認したところ、ソース コード内にコメントに関する情報が存在しないことがわかりました。コメントの位置までスライドを続けたところ、コメントが表示されるまでに読み込みに時間がかかっていることがわかり、この時点でコメントの情報を取得するにはパッケージをキャプチャする必要があると推測しました。

F12 を開き、ネットワーク        内の返信関連オプションを照会し、コメント情報を見つけます。

         URLを抽出して中の各種データを確認してみました

      

         ここの URL を通常に表示するには、なぜコールバックの背後にあるデータを削除する必要があるのか​​わかりません

より見やすくするには、 Json Formatter を         Edge にダウンロードしてください。

        パッケージにすべてのコメントを表示できないことがわかりました。引き続き下にスライドし、F12 で返信に関するデータを探し、URL を抽出します

        nextだけが変わることが分かりましたが、next=1とは何でしょうか?実際には、next=1 と next=0 のデータが同じであることがわかり、プログラミング時に直接 1 から開始できます。

        しかし、ルート コメントのみが存在し、サブコメントが存在しないことがわかりました。サブコメントは別のパッケージにあると思われます。コメントの 1 つのサブコメントを確認すると、F12 で新しいパッケージを検出しました。 。

        同様に、URL を抽出し、応答が必須のサブコメントであることを確認します。同様に、すべての返信を 1 ページに表示することはできず、観察すると、各コメントの pn が異なるだけであることがわかります。

         では、サブコメントとルートコメントはどのように関係しているのでしょうか?

        URL を観察すると、サブコメントの URL にルートがあることがわかり、ルートとサブコメントの整合性を調べたところ、ルートの rpid がサブコメントのルートであることがわかりまし。関係を見つけた。

         最後に、コードを書いているときに問題が見つかりました。一部のルート コメントは展開する必要がないため、サブコメント パッケージの返信項目は空であり、これらのコメントの情報はステム コメント パッケージに存在します。 、単純に判断するだけで済みます。

        構造を理解すると、プログラミングは非常に簡単になります。

3. コード

1.頭

#网页头
headers = {
    "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36",
    "referer" : "https://www.bilibili.com/"
}

2. ルートコメントの取得

def get_rootReply(headers):
    num = 1
    replay_index = 1
    while True:
        URL = (f"https://api.bilibili.com/x/v2/reply/main?&jsonp=jsonp&next={num}&type=1&oid=470113786&mode=3&plat=1&_=1680096302818")   #获得网页源码
        respond = requests.get(URL , headers = headers) # 获得源代码 抓包
        # print(respond.status_code)
        reply_num = 0
        if(respond.status_code == 200): # 如果响应为200就继续,否则退出
            respond.encoding = "UTF-8"
            html = respond.text
            json_html = json.loads(html)    # 把格式转化为json格式 一个是好让pprint打印,一个是好寻找关键代码
            
            if json_html['data']['replies'] is None or len(json_html['data']['replies']) == 0 :
                break

            for i in range(0,len(json_html['data']['replies'])):   #一页只能读取20条评论
                reply = json_html['data']['replies'][reply_num]['content']['message']
                root = json_html['data']['replies'][reply_num]['rpid']
                reply = reply.replace('\n',',')
                # print(reply)
                file.write(str(replay_index) + '.' + reply + '\n')
                if json_html['data']['replies'][reply_num]['replies'] is not None:
                    if(get_SecondReply(headers,root) == 0):
                        for i in range(0,len(json_html['data']['replies'][reply_num]['replies'])):
                            reply = json_html['data']['replies'][reply_num]['replies'][i]['content']['message']
                            reply = reply.replace('\n',',')
                            file.write("        " + reply + '\n')
                reply_num += 1 
                replay_index += 1
            num += 1
            
            time.sleep(0.5)
        else :
            print("respond error!")
            break
    file.close()

3. 子供のコメントを取得する

def get_SecondReply(headers,root):
    pn = 1
    while True:
        URL = (f"https://api.bilibili.com/x/v2/reply/reply?jsonp=jsonp&pn={pn}&type=1&oid=824175427&ps=10&root={root}&_=1679992607971")
        respond = requests.get(URL , headers = headers) # 获得源代码 抓包
        reply_num = 0
        if(respond.status_code == 200):
            respond.encoding = "UTF-8"
            html = respond.text
            json_html = json.loads(html)
            
            if json_html['data']['replies'] is None:
                if(pn == 1):
                    return 0
                else :
                    return 1
            
            for i in range(0,len(json_html['data']['replies'])):
                if json_html['data']['replies'] is None:
                    break
                reply = json_html['data']['replies'][reply_num]['content']['message']
                reply = reply.replace('\n',',')
                # print(reply)
                reply_num += 1
                file.write("        " + reply + '\n')
            pn += 1
            time.sleep(0.5)
        else:
            print("Sreply error!")
            exit(-1)

このようにして、すべてのモジュールが組み立てられます

4、合計コード

import requests
from bs4 import BeautifulSoup
import re
import json
from pprint import pprint
import time

#网页头
headers = {
    "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36",
    "referer" : "https://www.bilibili.com/"
}

file = open('lanyin.txt', 'w',encoding='utf-8')

def get_SecondReply(headers,root):
    pn = 1
    while True:
        URL = (f"https://api.bilibili.com/x/v2/reply/reply?jsonp=jsonp&pn={pn}&type=1&oid=824175427&ps=10&root={root}&_=1679992607971")
        respond = requests.get(URL , headers = headers) # 获得源代码 抓包
        reply_num = 0
        if(respond.status_code == 200):
            respond.encoding = "UTF-8"
            html = respond.text
            json_html = json.loads(html)
            
            if json_html['data']['replies'] is None:
                if(pn == 1):
                    return 0
                else :
                    return 1
            
            for i in range(0,len(json_html['data']['replies'])):
                if json_html['data']['replies'] is None:
                    break
                reply = json_html['data']['replies'][reply_num]['content']['message']
                reply = reply.replace('\n',',')
                # print(reply)
                reply_num += 1
                file.write("        " + reply + '\n')
            pn += 1
            time.sleep(0.5)
        else:
            print("Sreply error!")
            exit(-1)

    
def get_rootReply(headers):
    num = 1
    replay_index = 1
    while True:
        URL = (f"https://api.bilibili.com/x/v2/reply/main?&jsonp=jsonp&next={num}&type=1&oid=470113786&mode=3&plat=1&_=1680096302818")   #获得网页源码
        respond = requests.get(URL , headers = headers) # 获得源代码 抓包
        # print(respond.status_code)
        reply_num = 0
        if(respond.status_code == 200): # 如果响应为200就继续,否则退出
            respond.encoding = "UTF-8"
            html = respond.text
            json_html = json.loads(html)    # 把格式转化为json格式 一个是好让pprint打印,一个是好寻找关键代码
            
            if json_html['data']['replies'] is None or len(json_html['data']['replies']) == 0 :
                break

            for i in range(0,len(json_html['data']['replies'])):   #一页只能读取20条评论
                reply = json_html['data']['replies'][reply_num]['content']['message']
                root = json_html['data']['replies'][reply_num]['rpid']
                reply = reply.replace('\n',',')
                # print(reply)
                file.write(str(replay_index) + '.' + reply + '\n')
                if json_html['data']['replies'][reply_num]['replies'] is not None:
                    if(get_SecondReply(headers,root) == 0):
                        for i in range(0,len(json_html['data']['replies'][reply_num]['replies'])):
                            reply = json_html['data']['replies'][reply_num]['replies'][i]['content']['message']
                            reply = reply.replace('\n',',')
                            file.write("        " + reply + '\n')
                reply_num += 1 
                replay_index += 1
            num += 1
            
            time.sleep(0.5)
        else :
            print("respond error!")
            break
    file.close()

if __name__ == '__main__':
    get_rootReply(headers)
    print("sucessful")

V. まとめ

        私が自分で書いたコードはゴミなので、修正してください。

おすすめ

転載: blog.csdn.net/ClushioAqua/article/details/129834114