def get_s_c(): global ver input_sessdata = var_sess.get() input_csrf = var_csrf.get() ver = Verify(sessdata=input_sessdata, csrf=input_csrf) ret = ver.check()['code'] if ret == 0: tkinter.messagebox.showinfo(message='验证成功!') elif ret == -1: tkinter.messagebox.showwarning(message='csrf 校验失败') elif ret == -2: tkinter.messagebox.showwarning(message='SESSDATA值有误')
def getVerify(logger=getLogger('bot')): config = loadConfig(logger=logger) if 'account' in config and 'sessdata' in config['account']: logger.debug('发现本地账号,验证是否有效...') verify = Verify(sessdata=config['account']['sessdata'], csrf=config['account']['bili_jct']) ck = verify.check() if ck.get('code') != 0: logger.warning('本地记录的账号失效,重新登录...') logger.debug(f'错误代码:{ck["code"]}, 错误原因:{ck["message"]}') else: logger.debug('获取Verify成功') return verify return loginBilibili()
def upload_video(self, title, url): verify = Verify(self.sessdata, self.csrf) # 上传视频 filename = video.video_upload("tmp.mp4", verify=verify) data = { "copyright": 2, "source": url, "cover": None, "desc": "转自微博", "desc_format_id": 0, "dynamic": "", "interactive": 0, "no_reprint": 0, "subtitles": { "lan": "", "open": 0 }, "tag": "搞笑,日常", "tid": 22, "title": title, "videos": [{ "desc": "转自微博", "filename": filename, "title": "P1" }] } # 提交投稿 try: result = video.video_submit(data, verify=verify) # 成功的话会返回bv号和av号 print(result) except Exception as e: print("出错了", e)
def login(self): b = Bilibili() b.login(username=self.username, password=self.password) self.access_token = b.access_token self.sessdata = b._session.cookies['SESSDATA'] self.bili_jct = b._session.cookies['bili_jct'] print(f"login successfully! {self.name} {self.access_token} {self.sessdata} {self.bili_jct}") self.verify = Verify(sessdata=self.sessdata, csrf=self.bili_jct)
def from_dict(save_dict: {str: Any}) -> 'CommentTask': comment_task = CommentTask( save_dict['sc_path'], save_dict['he_path'], save_dict['session_id'], Verify(save_dict['sessdata'], save_dict['csrf'])) for key, value in save_dict.items(): comment_task.__setattr__(key, value) return comment_task
def __init__(self): self.config_file = BASE_DIR / "config.json" self.config = self.__load__() login = self.config.get("login") if login and login["SESSDATA"].strip() and login["bili_jct"].strip(): self.__verify = Verify(sessdata=login["SESSDATA"], csrf=login["bili_jct"]) else: self.__verify = None
def from_dict(save_dict: {str: Any}) -> 'SubtitleTask': comment_task = SubtitleTask( save_dict['subtitle_path'], save_dict['bvid'], save_dict['cid'], Verify(save_dict['sessdata'], save_dict['csrf']) ) for key, value in save_dict.items(): comment_task.__setattr__(key, value) return comment_task
def upload(video_path, title, source_link, thumbnail_path, description, uploader, upload_date): verify = Verify(config.cookie_sessdata, config.cookie_jct) try: video_file = video.video_upload(path=video_path, verify=verify) print("[Upload] Uploaded video file successfully.") except Exception as e: raise (Exception( f"[Upload] Failed to upload video file. Make sure the video file exists / the connection to bilibili is available / bili_jct is valid. Reason:{e.args}" )) return try: thumbnail_file = video.video_cover_upload(path=thumbnail_path, verify=verify) print("[Upload] Uploaded thubmnail successfully.") except Exception as e: raise (Exception( "[Upload] Failed to upload thubmnail. Make sure the thubmnail file exists / the connection to bilibili is available / bili_jct is valid" )) return description = "频道: {} 上传日期:{}\n".format(uploader, upload_date) + description data = { "copyright": 2, "source": source_link, "cover": thumbnail_file, "desc": description[0:1999 - len(source_link)], "desc_format_id": 0, "dynamic": "", "interactive": 0, "no_reprint": 1, "subtitles": { "lan": "语言", "open": 0 }, "tag": config.bilibili_tag, "tid": config.bilibili_tid, "title": title, "videos": [{ "desc": "", "filename": video_file, "title": "1" }] } print("[Upload] Submitting") try: result = video.video_submit(data, verify) print("[Upload] Submitted") except Exception as e: raise Exception(e.args.__str__())
def post_comment(self, session_dict: {str: str}) -> bool: if (datetime.datetime.now(datetime.timezone.utc) - self.start_date).total_seconds() / 60 / 60 > HOURS_THRESHOLD: return True if self.session_id not in session_dict: return False if self.error_count > ERROR_THRESHOLD: return True bvid = session_dict[self.session_id] try: video.get_video_info(bvid) except bilibili_api.exceptions.BilibiliApiException: # Video not published yet return False print(f"posting comments on {bvid}") self.error_count += 1 verify = Verify(self.sessdata, self.csrf) # load sc and se text with open(self.sc_path, 'r') as file: # sc_str = process_text(file.read(), bvid) sc_str = file.read() with open(self.he_path, 'r') as file: # he_str = process_text(file.read(), bvid) he_str = file.read() sc_list = sc_str.split(SEG_CHAR) he_list = he_str.split(SEG_CHAR) try: if self.he_root_id == "": resp = send_comment(he_list[0], bvid=bvid, verify=verify) self.he_root_id = resp['rpid'] self.he_progress = 1 for i, content in enumerate(he_list): if i >= self.he_progress: send_comment(content, bvid=bvid, root=self.he_root_id, verify=verify) self.he_progress = i + 1 if self.sc_root_id == "": resp = send_comment(sc_list[0], bvid=bvid, verify=verify) self.sc_root_id = resp['rpid'] self.sc_progress = 1 for i, content in enumerate(sc_list): if i >= self.sc_progress: send_comment(content, bvid=bvid, root=self.sc_root_id, verify=verify) self.sc_progress = i + 1 except bilibili_api.exceptions.BilibiliApiException: print("Comment posting failed") print(print(traceback.format_exc())) return False return True
def upload(topic, date, videoFile, imageFile, mid, sig, community): """上传视频到b站""" sessdata = os.getenv('SESSDATA', '') bili_jct = os.getenv('BILI_JCT', '') if not sessdata or not bili_jct: logger.error('both sessdata and bili_jct required, please check!') sys.exit(1) verify = Verify(sessdata, bili_jct) # 上传视频 filename = video.video_upload(videoFile, verify=verify) logger.info('meeting {}: B站上传视频'.format(mid)) # 上传封面 cover_url = video.video_cover_upload(imageFile, verify=verify) logger.info('meeting {}: B站上传封面'.format(mid)) # 提交投稿 data = { "copyright": 1, "cover": cover_url, "desc": "openEuler meeting record for {}".format(sig), "desc_format_id": 0, "dynamic": "", "interactive": 0, "no_reprint": 1, "subtitles": { "lan": "", "open": 0 }, "tag": "{}, community, recordings, 会议录像".format(community), "tid": 124, "title": topic + " (" + date + ")", "videos": [{ "desc": "recordings download from OBS", "filename": os.path.basename(filename), "title": "P1" }] } result = video.video_submit(data, verify=verify) logger.info('meeting {}: B站提交视频'.format(mid)) # 返回bv号和av号 logger.info('meeting {}: 视频提交成功!生成的bvid为{}'.format(mid, result['bvid'])) return result
def upload(video_path, title, source_link, thumbnail_path, description): try: verify = Verify(config.cookie_sessdata, config.cookie_jct) try: video_file = video.video_upload(video_path, verify=verify) print("[Upload] Uploaded video file successfully.") except Exception as e: print( "[Upload] Failed to upload video file. Make sure the video file exists" ) return try: thumbnail_file = video.video_cover_upload(thumbnail_path, verify=verify) print("[Upload] Uploaded thubmnail successfully.") except Exception as e: print( "[Upload] Failed to upload thubmnail. Make sure the thumbnail file exists" ) return data = { "copyright": 2, "source": source_link, "cover": thumbnail_file, "desc": "本视频由python搬运上传,有能力还请支持原作者.\n" + description, "desc_format_id": 0, "dynamic": "", "interactive": 0, "no_reprint": 1, "subtitles": { "lan": "语言", "open": 0 }, "tag": "标签改这里,多个标签使用英文半角逗号隔开", "tid": 17, "title": title, "videos": [{ "desc": "", "filename": video_file, "title": "1" }] } print("[Upload] Submitting") result = video.video_submit(data, verify) print(result) except Exception as e: print(e.args)
def getTodayDanmaku(seasonId=34430, timeLimit=0): verify = Verify(sessdata="c9f59cdb%2C1609146929%2C7963a*71", csrf="b6ce9e789575330a9308fad04b56377a") bg = bangumi.get_collective_info(seasonId) res = [] for i in range(0, len(bg["episodes"])): bgAid = bvid2aid(bg["episodes"][i]["bvid"]) Danmaku = bilibili_api.video.get_danmaku(aid=bgAid, verify=verify, timeLimit=timeLimit) res += Danmaku # 添加弹幕 print("已爬弹幕数: " + str(len(res))) time.sleep(1) return res
def post_comment(bv_number: str, sc_comments: [str], he_comments: [str], config: {str: str}) -> bool: try: verify = Verify(sessdata=config["sessdata"], csrf=config["bili_jct"]) _ = get_video_info(bvid=bv_number, verify=verify) try: post_comments_on_vid(bv_number, sc_comments, verify) post_comments_on_vid(bv_number, he_comments, verify) except bilibili_api.exceptions.BilibiliApiException: print("comment posting error", file=sys.stderr) print(traceback.format_exc(), file=sys.stderr) finally: return True except bilibili_api.exceptions.BilibiliApiException: return False
def check_login_info(key: str) -> Status: data = {"oauthKey": key} raw = requests.post("http://passport.bilibili.com/qrcode/getLoginInfo", data=data) if raw.status_code == 200: root = raw.json() if root["status"]: verify = Verify(sessdata=raw.cookies["SESSDATA"], csrf=raw.cookies["bili_jct"]) settings.verify = verify return Status.SUCCESS else: code = root["data"] return Status.get(code) return Status.UNKNOWN_ERROR
def post_subtitle(self) -> bool: if (datetime.datetime.now(datetime.timezone.utc) - self.start_date).total_seconds() / 60 / 60 > HOURS_THRESHOLD: return True if self.error_count > ERROR_THRESHOLD: return True try: video.get_video_info(self.bvid) except bilibili_api.exceptions.BilibiliApiException: # Video not published yet return False self.error_count += 1 verify = Verify(self.sessdata, self.csrf) with open(self.subtitle_path) as srt_file: srt_obj = srt.parse(srt_file.read()) srt_json = { "font_size": 0.4, "font_color": "#FFFFFF", "background_alpha": 0.5, "background_color": "#9C27B0", "Stroke": "none", "body": [] } for srt_single_obj in srt_obj: srt_single_obj: srt.Subtitle srt_single_obj_body = { "from": srt_single_obj.start.total_seconds(), "to": srt_single_obj.end.total_seconds(), "location": 2, "content": srt_single_obj.content } srt_json["body"] += [srt_single_obj_body] srt_json_str = json.dumps(srt_json) print(f"posting subtitles on {self.cid} of {self.bvid}") try: video.save_subtitle(srt_json_str, bvid=self.bvid, cid=self.cid, verify=verify) except bilibili_api.exceptions.BilibiliApiException as e: # noinspection PyUnresolvedReferences if hasattr(e, 'code') and (e.code == 79022 or e.code == -404 or e.code == 502): # video not approved yet self.error_count -= 1 return False else: print(traceback.format_exc()) return False return True
def upload(uname, roomID, uploadName, filePath, cookies): global now now = 0 logger.info('%s[RoomID:%s]开始本次上传,投稿名称: %s, 本地位置: %s' % (uname, roomID, uploadName, filePath)) verify = Verify(sessdata=cookies['SESSDATA'], csrf=cookies['bili_jct']) try: filename = video.video_upload(filePath, verify, on_progress) except Exception as e: logger.error('%s[RoomID:%s]上传失败 %s' % (uname, roomID, e)) return logger.info('%s[RoomID:%s]上传成功' % (uname, roomID)) data = { "copyright": 2, "source": "https://live.bilibili.com/%s" % roomID, "cover": "", "desc": "", "desc_format_id": 0, "dynamic": "", "interactive": 0, "no_reprint": 0, "subtitles": { "lan": "", "open": 0 }, "tag": "录播,%s" % uname, "tid": 174, "title": uploadName, "videos": [ { "desc": "", "filename": filename, "title": "P1" } ] } try: result = video.video_submit(data, verify) logger.info('上传结果: %s' % (result)) except: logger.error('%s[RoomID:%s]投稿失败' % (uname, roomID)) return None
def upload_to_bilibili(videoFile, imageFile, topic): sessdata = os.getenv('SESSDATA', '') bili_jct = os.getenv('BILI_JCT', '') if not sessdata or not bili_jct: logger.error('both sessdata and bili_jct required, please check!') sys.exit(1) verify = Verify(sessdata, bili_jct) # 上传视频 filename = video.video_upload(videoFile, verify=verify) logger.info('视频上传B站') # 上传封面 cover_url = video.video_cover_upload(imageFile, verify=verify) logger.info('封面上传B站') # 提交投稿 data = { "copyright": 1, "cover": cover_url, "desc": "openEuler meetup", "desc_format_id": 0, "dynamic": "", "no_reprint": 1, "subtitles": { "lan": "", "open": 0 }, "tag": "openEuler, openeuler, meetup", "tid": 124, "title": topic, "videos": [ { "desc": "openEuler meetup Record", "filename": os.path.basename(filename), "title": "P1" } ] } result = video.video_submit(data, verify=verify) logger.info('视频提交成功') return result['bvid']
def verify(self, sessdata, csrf): return Verify(sessdata=sessdata, csrf=csrf)
log_file_handler = logging.FileHandler(log_file, mode='a', encoding='utf-8') log_file_handler.setFormatter(utils.TrimColorFormatter(config.get('LOG', 'FORMAT'))) log.addHandler(log_file_handler) except Exception as exception: print(colored(text="程序初始化错误:" + str(exception), color='red', on_color='on_green', attrs=('bold', ))) os.system("PAUSE") sys.exit(1) """ ************************************************************************** ********** 初始化:读取配置文件,初始化全局变量,做连接到直播间前的准备 ********* ************************************************************************** """ # 初始化全局变量 room_id = config.getint('LIVE', 'ROOM_ID') verify = Verify(sessdata=config.get('USER', 'SESSDATA'), csrf=config.get('USER', 'BILIBILI_JCT')) room = live.LiveDanmaku(room_display_id=room_id, verify=verify) ds = danmaku_sender.DanmakuSender(room_id=room_id, verify=verify, enable=config.getboolean('DANMAKU', 'ENABLE')) scheduler = BackgroundScheduler() turing = TuringAI(api_url=config.get('TURING_AI', 'API_URL'), api_keys=config.get('TURING_AI', 'API_KEYS').split(','), request_body=config.get('TURING_AI', 'REQUEST_FORMAT'), enable=config.getboolean('TURING_AI', 'ENABLE')) # 查询API获取初始化需要的数据 # TODO: 已登录用户xxx room_info = live.get_room_info(room_id, verify) isStreaming = room_info['room_info']['live_status'] == 1 up_name = room_info['anchor_info']['base_info']['uname'] fan_medal = room_info['anchor_info']['medal_info']['medal_name'] log.info("连接到 [" + up_name + "] 的直播间 [" + str(room_id) + "] ,当前直播状态:" + colored("直播中" if isStreaming else "未开播", attrs=['bold', ])) dahanghai_dict = utils.get_dahanghai_dict(room_id)
root=self.he_root_id, verify=verify) self.he_progress = i + 1 if self.sc_root_id == "": resp = send_comment(sc_list[0], bvid=bvid, verify=verify) self.sc_root_id = resp['rpid'] self.sc_progress = 1 for i, content in enumerate(sc_list): if i >= self.sc_progress: send_comment(content, bvid=bvid, root=self.sc_root_id, verify=verify) self.sc_progress = i + 1 except bilibili_api.exceptions.BilibiliApiException: print("Comment posting failed") print(print(traceback.format_exc())) return False return True if __name__ == '__main__': import yaml ct_1 = CommentTask("sc_path", "he_path", "session_id", Verify("sessdata", "csrf")) ct_yaml = yaml.dump(ct_1.to_dict()) ct_2 = CommentTask.from_dict(yaml.load(ct_yaml)) print(ct_1) print(ct_2)
import json from bilibili_api import video, Verify from bilibili_api.video import VideoInfo from bilibili_api.video import Danmaku from wordcloud import WordCloud import jieba import matplotlib.pyplot as plt import numpy as np from PIL import Image import random # 格式化显示评论信息 pp = pprint.PrettyPrinter() # 1、创建视频信息对象 verify = Verify(sessdata="632da748%2C1602337725%2Cc4863*41", csrf="bili_jct") video_info = VideoInfo(bvid="BV1gC4y1h722", verify=verify) # 2、获取视频信息、评论、弹幕 basic_info = video_info.get_video_info() comments = video_info.get_comments() danmu = video_info.get_danmaku() # 3、词云可视化 # 3\1 jieba分词 danmu_list = [] for i in danmu: # print(i.text) danmu_list.append(i.text)
'FFMPEG': 'ffmpeg', } def check_ffmpeg(): try: check_output(['ffmpeg', '-version']) except Exception: logger.debug('ffmpeg不存在') return False return True if (config['BILIBILI']['SESSDATA'] == "") | (config['BILIBILI']['CSRF'] == ""): logger.info('登录账号') verify = Verify() else: verify = Verify(sessdata=config['BILIBILI']['SESSDATA'], csrf=config['BILIBILI']['CSRF']) if not check_ffmpeg(): config['FFMPEG'] = './bin/ffmpeg' def get_session(): sessions = session() sessions.headers.update({ 'Referer': 'https://www.bilibili.com', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_0_0) AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/86.0.4240.198 Safari/537.36', 'Origin': 'https://www.bilibili.com', }) logger.info('获取session') return sessions
from bilibili_api.dynamic import DrawDynamic, TextDynamic, InstantDynamic, UploadImages, ScheduleDynamic from bilibili_api import Verify # 验证类 verify = Verify(sessdata="", csrf="") # 上传图片路径列表 img_path = [ "pic1", "pic2" ] # 上传图片类 upload = UploadImages(images_path=img_path, verify=verify) # 画册动态类 draw = DrawDynamic(text="这是文字内容", upload_images=upload, verify=verify) # 纯文本动态 text = TextDynamic(text="这是文字内容", verify=verify) # 立即发送动态类 instant = InstantDynamic(draw) # 定时发送动态类(timestamp是时间戳) sche = ScheduleDynamic(dynamic=text, timestamp=1111111) # 发送动态,图片会自动上传 instant.send() sche.send()
def upload_video(image_path, video_path, date_string, uploader_name, title, config, update_mode, task_id): verify = Verify(sessdata=config["sessdata"], csrf=config["bili_jct"]) video_date = dateutil.parser.isoparse(date_string) history_names = [ video_name for task_id, (bvid, video_name) in upload_task_dict.items() ] video_name = f"【{uploader_name}】{video_date.strftime('%Y年%m月%d日')} {title} 无弹幕先行版" i = 1 while video_name in history_names: i += 1 video_name = f"【{uploader_name}】{video_date.strftime('%Y年%m月%d日')} {title}{i} 无弹幕先行版" cover_url = video_cover_upload(image_path, verify=verify) def on_progress(update): print(update, file=sys.stderr) filename = video_upload(video_path, verify=verify, on_progress=on_progress) if not update_mode: data = { "copyright": 2, "source": config["source"], "cover": cover_url, "desc": config["description"] + f"\nhttps://tsxk.jya.ng/{video_path}", "desc_format_id": 0, "dynamic": "", "interactive": 0, "no_reprint": 0, "subtitles": { "lan": "", "open": 0 }, "tag": config["tags"], "tid": config["channel_id"], "title": video_name, "videos": [{ "desc": "", "filename": filename, "title": video_name }] } result = video_submit(data, verify) print(f"{video_name} uploaded: {result}", file=sys.stderr) upload_task_dict[task_id] = (result['bvid'], video_name) update_upload_task_dict() return result else: v = get_video_info(bvid=upload_task_dict[task_id], is_simple=False, is_member=True, verify=verify) print(f"updating... original_video: {v}", file=sys.stderr) data = { "copyright": v["archive"]['copyright'], "source": v["archive"]["source"], "cover": v["archive"]["cover"], "desc": v["archive"]["desc"], "desc_format_id": v["archive"]["desc_format_id"], "dynamic": v["archive"]["dynamic"], # "interactive": v["archive"]["interactive"], # "no_reprint": v["archive"]["no_reprint"], # "subtitle": v["subtitle"], "tag": v["archive"]["tag"], "tid": v["archive"]["tid"], "title": v["archive"]["title"].replace("无弹幕先行版", "弹幕高能版"), "videos": [{ "desc": video['desc'], "filename": filename if idx == 0 else video['filename'], "title": video['title'] } for idx, video in enumerate(v["videos"])], "handle_staff": False, 'bvid': v["archive"]["bvid"] } result = video_update(data, verify) print(f"{data['title']} updated: {result}", file=sys.stderr) return result
from bilibili_api import video, Verify import json # 设置验证 verify = Verify(sessdata="your sessdata", csrf="your csrf") # 初始化VideoInfo类 my_video = video.VideoInfo(aid="40473736", verify=verify) # 获取视频信息 info = my_video.get_video_info() # 转换成可格式化JSON并打印 print(json.dumps(info, indent=4, ensure_ascii=False))
srt_single_obj_body = { "from": srt_single_obj.start.total_seconds(), "to": srt_single_obj.end.total_seconds(), "location": 2, "content": srt_single_obj.content } srt_json["body"] += [srt_single_obj_body] srt_json_str = json.dumps(srt_json) print(f"posting subtitles on {self.cid} of {self.bvid}") try: video.save_subtitle(srt_json_str, bvid=self.bvid, cid=self.cid, verify=verify) except bilibili_api.exceptions.BilibiliApiException as e: # noinspection PyUnresolvedReferences if hasattr(e, 'code') and (e.code == 79022 or e.code == -404 or e.code == 502): # video not approved yet self.error_count -= 1 return False else: print(traceback.format_exc()) return False return True if __name__ == '__main__': import yaml ct_1 = SubtitleTask("subtitle_path", "BV", 12345678, Verify("sessdata", "csrf")) ct_yaml = yaml.dump(ct_1.to_dict()) ct_2 = SubtitleTask.from_dict(yaml.load(ct_yaml)) print(ct_1) print(ct_2)
from bilibili_api import video, Verify import datetime # 参数 verify = Verify("你的SESSDATA值", "你的bili_jct值") # 获取存在历史弹幕的日期列表 days = video.get_history_danmaku_index(bvid="BV1HJ411L7DP", verify=verify) print(days) # 获取弹幕信息,并保存 for day in days: danmus = video.get_danmaku(bvid="BV1HJ411L7DP", verify=verify, date=datetime.date(*map(int, day.split('-')))) print(danmus) f = open(r'danmu.txt', 'a') for danmu in danmus: print(danmu) f.write(danmu.text + '\n') f.close()
) ]), MessageChain.create([ Xml( VIDEO_ARTICAL_XML.format( url= f'https://www.bilibili.com/video/{dynamicInfo[2]}', cover=dynamicInfo[0], title=dynamicInfo[1], type='视频')) ]) ])) time.sleep(20) BILI_VERIFY = Verify(Values.BILI_SESSDATA.value, Values.BILI_CSRF.value) CACHE_PATH = './cache' BILI_ASSET_PATH = f'{CACHE_PATH}/BiliDynamic' TEXT_IMAGE_PATTERN = [ regex.compile(pattern) for pattern in [ '#碧蓝航线# #舰船新增# (.|\n)+', '#碧蓝航线# \n(.|\n)+换装(【|「)(.|\n)+(」|】)参上(.|\n)*', '#碧蓝航线# \n(.|\n)+(【|「)(.|\n)+(」|】)改造即将开启!(.|\n)*', '(.|\n)+<该誓约立绘将于下次维护后实装>(.|\n)*', '#碧蓝航线# \n◆Live2D预览◆(.|\n)*', '(.|\n)*(各位亲爱的指挥官|◆强制更新维护注意◆)(.|\n)+' ] ] VERIFY_PATTERN = regex.compile('^((?!自碧蓝航线上线以来)(.|\n))*$') VIDEO_ARTICAL_XML = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><msg serviceID="1" templateID="-1" action="web" brief="" sourceMsgId="0" url="{url}" flag="0" adverSign="0" multiMsgFlag="0"><item layout="2" advertiser_id="0" aid="0"><picture cover="{cover}" w="0" h="0" /><title>{title}</title><summary>{type}</summary></item><source name="" icon="" action="" appid="0"/></msg>' if not os.path.exists(CACHE_PATH): os.mkdir(CACHE_PATH) if not os.path.exists(BILI_ASSET_PATH):