import hashlib import math import time import zlib import requests import re import json class Wb: def __init__(self, cookie): self.chunk_size = 1024 * 1024 * 8 self.xsrf_token = None if "XSRF-TOKEN" in cookie: del cookie["XSRF-TOKEN"] if "xsrf-token" in cookie: del cookie["xsrf-token"] self.cookie = cookie self.headers = self.get_headers() self.screen_name, self.idstr, self.xsrf_token = self.get_tk_info() self.headers['x-xsrf-token'] = self.xsrf_token self.cookie["XSRF-TOKEN"] = self.xsrf_token # self.headers[''] def md5(self, data): if type(data) == str: data = data.encode("utf-8") return hashlib.md5(data).hexdigest() def get_cs(self, data): return zlib.crc32(data) & 0xffffffff def get_session_id(self, video_data, vide_path): data = f'{str(int(time.time() * 1000))}|{len(video_data)}|{vide_path}|video|{str(int(time.time()))}' return hashlib.md5(data.encode()).hexdigest() def get_headers(self): headers = { "cache-control": "no-cache", "pragma": "no-cache", "priority": "u=0, i", "sec-ch-ua": "\"Chromium\";v=\"9\", \"Not?A_Brand\";v=\"8\"", "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": "\"Windows\"", "sec-fetch-dest": "document", "sec-fetch-mode": "navigate", "sec-fetch-site": "same-origin", "sec-fetch-user": "?1", "upgrade-insecure-requests": "1", "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 SLBrowser/9.0.6.8151 SLBChan/10 SLBVPV/64-bit" } if self.xsrf_token: headers['x-xsrf-token'] = self.xsrf_token return headers def get_tk_info(self): url = "https://weibo.com/" response = requests.get(url, headers=self.headers, cookies=self.cookie) data = json.loads(re.search('window\.\$CONFIG = (.*?);}', response.text).group(1)) user = data['user'] screen_name = user['screen_name'] idstr = user['idstr'] xsrf_token = response.cookies.get('XSRF-TOKEN') print(screen_name, idstr, xsrf_token) return screen_name, idstr, xsrf_token def put_image(self, image_data): url = 'https://picupload.weibo.com/interface/upload.php?' params = { "file_source": "1", "cs": self.get_cs(image_data), "ent": "miniblog", "appid": "339644097", "uid": self.idstr, "raw_md5": self.md5(image_data), "ori": "1", "mpos": "1", "nick": self.screen_name, "pri": "0", "request_id": str(int(time.time() * 1000)), "file_size": len(image_data) } res = requests.post(url=url, data=image_data, headers=self.headers, cookies=self.cookie, params=params).json() print(res) return res def get_media_group_id(self): url = "https://weibo.com/ajax/multimedia/mediaGroupInit" headers = self.get_headers() headers.update( { "referer": "https://weibo.com/", "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin", "server-version": "v2026.03.04.2", } ) response = requests.get(url, headers=headers, cookies=self.cookie).json() print(response) return response['data']['media_group_id'] def ini_video_id(self, media_group_id, video_name, video_data): url = "https://fileplatform-cn1.api.weibo.com/2/fileplatform/init.json" params = { "source": "339644097", "size": len(video_data), "name": video_name, "type": "video", "client": "web", "session_id": self.get_session_id(video_data, video_name) } boundary = f"2067456weiboPro{str(int(time.time()))}" headers = self.get_headers() headers.update({ "Content-Type": f"multipart/mixed; boundary={boundary}", }) # 完全按 curl 构造原始 multipart body body = ( f"--{boundary}\r\n" 'Content-Disposition: form-data; name="biz_file"\r\n\r\n' '{"mediaprops":"{\\"screenshot\\":1,\\"media_group_id\\":\\"' + media_group_id + '\\"}"}\r\n' f"--{boundary}--\r\n" ) response = requests.post( url, params=params, headers=headers, cookies=cookies, data=body.encode("utf-8") ) print(response.json()) return response.json() def upload_video(self, upload_id, media_id, video_data, index, chunk_count, start_loc): url = "https://up-cn1.video.weibocdn.com/2/fileplatform/upload.json?" params = { "source": "339644097", "upload_id": upload_id, "media_id": media_id, "upload_protocol": "binary", "type": "video", "client": "web", "check": self.md5(video_data), "index": index, "size": len(video_data), "start_loc": start_loc, "count": chunk_count } # print(params) res = requests.post(url=url, params=params, headers=self.headers, cookies=cookies, data=video_data ).json() print(res) return res def chak_video(self, upload_id, media_id, size, count): url = "https://fileplatform-cn1.api.weibo.com/2/fileplatform/check.json" data = { "source": "339644097", "upload_id": upload_id, "media_id": media_id, "upload_protocol": "binary", "count": count, "action": "finish", "size": size, "client": "web", "status": "" } response = requests.post(url, headers=self.headers, cookies=cookies, data=data).json() print(response) return response def get_video_pid(self, media_id): url = "https://weibo.com/ajax/multimedia/output" params = { "source": "339644097", "ids": media_id, "labels": "screenshot" } headers = self.get_headers() headers.update({ "referer": "https://weibo.com/", }) for i in range(10): response = requests.get(url, headers=headers, cookies=cookies, params=params).json() print(response) if response['data'] == {}: time.sleep(5) continue else: return json.loads(response['data'][str(media_id)]['screenshot']['file_detail'])['files'][0]['file_id'] return False def release(self, pic_id, content): url = "https://weibo.com/ajax/statuses/update" data = { "content": content, "visible": "0", "share_id": "", "vote": "", "media": "", "need_transcode": "1", "pic_id": json.dumps(pic_id, ensure_ascii=False) } headers = self.get_headers() headers.update({ "origin": "https://weibo.com", "pragma": "no-cache", "priority": "u=1, i", "referer": "https://weibo.com/", "sec-ch-ua": "\"Chromium\";v=\"9\", \"Not?A_Brand\";v=\"8\"", "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": "\"Windows\"", "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin", "server-version": "v2026.03.04.2", } ) response = requests.post(url, headers=headers, cookies=self.cookie, data=data).text print(response) return response def run_video(self, video_name): media_group_id = self.get_media_group_id() with open(video_name, "rb") as f: video_data = f.read() video_info = self.ini_video_id(media_group_id=media_group_id, video_name=video_name, video_data=video_data) upload_id = video_info["upload_id"] media_id = video_info["media_id"] chunk_count = math.ceil(len(video_data) / self.chunk_size) for index in range(chunk_count): # start = index * self.chunk_size # end = min((index + 1) * self.chunk_size, len(video_data)) # f.seek(start) # chunk_data = f.read(end - start) # print(start, end) # self.upload_video(upload_id=upload_id, media_id=media_id, video_data=chunk_data, index=index, # chunk_count=chunk_count, start_loc=start) start = index * self.chunk_size end = min(start + self.chunk_size, len(video_data)) f.seek(start) chunk_data = f.read(end - start) self.upload_video( upload_id=upload_id, media_id=media_id, video_data=chunk_data, index=index, chunk_count=chunk_count, start_loc=start ) self.chak_video(upload_id=upload_id, media_id=media_id, size=len(video_data), count=chunk_count) res = { "type": "video", "media_id": media_id, "media_group_id": media_group_id } pid = self.get_video_pid(media_id) if pid: res['pid'] = pid return res def run_images(self, image_path): with open(image_path, 'rb') as f: pid = self.put_image(image_data=f.read())['pic']['pid'] return { "type": "image/png", "pid": pid } def run(self): pid_list = [] pid_list.append(self.run_images(r'D:\2026-3\image\2.png')) pid_list.append(self.run_video(r'1.mp4')) print(pid_list) self.release(pic_id=pid_list, content='你们好我是2222') if __name__ == '__main__': cookies = { "SCF": "AnPzE03xm8BB9HlgIFL6amrpHcKurEbxl_Lidx2mwHySmzyyoCMjVNxfKQCNBwYxr-gvT8-50DlpsHI_XJIJlqA.", "SUB": "_2A25EosHEDeRhGeFG7lYX9SnKzT2IHXVn3lsMrDV8PUNbmtAbLRnGkW1NeV0u11k3Ss6dRbldGFr1JUHhVsbep0_3", "SUBP": "0033WrSXqPxfM725Ws9jqgMF55529P9D9W5mUlS3fLogK2SEkeFqLNEa5NHD95QN1h-XSo-NSoqpWs4DqcjMi--NiK.Xi-2Ri--ciKnRi-zNS0nfShqfS0qceBtt", "ALF": "02_1775124116", "SINAGLOBAL": "8767812016817.392.1772592155581", "ULV": "1772610236625:2:2:2:6590739668820.657.1772610236578:1772592155651", "XSRF-TOKEN": "DQZxABOM_NfYDlXz1lTy1cOD", "WBPSESS": "uH_pEmgfiICupYDn2MNJGBnQEfhqzo2bMY0VUuWK05-TR78aeKUmP0AyDqfzYmdbsI2dVYBedhIHV1snwDUpD1Lz1KXhMSCgjztzOlrwCTDLIhXWNZMTlGNIkU-lI5cmUf2721Pj2oQsCiRB-HQg1w==" } # Wb(cookies).get_video_pid('5272880565649510') # print(Wb(cookies).run_video(video_name='1.mp4')) # print(Wb(cookies).run_images(r'D:\2026-3\image\2.png')) print(Wb(cookies).run()) # Wb(cookies).release([{'type': 'image/png', 'pid': '008zzlgNgy1iavb8voqu5j30cu03iaa7'}, # {'type': 'video', 'media_id': '5272882008227937', # 'media_group_id': '0c22cd44-17db-11f1-b886-09e635c8dab8'}], # '你们好')