diff --git a/README.MD b/README.MD index 44117e8..b080869 100644 --- a/README.MD +++ b/README.MD @@ -6,7 +6,7 @@ social-auto-upload 该项目旨在自动化发布视频到各个社交媒体平 - 中国主流社交媒体平台: - 抖音 - 视频号 - - bilibili(todo) + - bilibili - 小红书 - 快手(todo) @@ -148,6 +148,17 @@ https://github.com/requireCool/stealth.min.js --- +### 5. bilibili +该实现,借助biliup的[biliup](https://github.com/biliup/biliup),再次感谢。 +1. 准备视频目录结构 +2. cookie获取:`biliup.exe -u account.json login` 选项你喜欢的登录方式 +![登录方式](media/get_bili_cookie.png) +3. 上传视频:upload_video_to_bilibili.py + + + + + ### 其余部分(todo) 整理后上传 diff --git a/bilibili_uploader/__init__.py b/bilibili_uploader/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bilibili_uploader/biliup.exe b/bilibili_uploader/biliup.exe new file mode 100644 index 0000000..ad18c58 Binary files /dev/null and b/bilibili_uploader/biliup.exe differ diff --git a/bilibili_uploader/main.py b/bilibili_uploader/main.py new file mode 100644 index 0000000..e4c27ac --- /dev/null +++ b/bilibili_uploader/main.py @@ -0,0 +1,77 @@ +import json +import pathlib +import random +from biliup.plugins.bili_webup import BiliBili, Data + + +def extract_keys_from_json(data): + """Extract specified keys from the provided JSON data.""" + keys_to_extract = ["SESSDATA", "bili_jct", "DedeUserID__ckMd5", "DedeUserID", "access_token"] + extracted_data = {} + + # Extracting cookie data + for cookie in data['cookie_info']['cookies']: + if cookie['name'] in keys_to_extract: + extracted_data[cookie['name']] = cookie['value'] + + # Extracting access_token + if "access_token" in data['token_info']: + extracted_data['access_token'] = data['token_info']['access_token'] + + return extracted_data + + +def read_cookie_json_file(filepath: pathlib.Path): + with open(filepath, 'r', encoding='utf-8') as file: + content = json.load(file) + return content + + +def random_emoji(): + emoji_list = ["🍏", "🍎", "🍊", "🍋", "🍌", "🍉", "🍇", "🍓", "🍈", "🍒", "🍑", "🍍", "🥭", "🥥", "🥝", + "🍅", "🍆", "🥑", "🥦", "🥒", "🥬", "🌶", "🌽", "🥕", "🥔", "🍠", "🥐", "🍞", "🥖", "🥨", "🥯", "🧀", "🥚", "🍳", "🥞", + "🥓", "🥩", "🍗", "🍖", "🌭", "🍔", "🍟", "🍕", "🥪", "🥙", "🌮", "🌯", "🥗", "🥘", "🥫", "🍝", "🍜", "🍲", "🍛", "🍣", + "🍱", "🥟", "🍤", "🍙", "🍚", "🍘", "🍥", "🥮", "🥠", "🍢", "🍡", "🍧", "🍨", "🍦", "🥧", "🍰", "🎂", "🍮", "🍭", "🍬", + "🍫", "🍿", "🧂", "🍩", "🍪", "🌰", "🥜", "🍯", "🥛", "🍼", "☕️", "🍵", "🥤", "🍶", "🍻", "🥂", "🍷", "🥃", "🍸", "🍹", + "🍾", "🥄", "🍴", "🍽", "🥣", "🥡", "🥢"] + return random.choice(emoji_list) + + +class BilibiliUploader(object): + def __init__(self, cookie_data, file: pathlib.Path, title, desc, tid, tags, dtime): + self.upload_thread_num = 3 + self.copyright = 1 + self.lines = 'AUTO' + self.cookie_data = cookie_data + self.file = file + self.title = title + self.desc = desc + self.tid = tid + self.tags = tags + self.dtime = dtime + self._init_data() + + def _init_data(self): + self.data = Data() + self.data.copyright = self.copyright + self.data.title = self.title + self.data.desc = self.desc + self.data.tid = self.tid + self.data.set_tag(self.tags) + self.data.dtime = self.dtime + + def upload(self): + with BiliBili(self.data) as bili: + bili.login_by_cookies(self.cookie_data) + bili.access_token = self.cookie_data.get('access_token') + video_part = bili.upload_file(str(self.file), lines=self.lines, + tasks=self.upload_thread_num) # 上传视频,默认线路AUTO自动选择,线程数量3。 + video_part['title'] = self.title + self.data.append(video_part) + ret = bili.submit() # 提交视频 + if ret.get('code') == 0: + print(f'[+] {self.file.name}上传 成功') + return True + else: + print(f'[-] {self.file.name}上传 失败, error messge: {ret.get("message")}') + return False diff --git a/examples/get_bilibili_cookie.py b/examples/get_bilibili_cookie.py new file mode 100644 index 0000000..8acfc37 --- /dev/null +++ b/examples/get_bilibili_cookie.py @@ -0,0 +1,2 @@ +# cd bilibili_uploader +# biliup.exe -u account.json login diff --git a/examples/upload_video_to_bilibili.py b/examples/upload_video_to_bilibili.py new file mode 100644 index 0000000..bfcc7a4 --- /dev/null +++ b/examples/upload_video_to_bilibili.py @@ -0,0 +1,42 @@ +import time +from pathlib import Path + +from bilibili_uploader.main import read_cookie_json_file, extract_keys_from_json, random_emoji, BilibiliUploader +from conf import BASE_DIR +from utils.constant import VideoZoneTypes +from utils.files_times import generate_schedule_time_next_day, get_title_and_hashtags + +if __name__ == '__main__': + filepath = Path(BASE_DIR) / "videos" + # how to get cookie, see the file of get_bilibili_cookie.py. + account_file = Path(BASE_DIR / "bilibili_uploader" / "account.json") + if not account_file.exists(): + print(f"{account_file.name} 配置文件不存在") + exit() + cookie_data = read_cookie_json_file(account_file) + cookie_data = extract_keys_from_json(cookie_data) + + tid = VideoZoneTypes.SPORTS_FOOTBALL.value # 设置分区id + # 获取视频目录 + folder_path = Path(filepath) + # 获取文件夹中的所有文件 + files = list(folder_path.glob("*.mp4")) + file_num = len(files) + timestamps = generate_schedule_time_next_day(file_num, 1, daily_times=[16], timestamps=True) + + for index, file in enumerate(files): + title, tags = get_title_and_hashtags(str(file)) + # just avoid error, bilibili don't allow same title of video. + title += random_emoji() + tags_str = ','.join([tag for tag in tags]) + # 打印视频文件名、标题和 hashtag + print(f"视频文件名:{file}") + print(f"标题:{title}") + print(f"Hashtag:{tags}") + # I set desc same as title, do what u like. + desc = title + bili_uploader = BilibiliUploader(cookie_data, file, title, desc, tid, tags, timestamps[index]) + bili_uploader.upload() + + # life is beautiful don't so rush. be kind be patience + time.sleep(30) diff --git a/media/get_bili_cookie.png b/media/get_bili_cookie.png new file mode 100644 index 0000000..872ce4a Binary files /dev/null and b/media/get_bili_cookie.png differ diff --git a/requirements.txt b/requirements.txt index 717f959..9828930 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,5 @@ requests playwright eventlet schedule -cf_clearance \ No newline at end of file +cf_clearance +biliup \ No newline at end of file diff --git a/utils/constant.py b/utils/constant.py index c8e9523..01b9096 100644 --- a/utils/constant.py +++ b/utils/constant.py @@ -26,3 +26,284 @@ class TencentZoneTypes(enum.Enum): ANIMALS = '动物' PARENTING = '育儿' TECHNOLOGY = '科技' + +class VideoZoneTypes(enum.Enum): + """ + 所有分区枚举 + + - MAINPAGE: 主页 + - ANIME: 番剧 + - ANIME_SERIAL: 连载中番剧 + - ANIME_FINISH: 已完结番剧 + - ANIME_INFORMATION: 资讯 + - ANIME_OFFICAL: 官方延伸 + - MOVIE: 电影 + - GUOCHUANG: 国创 + - GUOCHUANG_CHINESE: 国产动画 + - GUOCHUANG_ORIGINAL: 国产原创相关 + - GUOCHUANG_PUPPETRY: 布袋戏 + - GUOCHUANG_MOTIONCOMIC: 动态漫·广播剧 + - GUOCHUANG_INFORMATION: 资讯 + - TELEPLAY: 电视剧 + - DOCUMENTARY: 纪录片 + - DOUGA: 动画 + - DOUGA_MAD: MAD·AMV + - DOUGA_MMD: MMD·3D + - DOUGA_VOICE: 短片·手书·配音 + - DOUGA_GARAGE_KIT: 手办·模玩 + - DOUGA_TOKUSATSU: 特摄 + - DOUGA_ACGNTALKS: 动漫杂谈 + - DOUGA_OTHER: 综合 + - GAME: 游戏 + - GAME_STAND_ALONE: 单机游戏 + - GAME_ESPORTS: 电子竞技 + - GAME_MOBILE: 手机游戏 + - GAME_ONLINE: 网络游戏 + - GAME_BOARD: 桌游棋牌 + - GAME_GMV: GMV + - GAME_MUSIC: 音游 + - GAME_MUGEN: Mugen + - KICHIKU: 鬼畜 + - KICHIKU_GUIDE: 鬼畜调教 + - KICHIKU_MAD: 音MAD + - KICHIKU_MANUAL_VOCALOID: 人力VOCALOID + - KICHIKU_THEATRE: 鬼畜剧场 + - KICHIKU_COURSE: 教程演示 + - MUSIC: 音乐 + - MUSIC_ORIGINAL: 原创音乐 + - MUSIC_COVER: 翻唱 + - MUSIC_PERFORM: 演奏 + - MUSIC_VOCALOID: VOCALOID·UTAU + - MUSIC_LIVE: 音乐现场 + - MUSIC_MV: MV + - MUSIC_COMMENTARY: 乐评盘点 + - MUSIC_TUTORIAL: 音乐教学 + - MUSIC_OTHER: 音乐综合 + - DANCE: 舞蹈 + - DANCE_OTAKU: 宅舞 + - DANCE_HIPHOP: 街舞 + - DANCE_STAR: 明星舞蹈 + - DANCE_CHINA: 中国舞 + - DANCE_THREE_D: 舞蹈综合 + - DANCE_DEMO: 舞蹈教程 + - CINEPHILE: 影视 + - CINEPHILE_CINECISM: 影视杂谈 + - CINEPHILE_MONTAGE: 影视剪辑 + - CINEPHILE_SHORTFILM: 小剧场 + - CINEPHILE_TRAILER_INFO: 预告·资讯 + - ENT: 娱乐 + - ENT_VARIETY: 综艺 + - ENT_TALKER: 娱乐杂谈 + - ENT_FANS: 粉丝创作 + - ENT_CELEBRITY: 明星综合 + - KNOWLEDGE: 知识 + - KNOWLEDGE_SCIENCE: 科学科普 + - KNOWLEDGE_SOCIAL_SCIENCE: 社科·法律·心理 + - KNOWLEDGE_HUMANITY_HISTORY: 人文历史 + - KNOWLEDGE_BUSINESS: 财经商业 + - KNOWLEDGE_CAMPUS: 校园学习 + - KNOWLEDGE_CAREER: 职业职场 + - KNOWLEDGE_DESIGN: 设计·创意 + - KNOWLEDGE_SKILL: 野生技能协会 + - TECH: 科技 + - TECH_DIGITAL: 数码 + - TECH_APPLICATION: 软件应用 + - TECH_COMPUTER_TECH: 计算机技术 + - TECH_INDUSTRY: 科工机械 + - INFORMATION: 资讯 + - INFORMATION_HOTSPOT: 热点 + - INFORMATION_GLOBAL: 环球 + - INFORMATION_SOCIAL: 社会 + - INFORMATION_MULTIPLE: 综合 + - FOOD: 美食 + - FOOD_MAKE: 美食制作 + - FOOD_DETECTIVE: 美食侦探 + - FOOD_MEASUREMENT: 美食测评 + - FOOD_RURAL: 田园美食 + - FOOD_RECORD: 美食记录 + - LIFE: 生活 + - LIFE_FUNNY: 搞笑 + - LIFE_TRAVEL: 出行 + - LIFE_RURALLIFE: 三农 + - LIFE_HOME: 家居房产 + - LIFE_HANDMAKE: 手工 + - LIFE_PAINTING: 绘画 + - LIFE_DAILY: 日常 + - CAR: 汽车 + - CAR_RACING: 赛车 + - CAR_MODIFIEDVEHICLE: 改装玩车 + - CAR_NEWENERGYVEHICLE: 新能源车 + - CAR_TOURINGCAR: 房车 + - CAR_MOTORCYCLE: 摩托车 + - CAR_STRATEGY: 购车攻略 + - CAR_LIFE: 汽车生活 + - FASHION: 时尚 + - FASHION_MAKEUP: 美妆护肤 + - FASHION_COS: 仿妆cos + - FASHION_CLOTHING: 穿搭 + - FASHION_TREND: 时尚潮流 + - SPORTS: 运动 + - SPORTS_BASKETBALL: 篮球 + - SPORTS_FOOTBALL: 足球 + - SPORTS_AEROBICS: 健身 + - SPORTS_ATHLETIC: 竞技体育 + - SPORTS_CULTURE: 运动文化 + - SPORTS_COMPREHENSIVE: 运动综合 + - ANIMAL: 动物圈 + - ANIMAL_CAT: 喵星人 + - ANIMAL_DOG: 汪星人 + - ANIMAL_PANDA: 大熊猫 + - ANIMAL_WILD_ANIMAL: 野生动物 + - ANIMAL_REPTILES: 爬宠 + - ANIMAL_COMPOSITE: 动物综合 + - VLOG: VLOG + """ + + MAINPAGE = 0 + + ANIME = 13 + ANIME_SERIAL = 33 + ANIME_FINISH = 32 + ANIME_INFORMATION = 51 + ANIME_OFFICAL = 152 + + MOVIE = 23 + + GUOCHUANG = 167 + GUOCHUANG_CHINESE = 153 + GUOCHUANG_ORIGINAL = 168 + GUOCHUANG_PUPPETRY = 169 + GUOCHUANG_MOTIONCOMIC = 195 + GUOCHUANG_INFORMATION = 170 + + TELEPLAY = 11 + + DOCUMENTARY = 177 + + DOUGA = 1 + DOUGA_MAD = 24 + DOUGA_MMD = 25 + DOUGA_VOICE = 47 + DOUGA_GARAGE_KIT = 210 + DOUGA_TOKUSATSU = 86 + DOUGA_ACGNTALKS = 253 + DOUGA_OTHER = 27 + + GAME = 4 + GAME_STAND_ALONE = 17 + GAME_ESPORTS = 171 + GAME_MOBILE = 172 + GAME_ONLINE = 65 + GAME_BOARD = 173 + GAME_GMV = 121 + GAME_MUSIC = 136 + GAME_MUGEN = 19 + + KICHIKU = 119 + KICHIKU_GUIDE = 22 + KICHIKU_MAD = 26 + KICHIKU_MANUAL_VOCALOID = 126 + KICHIKU_THEATRE = 216 + KICHIKU_COURSE = 127 + + MUSIC = 3 + MUSIC_ORIGINAL = 28 + MUSIC_COVER = 31 + MUSIC_PERFORM = 59 + MUSIC_VOCALOID = 30 + MUSIC_LIVE = 29 + MUSIC_MV = 193 + MUSIC_COMMENTARY = 243 + MUSIC_TUTORIAL = 244 + MUSIC_OTHER = 130 + + DANCE = 129 + DANCE_OTAKU = 20 + DANCE_HIPHOP = 198 + DANCE_STAR = 199 + DANCE_CHINA = 200 + DANCE_THREE_D = 154 + DANCE_DEMO = 156 + + CINEPHILE = 181 + CINEPHILE_CINECISM = 182 + CINEPHILE_MONTAGE = 183 + CINEPHILE_SHORTFILM = 85 + CINEPHILE_TRAILER_INFO = 184 + + ENT = 5 + ENT_VARIETY = 71 + ENT_TALKER = 241 + ENT_FANS = 242 + ENT_CELEBRITY = 137 + + KNOWLEDGE = 36 + KNOWLEDGE_SCIENCE = 201 + KNOWLEDGE_SOCIAL_SCIENCE = 124 + KNOWLEDGE_HUMANITY_HISTORY = 228 + KNOWLEDGE_BUSINESS = 207 + KNOWLEDGE_CAMPUS = 208 + KNOWLEDGE_CAREER = 209 + KNOWLEDGE_DESIGN = 229 + KNOWLEDGE_SKILL = 122 + + TECH = 188 + TECH_DIGITAL = 95 + TECH_APPLICATION = 230 + TECH_COMPUTER_TECH = 231 + TECH_INDUSTRY = 232 + + INFORMATION = 202 + INFORMATION_HOTSPOT = 203 + INFORMATION_GLOBAL = 204 + INFORMATION_SOCIAL = 205 + INFORMATION_MULTIPLE = 206 + + FOOD = 211 + FOOD_MAKE = 76 + FOOD_DETECTIVE = 212 + FOOD_MEASUREMENT = 213 + FOOD_RURAL = 214 + FOOD_RECORD = 215 + + LIFE = 160 + LIFE_FUNNY = 138 + LIFE_TRAVEL = 250 + LIFE_RURALLIFE = 251 + LIFE_HOME = 239 + LIFE_HANDMAKE = 161 + LIFE_PAINTING = 162 + LIFE_DAILY = 21 + + CAR = 223 + CAR_RACING = 245 + CAR_MODIFIEDVEHICLE = 246 + CAR_NEWENERGYVEHICLE = 247 + CAR_TOURINGCAR = 248 + CAR_MOTORCYCLE = 240 + CAR_STRATEGY = 227 + CAR_LIFE = 176 + + FASHION = 155 + FASHION_MAKEUP = 157 + FASHION_COS = 252 + FASHION_CLOTHING = 158 + FASHION_TREND = 159 + + SPORTS = 234 + SPORTS_BASKETBALL = 235 + SPORTS_FOOTBALL = 249 + SPORTS_AEROBICS = 164 + SPORTS_ATHLETIC = 236 + SPORTS_CULTURE = 237 + SPORTS_COMPREHENSIVE = 238 + + ANIMAL = 217 + ANIMAL_CAT = 218 + ANIMAL_DOG = 219 + ANIMAL_PANDA = 220 + ANIMAL_WILD_ANIMAL = 221 + ANIMAL_REPTILES = 222 + ANIMAL_COMPOSITE = 75 + + VLOG = 19