Python爬蟲日記八:利用API實時爬取斗魚彈幕

斗魚

一:前言

這些天一直想做一個斗魚爬取彈幕,但是一直考試時間不夠耸别,而且這個斗魚的api接口雖然開放了但是我在github上沒有找到可以完美實現(xiàn)連接健芭。我看了好多文章,學(xué)了寫然后總結(jié)一下秀姐。也為后面數(shù)據(jù)分析做準備慈迈,后面先對彈幕簡單詞云化,然后再對各個房間的數(shù)據(jù)可視化省有。
代碼地址:github.com/rieuse/DouyuTV


這次爬取的房間是斗魚直播的蕪湖大司馬痒留,因為他人氣比較多,方便分析蠢沿。主播也是我老鄉(xiāng)伸头,嘿嘿。然后把彈幕的信息的uid舷蟀,昵稱恤磷,等級,彈幕內(nèi)容保存mongodb雪侥。

先看看效果

Paste_Image.png

GIF.gif

二:運行環(huán)境

  • IDE:Pycharm
  • Python3.6
  • pymongo 3.4.0

三:實例分析

首先要想爬取彈幕要看看官方的開發(fā)文檔碗殷。

  • 第一點就是協(xié)議組成:
def sendmsg(msgstr):
    msg = msgstr.encode('utf-8')
    data_length = len(msg) + 8
    code = 689
    msgHead = int.to_bytes(data_length, 4, 'little') \
              + int.to_bytes(data_length, 4, 'little') + int.to_bytes(code, 4, 'little')
    client.send(msgHead)
    sent = 0
    while sent < len(msg):
        tn = client.send(msg[sent:])
        sent = sent + tn
Paste_Image.png
  • 第二點是登錄請求精绎,之后把這個傳遞給sendmsg即可發(fā)送請求:
 msg = 'type@=loginreq/username@=rieuse/password@=douyu/roomid@={}/\0'.format(roomid)
sendmsg(msg)
Paste_Image.png
  • 第三點是獲取彈幕信息
    msg_more = 'type@=joingroup/rid@={}/gid@=-9999/\0'.format(roomid)
    sendmsg(msg_more)
Paste_Image.png
  • 第四點是要保存登錄狀態(tài)
def keeplive():
    while True:
        msg = 'type@=keeplive/tick@=' + str(int(time.time())) + '/\0'
        sendmsg(msg)
        time.sleep(15)
  • 第五點是要把接受到的byte,轉(zhuǎn)換我們識別的編碼速缨,然后保存到monggodb,也可以保存到text文檔中代乃。
Paste_Image.png

  • 補充說明

到這里這個API的主要功能已經(jīng)了解了旬牲,剩下的就是具體實現(xiàn),有以下幾點:

  • 1.用戶輸入房間號搁吓,獲取房間說明
  • 2.發(fā)送數(shù)據(jù)后原茅,我們就會接受到斗魚返回的數(shù)據(jù),但是返回的數(shù)據(jù)是二進制所以我 們需要對數(shù)據(jù)轉(zhuǎn)換編碼堕仔。
  • 3.我這里爬取了斗魚用戶發(fā)送彈幕的信息有uid擂橘,昵稱,等級摩骨,彈幕內(nèi)容通贞,這里的等級有的人是空的,如果不處理就會造成錯誤所以要使用下面處理一下恼五。
if not level_more:
            level_more = b'0'

四:實戰(zhàn)代碼

點擊查看完整代碼

import multiprocessing
import socket
import time
import re
import pymongo
import requests
from bs4 import BeautifulSoup

clients = pymongo.MongoClient('localhost')
db = clients["DouyuTV_danmu"]
col = db["info"]

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = socket.gethostbyname("openbarrage.douyutv.com")
port = 8601
client.connect((host, port))

danmu_path = re.compile(b'txt@=(.+?)/cid@')
uid_path = re.compile(b'uid@=(.+?)/nn@')
nickname_path = re.compile(b'nn@=(.+?)/txt@')
level_path = re.compile(b'level@=([1-9][0-9]?)/sahf')

def sendmsg(msgstr):
    msg = msgstr.encode('utf-8')
    data_length = len(msg) + 8
    code = 689
    msgHead = int.to_bytes(data_length, 4, 'little') \
              + int.to_bytes(data_length, 4, 'little') + int.to_bytes(code, 4, 'little')
    client.send(msgHead)
    sent = 0
    while sent < len(msg):
        tn = client.send(msg[sent:])
        sent = sent + tn


def start(roomid):
    msg = 'type@=loginreq/username@=rieuse/password@=douyu/roomid@={}/\0'.format(roomid)
    sendmsg(msg)
    msg_more = 'type@=joingroup/rid@={}/gid@=-9999/\0'.format(roomid)
    sendmsg(msg_more)

    print('---------------歡迎連接到{}的直播間---------------'.format(get_name(roomid)))
    while True:
        data = client.recv(1024)
        uid_more = uid_path.findall(data)
        nickname_more = nickname_path.findall(data)
        level_more = level_path.findall(data)
        danmu_more = danmu_path.findall(data)
        if not level_more:
            level_more = b'0'
        if not data:
            break
        else:
            for i in range(0, len(danmu_more)):
                try:
                    product = {
                        'uid': uid_more[0].decode(encoding='utf-8'),
                        'nickname': nickname_more[0].decode(encoding='utf-8'),
                        'level': level_more[0].decode(encoding='utf-8'),
                        'danmu': danmu_more[0].decode(encoding='utf-8')
                    }
                    print(product)
                    col.insert(product)
                    print('成功導(dǎo)入mongodb')
                except Exception as e:
                    print(e)


def keeplive():
    while True:
        msg = 'type@=keeplive/tick@=' + str(int(time.time())) + '/\0'
        sendmsg(msg)
        time.sleep(15)


def get_name(roomid):
    r = requests.get("http://www.douyu.com/" + roomid)
    soup = BeautifulSoup(r.text, 'lxml')
    return soup.find('a', {'class', 'zb-name'}).string


if __name__ == '__main__':
    room_id = input('請出入房間ID: ')
    p1 = multiprocessing.Process(target=start, args=(room_id,))
    p2 = multiprocessing.Process(target=keeplive)
    p1.start()
    p2.start()

五:彈幕的后續(xù)使用

這里我們是將彈幕的幾個信息昌罩,uid,用戶昵稱灾馒,等級茎用,彈幕內(nèi)容保存到mongodb,后續(xù)要對數(shù)據(jù)分析就可以直接拿出來,如果我們只需要彈幕那么就可以只把彈幕信息保存到txt文檔中就行了轨功。
貼出我的github地址旭斥,我的爬蟲代碼和學(xué)習(xí)的基礎(chǔ)部分都放進去了,有喜歡的朋友可以點擊 start follw一起學(xué)習(xí)交流吧夯辖!github.com/rieuse/DouyuTV

加油琉预!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蒿褂,隨后出現(xiàn)的幾起案子圆米,更是在濱河造成了極大的恐慌,老刑警劉巖啄栓,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件娄帖,死亡現(xiàn)場離奇詭異,居然都是意外死亡昙楚,警方通過查閱死者的電腦和手機近速,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來堪旧,“玉大人削葱,你說我怎么就攤上這事〈久危” “怎么了析砸?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長爆袍。 經(jīng)常有香客問我首繁,道長,這世上最難降的妖魔是什么陨囊? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任弦疮,我火速辦了婚禮,結(jié)果婚禮上蜘醋,老公的妹妹穿的比我還像新娘胁塞。我一直安慰自己,他們只是感情好压语,可當我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布啸罢。 她就那樣靜靜地躺著,像睡著了一般无蜂。 火紅的嫁衣襯著肌膚如雪伺糠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天斥季,我揣著相機與錄音训桶,去河邊找鬼累驮。 笑死,一個胖子當著我的面吹牛舵揭,可吹牛的內(nèi)容都是我干的谤专。 我是一名探鬼主播,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼午绳,長吁一口氣:“原來是場噩夢啊……” “哼置侍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起拦焚,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤蜡坊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后赎败,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體秕衙,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年僵刮,在試婚紗的時候發(fā)現(xiàn)自己被綠了据忘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡搞糕,死狀恐怖勇吊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情窍仰,我是刑警寧澤汉规,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站辈赋,受9級特大地震影響鲫忍,放射性物質(zhì)發(fā)生泄漏膏燕。R本人自食惡果不足惜钥屈,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望坝辫。 院中可真熱鬧篷就,春花似錦、人聲如沸近忙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽及舍。三九已至未辆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間锯玛,已是汗流浹背咐柜。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工兼蜈, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拙友。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓为狸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親遗契。 傳聞我的和親對象是個殘疾皇子辐棒,可洞房花燭夜當晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容