用python寫一個B站彈幕聊天機器人腳本
1 回覆B站彈幕基本框架:
(當時bing出來抄人家的, 能用- -但是忘記表明出處了, 實在是抱歉- -)
import requests, sys
def B_send(MSG): Cookies = "LIVE_BUVID=AUTO5015807896693605; _uuid=58C69C39-C741-47C7-0E98-A379326816DE70318infoc; buvid3=3B00857F-A757-4982-9792-4B46DEC0BB12155821infoc; sid=bejf3qns; LIVE_ROOM_ADMIN_UP_TIP=1; CURRENT_FNVAL=16; rpdid=|(k|k)k|))Y)0J'ul)|~mYmk|; im_notify_type_393056819=0; _ga=GA1.2.517604625.1581950019; dy_spec_agreed=1; GIFT_BLOCK_COOKIE=GIFT_BLOCK_COOKIE; INTVER=1; stardustpgcv=0606; DedeUserID=393056819; DedeUserID__ckMd5=43771d91224c7285; SESSDATA=bb15b3a2%2C1598937340%2C37fab*31; bili_jct=e8377d560fe3434ffd36531d323df842; CURRENT_QUALITY=80; bp_t_offset_393056819=365856292215780322; _dfcaptcha=08c1c131463a58b5c74c50f3d9eaed6d; Hm_lvt_8a6e55dbd2870f0f5bc9194cddf32a02=1583825216,1583853309,1583925148,1584087368; Hm_lpvt_8a6e55dbd2870f0f5bc9194cddf32a02=1584087368; PVID=15" cookie = {'Cookie': Cookies} data = { 'color':'16777215', 'fontsize':'25', 'mode':'1', 'msg':MSG, 'rnd':'1584087359', 'roomid':'21154895', 'bubble':'0', 'aid':'56737027', 'csrf_token':'e8377d560fe3434ffd36531d323df842', 'csrf':'e8377d560fe3434ffd36531d323df842' } requests.post('https://api.live.bilibili.com/msg/send', cookies=cookie, data=data)
|
獲取cookies 方法見視屏:…[還沒上傳]
2 獲取彈幕的方法:
用github的項目吧, xfgryujk/blivedm
這是我已知的, 最好的彈幕獲取項目
git clone https://github.com/xfgryujk/blivedm.git
|
3 聊天模塊
用: https://blog.csdn.net/qq_29129381/article/details/82865617
這個是最簡單的
抄來的代碼~, 感謝青云客智能聊天机器人的奉獻~
class airoot(object): def __init__(self): self.url = r'http://api.qingyunke.com/api.php?%s' self.data = { 'key':'free', 'appid':0, 'msg':'' } def getword(self, word=''): self.data['msg'] = word if self.data['msg'] == '': self.data['msg'] = '你不说话, 我来撩你吧' self.params = urllib.parse.urlencode(self.data) self.url = self.url % self.params self.page = urllib.request.urlopen(self.url,timeout=15).read() self.res = json.loads(self.page) self.res['content'] = self.res['content'].replace('{br}',' ') return self.res
|
4 在blivedm裏面, 加入聊天機器人的代碼
修改sample.py
把client ID改成要回覆彈幕的ID
async def _on_receive_danmaku(self, danmaku: blivedm.DanmakuMessage): print(f'{danmaku.uname}:{danmaku.msg}')
|
這兩行是彈幕, 直接用後面的{danmaku.msg}就好,
這裏, 我們改成
async def _on_receive_danmaku(self, danmaku: blivedm.DanmakuMessage): print(f'{danmaku.uname}:{danmaku.msg}') if f'{danmaku.uname}' != "史上最不正經的生物狗": B_send(airoot().getword(str(f'{danmaku.msg}'))['content'])
|
彈幕分割
因爲普通人員, 一個彈幕只能發20個字節, 字數多了, 會自動忽略, 所以需要分割分佈發送
def B_Slice(MSG): for i in range((len(MSG)//20)+1): B_send(MSG[i*20:(i+1)*20])
|
把分割套進去
async def _on_receive_danmaku(self, danmaku: blivedm.DanmakuMessage): print(f'{danmaku.uname}:{danmaku.msg}') if f'{danmaku.uname}' != "史上最不正經的生物狗": B_Slice(airoot().getword(str(f'{danmaku.msg}'))['content'])
|
鏈接超時
發現經常連接超時, 然後卡在了那裏. 我設置了一個timeout=15, 在前面, 已更新
後面老地方, 加一個try
async def _on_receive_danmaku(self, danmaku: blivedm.DanmakuMessage): print(f'{danmaku.uname}:{danmaku.msg}') if f'{danmaku.uname}' != "史上最不正經的生物狗": try: MSG = airoot().getword(str(f'{danmaku.msg}'))['content'] except: MSG = "鏈接超時了 = =(自動回覆)" B_Slice(MSG)
|
发送太快而被吞
加一个1s延迟,发送弹幕过多的时候
def B_Slice(MSG): for i in range((len(MSG)//20)+1): B_send(MSG[i*20:(i+1)*20]) time.sleep(1)
|
娛樂而已, 應該不會載更新了, /摔板凳
Sample.py
import asyncio,requests, sys, time import urllib.request import urllib.parse import json
import blivedm
class MyBLiveClient(blivedm.BLiveClient): _COMMAND_HANDLERS = blivedm.BLiveClient._COMMAND_HANDLERS.copy()
async def __on_vip_enter(self, command): print(command) _COMMAND_HANDLERS['WELCOME'] = __on_vip_enter
async def _on_receive_popularity(self, popularity: int): AAAAAAAA = 1 async def _on_receive_danmaku(self, danmaku: blivedm.DanmakuMessage): print(f'{danmaku.uname}:{danmaku.msg}') if f'{danmaku.uname}' != "史上最不正經的生物狗": try: MSG = airoot().getword(str(f'{danmaku.msg}'))['content'] except: MSG = "鏈接超時了 = =(自動回覆)" B_Slice(MSG)
async def _on_receive_gift(self, gift: blivedm.GiftMessage): print(f'{gift.uname} 赠送{gift.gift_name}x{gift.num} ({gift.coin_type}币x{gift.total_coin})')
async def _on_buy_guard(self, message: blivedm.GuardBuyMessage): print(f'{message.username} 购买{message.gift_name}')
async def _on_super_chat(self, message: blivedm.SuperChatMessage): print(f'醒目留言 ¥{message.price} {message.uname}:{message.message}')
class airoot(object): def __init__(self): self.url = r'http://api.qingyunke.com/api.php?%s' self.data = { 'key':'free', 'appid':0, 'msg':'' } def getword(self, word=''): self.data['msg'] = word if self.data['msg'] == '': self.data['msg'] = '你不说话, 我来撩你吧' self.params = urllib.parse.urlencode(self.data) self.url = self.url % self.params self.page = urllib.request.urlopen(self.url,timeout=15).read() self.res = json.loads(self.page) self.res['content'] = self.res['content'].replace('{br}',' ') return self.res
def B_send(MSG): Cookies = "" cookie = {'Cookie': Cookies} data = { 'color':'16777215', 'fontsize':'25', 'mode':'1', 'msg':MSG, 'rnd':'1584087359', 'roomid':'21154895', 'bubble':'0', 'aid':'56737027', 'csrf_token':'e8377d560fe3434ffd36531d323df842', 'csrf':'e8377d560fe3434ffd36531d323df842' } requests.post('https://api.live.bilibili.com/msg/send', cookies=cookie, data=data)
def B_Slice(MSG): for i in range((len(MSG)//20)+1): B_send(MSG[i*20:(i+1)*20]) time.sleep(1)
async def main(): client = MyBLiveClient(21154895, ssl=True) future = client.start() try: await future finally: await client.close()
if __name__ == '__main__': asyncio.get_event_loop().run_until_complete(main())
|
用戶自主開啓關閉機器人
有時候機器人實在是太煩了, 簡直煩到想取關
這裏, 我們可以添加一個屏蔽名單, 並用簡單的命令判斷,讓發彈幕的人, 自主選擇, 打開或者關閉機器人回答
爲了長久有效, 我們最好是, 把這個名單存入本地文件. 這裏, 取名IgnoreList,我直接把他放進同樣的路徑, 方便讀取.
def IgnoreList(USER,MSG): Ignore_List = open(sys.path[0]+"/IgnoreList",'r').read().split("\n")[:-1] if str(MSG) == "菲菲辛苦啦~": B_Slice("好的,菲菲先行告退了,愛你呦,木木噠~") Ignore_List += [USER] elif str(MSG) == "菲菲快回來~": try: Ignore_List.remove(USER) except: B_Slice("你一直都在菲菲心里哟~") Update = "\n".join(Ignore_List)+"\n" F = open(sys.path[0]+"/IgnoreList",'w') F.write(Update) F.close() return Ignore_List
|
防沉迷程序
爲了防止惡意刷屏,或者過於小盆友沉迷而耽誤學習, 因此在學習/工作時間內, 限制每分鐘內響應次數. 若超過, 則忽視多少分鐘
時間設定在早上9點,到晚上9點之間
Bubling_List = {} Bubling_ban = {}
def ToBubling_detect(User,Bubling_List,Bubling_ban,Times,TimeOut): Times -=1 if User != '史上最不正經的生物狗' and User not in Bubling_ban.keys(): if User not in Bubling_List.keys(): Bubling_List.update({User:{'Time': time.time(), 'Num': 1}}) else: Time_endur = time.time() - Bubling_List[User]['Time'] if Time_endur < 60 and Bubling_List[User]['Num'] > Times: Bubling_ban.update({User:time.time()}) B_Slice(User+" 因調戲菲菲過於頻繁,而被選擇性忽略5min, 略略略~") Bubling_List[User]['Num'] = 0 Bubling_List[User]['Time'] = time.time() elif Time_endur < 60 and Bubling_List[User]['Num'] <= Times: Bubling_List[User]['Num'] +=1 else: Bubling_List[User]['Num'] =1 Bubling_List[User]['Time'] = time.time() try: if time.time() - Bubling_ban[User] > TimeOut*60: Bubling_ban.pop(User) except Exception as e: Bubling_ban = Bubling_ban return Bubling_List, Bubling_ban
|
到此, 全程序爲: (自己加cookies)
import asyncio,requests, sys, time import urllib.request import urllib.parse import json
import blivedm
class MyBLiveClient(blivedm.BLiveClient): _COMMAND_HANDLERS = blivedm.BLiveClient._COMMAND_HANDLERS.copy()
async def __on_vip_enter(self, command): print(command) _COMMAND_HANDLERS['WELCOME'] = __on_vip_enter
async def _on_receive_popularity(self, popularity: int): AAAAAAAA = 1 async def _on_receive_danmaku(self, danmaku: blivedm.DanmakuMessage): global Bubling_List, Bubling_ban print(f'{danmaku.uname}:{danmaku.msg}') Bubling_List, Bubling_ban = ToBubling_detect(f'{danmaku.uname}',Bubling_List,Bubling_ban,10,5) Ignore_List = IgnoreList(f'{danmaku.uname}',f'{danmaku.msg}') Ignore_List += list(Bubling_ban.keys()) if f'{danmaku.uname}' not in Ignore_List: try: MSG = airoot().getword(str(f'{danmaku.msg}'))['content'] except: MSG = "鏈接超時了 = =(自動回覆)" B_Slice(MSG)
async def _on_receive_gift(self, gift: blivedm.GiftMessage): print(f'{gift.uname} 赠送{gift.gift_name}x{gift.num} ({gift.coin_type}币x{gift.total_coin})') B_Slice(str(f'谢谢{gift.uname} 赠送的{gift.gift_name}')) async def _on_buy_guard(self, message: blivedm.GuardBuyMessage): print(f'{message.username} 购买{message.gift_name}')
async def _on_super_chat(self, message: blivedm.SuperChatMessage): print(f'醒目留言 ¥{message.price} {message.uname}:{message.message}')
class airoot(object): def __init__(self): self.url = r'http://api.qingyunke.com/api.php?%s' self.data = { 'key':'free', 'appid':0, 'msg':'' } def getword(self, word=''): self.data['msg'] = word if self.data['msg'] == '': self.data['msg'] = '你不说话, 我来撩你吧' self.params = urllib.parse.urlencode(self.data) self.url = self.url % self.params self.page = urllib.request.urlopen(self.url,timeout=20).read() self.res = json.loads(self.page) self.res['content'] = self.res['content'].replace('{br}',' ') return self.res
def IgnoreList(USER,MSG): Ignore_List = open(sys.path[0]+"/IgnoreList",'r').read().split("\n")[:-1] if str(MSG) == "菲菲辛苦啦~": B_Slice("好的,菲菲先行告退了,愛你呦,木木噠~") Ignore_List += [USER] elif str(MSG) == "菲菲快回來~": try: Ignore_List.remove(USER) except: B_Slice("你一直都在菲菲心里哟~") Update = "\n".join(Ignore_List)+"\n" F = open(sys.path[0]+"/IgnoreList",'w') F.write(Update) F.close() return Ignore_List
def B_send(MSG): Cookies = "" cookie = {'Cookie': Cookies} data = { 'color':'16777215', 'fontsize':'25', 'mode':'1', 'msg':MSG, 'rnd':'1584087359', 'roomid': str(ROOM_ID), 'bubble':'0', 'aid':'56737027', 'csrf_token':'e8377d560fe3434ffd36531d323df842', 'csrf':'e8377d560fe3434ffd36531d323df842' } requests.post('https://api.live.bilibili.com/msg/send', cookies=cookie, data=data)
Bubling_List = {} Bubling_ban = {} def ToBubling_detect(User,Bubling_List,Bubling_ban,Times,TimeOut): Times -=1 if User != '史上最不正經的生物狗' and User not in Bubling_ban.keys(): if User not in Bubling_List.keys(): Bubling_List.update({User:{'Time': time.time(), 'Num': 1}}) else: Time_endur = time.time() - Bubling_List[User]['Time'] if Time_endur < 60 and Bubling_List[User]['Num'] > Times: Bubling_ban.update({User:time.time()}) B_Slice(User+" 因調戲菲菲過於頻繁,而被選擇性忽略5min, 略略略~") Bubling_List[User]['Num'] = 0 Bubling_List[User]['Time'] = time.time() elif Time_endur < 60 and Bubling_List[User]['Num'] <= Times: Bubling_List[User]['Num'] +=1 else: Bubling_List[User]['Num'] =1 Bubling_List[User]['Time'] = time.time() try: if time.time() - Bubling_ban[User] > TimeOut*60: Bubling_ban.pop(User) except Exception as e: Bubling_ban = Bubling_ban return Bubling_List, Bubling_ban
ROOM_ID = 21154895 def B_Slice(MSG): for i in range((len(MSG)//20)+1): B_send(MSG[i*20:(i+1)*20]) time.sleep(1)
async def main(): client = MyBLiveClient(ROOM_ID, ssl=True) future = client.start() try: await future finally: await client.close()
if __name__ == '__main__': asyncio.get_event_loop().run_until_complete(main())
|