自動參加小電視抽獎
自動領取艦長、提督獎勵
運行一天大概能獲取1800包辣條
However. 每次凌晨B站後臺都會檢測帳號腳本,一次搶太多很容易被封號一週。
多是依據最大的連續領獎次數判斷的吧jquery
1、抽獎流程
1. 分析頁面可知
每當有人贈送小電視之類的禮物時
系統就會發送廣播彈幕(SYS_MSG)
2. 點擊廣播跳轉到抽獎房間
F12清空網絡請求
接着點擊抽獎
就找到了抽獎請求web
POST https://api.live.bilibili.com/gift/v3/smalltv/join
參數
ajax
響應
json
GET https://api.live.bilibili.com/gift/v3/smalltv/check data={ 'roomid':roomid }
響應
分析結果api
https://api.live.bilibili.com/gift/v3/smalltv/check https://api.live.bilibili.com/gift/v2/smalltv/check
參加抽獎的請求相同
2、代碼實現
api.py 添加Gift類cookie
class Gift(): def check_smalltv(self,s,roomid,ver='v2'): url='https://api.live.bilibili.com/gift/'+ver+'/smalltv/check' data={'roomid': roomid} return ajax(s,url,'GET',data) def join_smalltv(self,s,roomid,raffleId,csrf_token,visit_id='', type = 'Gift'): url= 'https://api.live.bilibili.com/gift/v3/smalltv/join' data={ 'roomid': roomid, 'raffleId': raffleId, 'type': type, 'csrf_token': csrf_token, 'visit_id': visit_id } return ajax(s,url,'POST',data) def check_guard(self,s,roomid,_type='_guard'): url='https://api.live.bilibili.com/lottery/v1/Lottery/check'+_type+'?roomid='+str(roomid) return ajax(s,url,'GET'); def join_guard(self,s,roomid,id,csrf_token,type='guard',visit_id=None): url= 'https://api.live.bilibili.com/lottery/v2/Lottery/join' data= { 'roomid': roomid, 'id': id, 'type': type, 'csrf_token': csrf_token, 'visit_id': visit_id } return ajax(s,url,'POST',data)
server.py添加抽獎類網絡
class Join: def __init__(self,Info,s): self.Info = Info self.check_roomids=[Info['roomid']] self.raffleId=0 self.hour_run=Timer(7.2e3,self.each_hour_run) self.s=s self.num=1 def join_smalltv(self,obj): if self.num==50: self.num=0 print('[跳過抽獎]['+obj['title']+']已跳過抽獎(roomid=' + str(obj['roomid'])+ ',raffleId=' + str(obj['raffleId'])+ ')') return self.num+=1 res=API.Gift.join_smalltv(self.s,obj['roomid'], obj['raffleId'],self.Info['csrf_token'],self.Info['visit_id']) code=res['code'] if code==0:Logger.info('[自動抽獎]['+obj['title']+']已參加抽獎(roomid=' + str(obj['roomid'])+ ',raffleId=' + str(obj['raffleId'])+ ')') elif code==400:Logger.warning('[自動抽獎][禮物抽獎]訪問被拒絕,您的賬號可能已經被封禁,已中止') elif code==65531:Logger.info('[自動抽獎][禮物抽獎]已參加抽獎(roomid=' + str(obj['roomid'])+ ',raffleId=' + str(obj['raffleId'])+ ')') else:Logger.error('[自動抽獎][禮物抽獎]已參加抽獎(roomid=' + str(obj['roomid'])+ ',raffleId=' + str(obj['raffleId'])+ ')'+res['msg']) def push_and_check_roomid(self,roomid): self.push_roomid(roomid) for roomid in self.check_roomids:self.check_and_join_guard(roomid) def push_roomid(self,roomid): if roomid in self.check_roomids:return self.check_roomids.append(roomid) def each_hour_run(self): res=API.Room.room_rank(self.s,"master_realtime_hour",'areaid_realtime_hour') for room in res['data']['list']:self.push_roomid(room['roomid']) res=API.Room.room_rank(self.s,"week_star_master",'week') for room in res['data']['list']:self.push_roomid(room['roomid']) def check_and_join_smalltv(self,roomid): res=API.Gift.check_smalltv(self.s,roomid,'v2') if res['code']==-400:return for data in res['data']: if data['raffleId']<=self.raffleId:continue self.raffleId=data['raffleId'] self.join_smalltv({'roomid':roomid,'raffleId':self.raffleId,'title':data['title']}) if len(res['data'])==0: res=API.Gift.check_smalltv(self.s,roomid,'v3') for data in res['data']['list']: if data['raffleId']<=self.raffleId:continue self.raffleId=data['raffleId'] self.join_smalltv({'roomid':roomid,'raffleId':self.raffleId,'title':data['title']}) self.push_and_check_roomid(roomid) def join_guard(self,obj): res=API.Gift.join_guard(self.s,obj['roomid'],obj['id'],self.Info['csrf_token']) print(obj['roomid']) Logger.info(res['data']['message']) def check_and_join_guard(self,roomid): res=API.Gift.check_guard(self.s,roomid) if len(res['data'])==0:return for guard in res['data']:self.join_guard({'id':guard['id'],'roomid':roomid}) res=API.Gift.check_guard(self.s,roomid,'') if len(res['data']['guard'])==0:return for guard in res['data']['guard']:self.join_guard({'id':guard['id'],'roomid':roomid})
utils.py添加日誌類session
@singleton class Logger: def __init__(self): handlers = { logging.NOTSET: "logs/notset.logs", logging.DEBUG: "logs/debug.logs", logging.INFO: "logs/info.logs", logging.WARNING: "logs/warning.logs", logging.ERROR: "logs/error.logs", logging.CRITICAL: "logs/critical.logs" } self.__loggers = {} logLevels = handlers.keys() fmt = logging.Formatter('%(asctime)s [%(levelname)s]: %(message)s') for level in logLevels: #建立logger logger = logging.getLogger(str(level)) logger.setLevel(level) #建立hander用於寫日日誌文件 log_path = os.path.abspath(handlers[level]) fh = logging.FileHandler(log_path) #定義日誌的輸出格式 fh.setFormatter(fmt) fh.setLevel(level) #給logger添加hander logger.addHandler(fh) self.__loggers.update({level: logger}) def info(self, message): self.__loggers[logging.INFO].info(message) def error(self, message): self.__loggers[logging.ERROR].error(message) def warning(self, message): self.__loggers[logging.WARNING].warning(message) def debug(self, message): self.__loggers[logging.DEBUG].debug(message) def critical(self, message): self.__loggers[logging.CRITICAL].critical(message)
utils.py添加 保存配置文件函數app
def save_py(moudle): keys,py=dir(moudle),'' for key in keys: if '__' in key:continue py+=key+'='+json.dumps(getattr(moudle,key),indent=4, separators=(',', ':'))+'\n' with open(moudle.__name__+".py",'w') as f:f.write(py)
添加配置文件 config.py函數
headers={ "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0", "Accept":"application/json, text/plain, */*", "Accept-Language":"zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2", "Accept-Encoding":"gzip, deflate, br", "Referer":"https://live.bilibili.com/", "Origin":"https://live.bilibili.com", "Connection":"keep-alive" } msg_info={ "reject_msg":[ "SEND_GIFT", "WELCOME", "WELCOME_GUARD", "COMBO_SEND", "ENTRY_EFFECT", "NOTICE_MSG", "DANMU_MSG", "ROOM_RANK", "WISH_BOTTLE", "COMBO_END" ], "receive_msg":[ "SYS_MSG", "SPECIAL_GIFT" ] } post_info={ "csrf_token":"", "visit_id":"", "roomid":392351, "uid":380741418 } ws_info={ "uid":380741418, "roomid":392351, "protover":1, "platform":"web", "clientver":"1.4.0" }
主程序
import os os.chdir('/data/jupyter/root/軟件/Bilibili') from jquery import http,session from servers import Join,Login from DanmuWS import DanmuWebSocket from config import * from utils import save_py import config %matplotlib inline #save_py(config) s=session(headers,'config/2685054765.txt') login=Login(s) join=Join(post_info,s) ws=None while not login.isLogin(): login.get_vdcode() login.loop_vdcode() ws_info['uid']=post_info['uid']=login.info['uid'] def oncmd(data): cmd=data["cmd"] if cmd in msg_info['reject_msg']:return if cmd=="SYS_MSG": if "real_roomid" in data:join.check_and_join_smalltv(data["real_roomid"]) def onlogin(data): print("login success") def onreconnect(code,data=None): global ws ws=data['dws'] room_num=0 def onheartbeat(num): if num>3:return close() if len(join.check_roomids)==0: global room_num join.each_hour_run() room_num+=1 if room_num>3:return join.hour_run.cancel() ws_info['roomid']=post_info['roomid']=join.check_roomids.pop() main() def main(): global ws try: print(ws_info['roomid']) ws = DanmuWebSocket(ws_info,'wss://broadcastlv.chat.bilibili.com/sub') ws.connect() ws.bind(onreconnect,onlogin,onheartbeat,oncmd) #ws.run_forever() except: close() def close(): ws.close() save_py(config) s.save() main()