🔄 卡若AI 同步 2026-03-11 09:56 | 更新:卡木、运营中枢工作台 | 排除 >20MB: 11 个

This commit is contained in:
2026-03-11 09:56:42 +08:00
parent 565fbb6caa
commit 2393f0ed5f
10 changed files with 382 additions and 461 deletions

View File

@@ -1,163 +1 @@
{
"cookies": [
{
"name": "sessionid",
"value": "BgAAlUekVXtrtxMKBuoTfHRptlfxmDAWjCoVppaDKWcrAiVDAycStUCN%2BkcYWkC786pzHlNnmrbJG1NkDrDjw1epdXydipxraFq1fqWAOIA%3D",
"domain": "channels.weixin.qq.com",
"path": "/",
"expires": 1807693838.404647,
"httpOnly": false,
"secure": true,
"sameSite": "None"
},
{
"name": "wxuin",
"value": "1925733981",
"domain": "channels.weixin.qq.com",
"path": "/",
"expires": 1807693838.404685,
"httpOnly": false,
"secure": true,
"sameSite": "None"
}
],
"origins": [
{
"origin": "https://channels.weixin.qq.com",
"localStorage": [
{
"name": "finder_route_meta",
"value": "micro.content/post/list;index;1;1773134435681"
},
{
"name": "__ml::page_e7b7ede3-dadd-44d8-bfee-f0467dc018c6",
"value": "{\"pageId\":\"MicroPost\",\"accessId\":\"6dd2b03b-87f5-48eb-b7cd-7b848f34b4ea\",\"step\":2,\"refAccessId\":\"716a0cd8-b79e-4d09-96a5-3608ca3b56a6\",\"refPageId\":\"MicroPost\"}"
},
{
"name": "__ml::hb_ts",
"value": "1773134395731"
},
{
"name": "__ml::page_e6ebcfbf-55f8-459f-8cbd-e25593f752aa",
"value": "{\"pageId\":\"PostList\",\"accessId\":\"5c9016f6-ca55-487d-bfff-e731be19c890\",\"step\":1}"
},
{
"name": "__ml::page_5f9512e8-0a4e-41bd-9f10-c846a52f811c",
"value": "{\"pageId\":\"PostList\",\"accessId\":\"3c75cadf-81f0-4d36-a869-53c55b7bf8bb\",\"step\":1}"
},
{
"name": "__ml::page_d43dfe7c-183b-4b7f-9b0d-fc0037082ad2",
"value": "{\"pageId\":\"PostCreate\",\"accessId\":\"2bda158d-425c-42be-8902-b54bd90fcebc\",\"step\":1}"
},
{
"name": "__ml::page",
"value": "[\"9fa40fc4-98eb-4d7b-8e22-1ec96a1e1712\",\"5dcbd7e6-1d0a-4fad-a073-cbe548ef78ab\",\"7b06f5f0-dbea-49f7-b8f2-584bbb5f5255\",\"e6ebcfbf-55f8-459f-8cbd-e25593f752aa\",\"99804864-a1fe-4ba0-8ae6-969f5c7ea8ec\",\"be6dc06b-00e1-4f0f-8225-da6660790adc\",\"4d9862c3-8891-459f-a432-0993148c4e48\",\"17b7c164-a20f-4a38-8811-4c4504de332f\",\"efde92e1-a447-48d3-8691-ed52d1ecf999\",\"d43dfe7c-183b-4b7f-9b0d-fc0037082ad2\",\"be10d348-b3e2-4fc6-8252-5ac529b60e61\",\"4feaceae-d5a5-44ed-9d0c-a61790d0ac88\",\"4493896b-8ace-49b1-8ec3-d33697af23a2\",\"770458db-9fff-4509-b630-d46ab45465eb\",\"66c89831-55ca-437b-a518-7a96a07c6fdc\",\"5f9512e8-0a4e-41bd-9f10-c846a52f811c\",\"e7b7ede3-dadd-44d8-bfee-f0467dc018c6\",\"bc60cd6e-0a51-4cd3-9d93-15d4a1414562\",\"83a755e9-c380-49fd-be06-2f29a20deb8d\",\"9cc52efb-076f-4482-a99e-954872e95a52\"]"
},
{
"name": "__ml::page_4493896b-8ace-49b1-8ec3-d33697af23a2",
"value": "{\"pageId\":\"MicroPost\",\"accessId\":\"c63ac4ee-58ba-495a-bc33-8b30d3d488c6\",\"step\":2,\"refAccessId\":\"c44c0221-f278-494e-95d4-2ccecf6eb900\",\"refPageId\":\"MicroPost\"}"
},
{
"name": "__ml::page_efde92e1-a447-48d3-8691-ed52d1ecf999",
"value": "{\"pageId\":\"MicroPost\",\"accessId\":\"ea094f50-eaf0-48be-8d17-03447ec3c21a\",\"step\":1}"
},
{
"name": "__ml::page_4d9862c3-8891-459f-a432-0993148c4e48",
"value": "{\"pageId\":\"MicroPost\",\"accessId\":\"5220a072-43fe-4917-9be1-3d9651c32cc8\",\"step\":1}"
},
{
"name": "AssistantUploadedInfoStorageKey_3899420810",
"value": "[{\"fileUploadedInfoKey\":\"金融AI获客体系 后端30人沉淀12年前端丢手机.mp4:1773049087899:13904487:video/mp4:cf94106b56208a5f60024854fd65c749\",\"isUsedQuickUpload\":false,\"uploadChunkRecord\":[{\"index\":0,\"reqTime\":1773134417475,\"resTime\":1773134419978,\"cost\":2503,\"success\":true},{\"index\":1,\"reqTime\":1773134417500,\"resTime\":1773134419632,\"cost\":2132,\"success\":true}],\"uuid\":\"5ead770c-fcb7-4069-bd32-cf8632fb00ce\",\"uploadTaskId\":\"CkRmMDM2NTU1NTQzMDVmYjBkZmM3YmM1MTQyMWFjMThjZTQzZWQ2MDc5N2MzNjQxOGE4MGY5MTRiNDgxNWJkMDAwMzMwYxI+NTY5YWZlMjUxMDAwNzI0OWNlODZjNzA4YTAwMDAwMGZiMDAwMDRmNGU1MzQ4MjFiMzUxZjE1NmEyM2NlY2Mw59TQBg==\",\"uploadTaskIdTimeStamp\":1773134417433,\"transFlag\":\"0_0\",\"partInfo\":[{\"PartNumber\":1,\"ETag\":\"\\\"7aa7d5d4489b865e3fabba21d6441651e5affa44\\\"\"},{\"PartNumber\":2,\"ETag\":\"\\\"0b210f5d82059972fd1356f41ebe3bbcc0fb4afd\\\"\"}],\"uploadSuccessResp\":{\"data\":{\"DownloadURL\":\"http://wxapp.tc.qq.com/251/20302/stodownload?bizid=1023&dotrans=0&encfilekey=Cvvj5Ix3eewK0tHtibORqcsqchXNh0Gf3sJcaYqC2rQDo10woW6qVWuvF2I1kB1OPp2P3icKiaZ5zdLS4iaIsaxPDSvhIfDBgB3TyQukaRq52SDcRBGorELARBE3gV4iaLdV4&findertoken=088ae1b1c30e10d4c4bfcd061800223c66696e64657275706c6f616475726c5f333839393432303831305f313737333133343432303230355f363731353536363339363131303136333839362a2030376231363265623862393934663434346134383130623433313133663761303801400348005000580260ce9e01&hy=SH&idx=1&m=&scene=2&token=x5Y29zUxcibCDPn6ryZn3m8ZIGECqs0ey1a4K09cBLCpm4WxcwIocbCw6j4NZh9wiaZZII3O5U87cVu45stAvtAnrES61UruMwEGib3TLk2yoKEvvia6u8nU6A&uzid=7a152\",\"httpsUrl\":\"https://finder.video.qq.com/251/20302/stodownload?bizid=1023&dotrans=0&encfilekey=Cvvj5Ix3eewK0tHtibORqcsqchXNh0Gf3sJcaYqC2rQDo10woW6qVWuvF2I1kB1OPp2P3icKiaZ5zdLS4iaIsaxPDSvhIfDBgB3TyQukaRq52SDcRBGorELARBE3gV4iaLdV4&findertoken=088ae1b1c30e10d4c4bfcd061800223c66696e64657275706c6f616475726c5f333839393432303831305f313737333133343432303230355f363731353536363339363131303136333839362a2030376231363265623862393934663434346134383130623433313133663761303801400348005000580260ce9e01&hy=SH&idx=1&m=&scene=2&token=x5Y29zUxcibCDPn6ryZn3m8ZIGECqs0ey1a4K09cBLCpm4WxcwIocbCw6j4NZh9wiaZZII3O5U87cVu45stAvtAnrES61UruMwEGib3TLk2yoKEvvia6u8nU6A&uzid=7a152\"}}}]"
},
{
"name": "__ml::page_5dcbd7e6-1d0a-4fad-a073-cbe548ef78ab",
"value": "{\"pageId\":\"PostList\",\"accessId\":\"35c98491-9b79-4ac5-aea8-7b009c6c73f3\",\"step\":2,\"refAccessId\":\"a66782b9-9954-46f9-b10a-a70547d5cb90\",\"refPageId\":\"PostCreate\"}"
},
{
"name": "__ml::page_7b06f5f0-dbea-49f7-b8f2-584bbb5f5255",
"value": "{\"pageId\":\"MicroPost\",\"accessId\":\"519b9718-cf53-4413-afb5-34b6170d56fe\",\"step\":1}"
},
{
"name": "finder_ua_report_data",
"value": "{\"browser\":\"Chrome\",\"browserVersion\":\"143.0.0.0\",\"engine\":\"Webkit\",\"engineVersion\":\"537.36\",\"os\":\"Mac OS X\",\"osVersion\":\"10.15.7\",\"device\":\"desktop\",\"darkmode\":0}"
},
{
"name": "__ml::page_be10d348-b3e2-4fc6-8252-5ac529b60e61",
"value": "{\"pageId\":\"MicroPost\",\"accessId\":\"550e4b8d-a7b6-4e07-9483-478f6092cc5d\",\"step\":1}"
},
{
"name": "__ml::page_9cc52efb-076f-4482-a99e-954872e95a52",
"value": "{\"pageId\":\"PostList\",\"accessId\":\"8088110d-acd4-4ff9-a9bb-20c320749269\",\"step\":1}"
},
{
"name": "__ml::page_99804864-a1fe-4ba0-8ae6-969f5c7ea8ec",
"value": "{\"pageId\":\"MicroPost\",\"accessId\":\"67682578-18a2-4d06-9243-838f5310df15\",\"step\":2,\"refAccessId\":\"173adf5d-8e34-4ba6-a8ba-4f4ede0d98c5\",\"refPageId\":\"MicroPost\"}"
},
{
"name": "__ml::page_bc60cd6e-0a51-4cd3-9d93-15d4a1414562",
"value": "{\"pageId\":\"PostList\",\"accessId\":\"8950bd30-9573-4ace-955f-aef4834f5d48\",\"step\":2,\"refAccessId\":\"0d5130ac-b06b-48bb-92ad-9ded3632fd27\",\"refPageId\":\"PostCreate\"}"
},
{
"name": "__ml::page_66c89831-55ca-437b-a518-7a96a07c6fdc",
"value": "{\"pageId\":\"MicroPost\",\"accessId\":\"51c9dcd4-561d-4151-b148-03b62c02a870\",\"step\":1}"
},
{
"name": "__ml::aid",
"value": "\"bd71a1bd-04de-40a0-9f51-bbb8a5742f95\""
},
{
"name": "__rx::aid",
"value": "\"bd71a1bd-04de-40a0-9f51-bbb8a5742f95\""
},
{
"name": "finder_login_token",
"value": ""
},
{
"name": "__ml::page_9fa40fc4-98eb-4d7b-8e22-1ec96a1e1712",
"value": "{\"pageId\":\"MicroPost\",\"accessId\":\"7507f92b-ea29-4278-b825-7a15bb166c07\",\"step\":2,\"refAccessId\":\"4dfed0e6-3b01-4104-bf31-31fe396e7c90\",\"refPageId\":\"MicroPost\"}"
},
{
"name": "__ml::page_be6dc06b-00e1-4f0f-8225-da6660790adc",
"value": "{\"pageId\":\"PostList\",\"accessId\":\"5951b6d4-0b5b-4e8a-97fe-fb6f2e279eda\",\"step\":2,\"refAccessId\":\"e8c08c35-6dab-4f95-b5c9-3630440cb41a\",\"refPageId\":\"PostCreate\"}"
},
{
"name": "__ml::page_17b7c164-a20f-4a38-8811-4c4504de332f",
"value": "{\"pageId\":\"PostList\",\"accessId\":\"c05f2163-1df4-46cb-ade2-e1c8e55e3510\",\"step\":1}"
},
{
"name": "finder_username",
"value": "v2_060000231003b20faec8c5e48919cbd5cb05e53db077dd1924028a806c10cffd891eb5a80ce7@finder"
},
{
"name": "_finger_print_device_id",
"value": "6fd704941768442b12a996d2652fc61e"
},
{
"name": "MICRO_VISITED_NAME",
"value": "{\"content\":15}"
},
{
"name": "__ml::page_4feaceae-d5a5-44ed-9d0c-a61790d0ac88",
"value": "{\"pageId\":\"PostList\",\"accessId\":\"483570fa-e6a0-4ffb-9346-9b5f2f8381f4\",\"step\":1}"
},
{
"name": "UvFirstReportLocalKey",
"value": "1773072000000"
},
{
"name": "__ml::page_83a755e9-c380-49fd-be06-2f29a20deb8d",
"value": "{\"pageId\":\"MicroPost\",\"accessId\":\"44db79de-9a51-457c-956a-06eeab7d8ebd\",\"step\":1}"
},
{
"name": "__ml::page_770458db-9fff-4509-b630-d46ab45465eb",
"value": "{\"pageId\":\"PostList\",\"accessId\":\"6e166aa7-4132-4d21-a03c-215fb557eab5\",\"step\":2,\"refAccessId\":\"2225f708-4e6b-4aef-a741-c2950fd397dc\",\"refPageId\":\"PostCreate\"}"
},
{
"name": "finder_uin",
"value": ""
}
]
}
]
}
{"cookies": [{"name": "sessionid", "value": "BgAAXn42dDVxziLfiAgbkcIfNWJuq3q4eqUcsucKM6%2B22j8kyqgfK6EmAYjVKRnfRVF5H4ImiqYsYmA%2FHCKErGMPGj9qUIkciQgbCJitvtI%3D", "domain": "channels.weixin.qq.com", "path": "/", "expires": 1807752687.942864, "httpOnly": false, "secure": true, "sameSite": "None"}, {"name": "wxuin", "value": "3584477580", "domain": "channels.weixin.qq.com", "path": "/", "expires": 1807752687.942958, "httpOnly": false, "secure": true, "sameSite": "None"}], "origins": [{"origin": "https://channels.weixin.qq.com", "localStorage": [{"name": "finder_route_meta", "value": "micro.content/post/list;index;1;1773192699321"}, {"name": "__ml::hb_ts", "value": "1773192690709"}, {"name": "__ml::page_1819fde5-8cd1-4fc4-a0a0-02ccc76e5581", "value": "{\"pageId\":\"LoginForIframe\",\"accessId\":\"c11107b0-1b67-4ed6-86d1-641dde624ca0\",\"step\":1}"}, {"name": "__ml::page_5e0063e9-0029-467d-a08a-289bc33adc36", "value": "{\"pageId\":\"LoginForIframe\",\"accessId\":\"c386e434-b5d1-41e5-a2fd-4f0816f0b734\",\"step\":1}"}, {"name": "__rx::aid", "value": "\"703dddc3-441f-43df-af5a-4b45cad6672e\""}, {"name": "__ml::aid", "value": "\"703dddc3-441f-43df-af5a-4b45cad6672e\""}, {"name": "__ml::page", "value": "[\"5e0063e9-0029-467d-a08a-289bc33adc36\",\"1819fde5-8cd1-4fc4-a0a0-02ccc76e5581\",\"1868b17e-5980-4657-afd9-d0dcd1d69a66\",\"b5b449ff-c981-41e2-acce-928cd78ac655\"]"}, {"name": "finder_login_token", "value": ""}, {"name": "__ml::page_b5b449ff-c981-41e2-acce-928cd78ac655", "value": "{\"pageId\":\"PostList\",\"accessId\":\"6f900704-4b40-4c5d-9112-5dcc0eba3220\",\"step\":1}"}, {"name": "finder_username", "value": "v2_060000231003b20faec8c5e48919cbd5cb05e53db077dd1924028a806c10cffd891eb5a80ce7@finder"}, {"name": "_finger_print_device_id", "value": "7560eede9c907e094cee8c2d642456c1"}, {"name": "MICRO_VISITED_NAME", "value": "{\"content\":1}"}, {"name": "__ml::page_1868b17e-5980-4657-afd9-d0dcd1d69a66", "value": "{\"pageId\":\"MicroPost\",\"accessId\":\"783ab67d-d2aa-4007-9fed-50aa8a8f3757\",\"step\":1}"}, {"name": "UvFirstReportLocalKey", "value": "1773158400000"}, {"name": "finder_ua_report_data", "value": "{\"browser\":\"Chrome\",\"browserVersion\":\"143.0.0.0\",\"engine\":\"Webkit\",\"engineVersion\":\"537.36\",\"os\":\"Mac OS X\",\"osVersion\":\"10.15.7\",\"device\":\"desktop\",\"darkmode\":0}"}, {"name": "finder_uin", "value": ""}]}]}

View File

@@ -80,3 +80,27 @@
{"platform": "B站", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/深度AI模型对比 哪个才是真正的AI不是语言模型.mp4", "title": "深度对比各大AI模型哪个才是真正的智能而不只是语言模型 #AI对比 #深度思考 #小程序 卡若创业派对", "success": true, "status": "reviewing", "message": "纯API投稿成功 (4.7s)", "elapsed_sec": 4.689250946044922, "timestamp": "2026-03-11 09:30:36"}
{"platform": "B站", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/疗愈师配AI助手能收多少钱 一个小团队5万到10万.mp4", "title": "疗愈师+AI助手组合一个小团队月收5万到10万 #AI赋能 #疗愈商业 #小程序 卡若创业派对", "success": true, "status": "reviewing", "message": "纯API投稿成功 (7.6s)", "elapsed_sec": 7.606438159942627, "timestamp": "2026-03-11 09:30:52"}
{"platform": "B站", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/赚钱没那么复杂,自信心才是核心问题.mp4", "title": "赚钱真没那么复杂,自信心才是卡住你的核心问题 #创业心态 #自信 #小程序 卡若创业派对", "success": true, "status": "reviewing", "message": "纯API投稿成功 (7.3s)", "elapsed_sec": 7.324275970458984, "timestamp": "2026-03-11 09:31:07"}
{"platform": "小红书", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/AI最大的缺点是上下文太短这样来解决.mp4", "title": "AI的短板是记忆太短上下文一长就废了这个方法能解决 #AI工具 #效率提升 #小程序 卡若创业派对", "success": true, "status": "published", "message": "页面已重置(发布成功)", "screenshot": "/tmp/xhs_result.png", "elapsed_sec": 28.81607222557068, "timestamp": "2026-03-11 09:28:53"}
{"platform": "小红书", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/AI每天剪1000个视频 M4电脑24T素材库全网分发.mp4", "title": "M4芯片+24T素材库AI每天剪1000条视频自动全网分发 #AI剪辑 #内容工厂 #小程序 卡若创业派对", "success": true, "status": "published", "message": "页面已重置(发布成功)", "screenshot": "/tmp/xhs_result.png", "elapsed_sec": 27.494543075561523, "timestamp": "2026-03-11 09:29:36"}
{"platform": "小红书", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/Soul派对变现全链路 发视频就有钱,后端全解决.mp4", "title": "Soul派对怎么赚钱发视频就有收益后端体系全部搞定 #Soul派对 #副业收入 #小程序 卡若创业派对", "success": true, "status": "published", "message": "页面已重置(发布成功)", "screenshot": "/tmp/xhs_result.png", "elapsed_sec": 27.850404024124146, "timestamp": "2026-03-11 09:30:19"}
{"platform": "小红书", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/从0到切片发布 AI自动完成每天副业30条视频.mp4", "title": "从零到切片发布AI全自动完成每天副业产出30条视频 #AI副业 #切片分发 #小程序 卡若创业派对", "success": true, "status": "published", "message": "页面已重置(发布成功)", "screenshot": "/tmp/xhs_result.png", "elapsed_sec": 27.42349100112915, "timestamp": "2026-03-11 09:31:01"}
{"platform": "小红书", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/做副业的基本条件 苹果电脑和特殊访问工具.mp4", "title": "做副业的两个基本条件一台Mac和一个上网工具 #副业入门 #工具推荐 #小程序 卡若创业派对", "success": true, "status": "published", "message": "页面已重置(发布成功)", "screenshot": "/tmp/xhs_result.png", "elapsed_sec": 27.265256881713867, "timestamp": "2026-03-11 09:31:44"}
{"platform": "小红书", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/切片分发全自动化 从视频到发布一键完成.mp4", "title": "从录制到发布全自动化,一键切片分发五大平台 #自动化 #内容分发 #小程序 卡若创业派对", "success": true, "status": "published", "message": "页面已重置(发布成功)", "screenshot": "/tmp/xhs_result.png", "elapsed_sec": 27.292948007583618, "timestamp": "2026-03-11 09:32:26"}
{"platform": "小红书", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/创业团队4人平分25有啥危险 先跑钱再谈股权.mp4", "title": "创业团队4人平分25%股权有啥风险?先跑出收入再谈分配 #创业股权 #团队管理 #小程序 卡若创业派对", "success": true, "status": "published", "message": "页面已重置(发布成功)", "screenshot": "/tmp/xhs_result.png", "elapsed_sec": 27.253703832626343, "timestamp": "2026-03-11 09:33:09"}
{"platform": "小红书", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/坚持到120场是什么感觉 方向越确定执行越坚决.mp4", "title": "坚持到第120场派对是什么感觉方向越清晰执行越坚决 #Soul派对 #坚持的力量 #小程序 卡若创业派对", "success": true, "status": "published", "message": "页面已重置(发布成功)", "screenshot": "/tmp/xhs_result.png", "elapsed_sec": 27.21050763130188, "timestamp": "2026-03-11 09:33:51"}
{"platform": "小红书", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/帮人装AI一单300到1000块传统行业也能做.mp4", "title": "帮传统行业的人装AI工具一单收300到1000块简单好做 #AI服务 #传统行业 #小程序 卡若创业派对", "success": true, "status": "published", "message": "页面已重置(发布成功)", "screenshot": "/tmp/xhs_result.png", "elapsed_sec": 27.359671115875244, "timestamp": "2026-03-11 09:34:33"}
{"platform": "小红书", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/深度AI模型对比 哪个才是真正的AI不是语言模型.mp4", "title": "深度对比各大AI模型哪个才是真正的智能而不只是语言模型 #AI对比 #深度思考 #小程序 卡若创业派对", "success": true, "status": "published", "message": "页面已重置(发布成功)", "screenshot": "/tmp/xhs_result.png", "elapsed_sec": 27.583051681518555, "timestamp": "2026-03-11 09:35:16"}
{"platform": "小红书", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/疗愈师配AI助手能收多少钱 一个小团队5万到10万.mp4", "title": "疗愈师+AI助手组合一个小团队月收5万到10万 #AI赋能 #疗愈商业 #小程序 卡若创业派对", "success": true, "status": "published", "message": "页面已重置(发布成功)", "screenshot": "/tmp/xhs_result.png", "elapsed_sec": 28.647475004196167, "timestamp": "2026-03-11 09:36:00"}
{"platform": "小红书", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/赚钱没那么复杂,自信心才是核心问题.mp4", "title": "赚钱真没那么复杂,自信心才是卡住你的核心问题 #创业心态 #自信 #小程序 卡若创业派对", "success": true, "status": "published", "message": "页面已重置(发布成功)", "screenshot": "/tmp/xhs_result.png", "elapsed_sec": 28.323018074035645, "timestamp": "2026-03-11 09:36:43"}
{"platform": "视频号", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/AI最大的缺点是上下文太短这样来解决.mp4", "title": "AI的短板是记忆太短上下文一长就废了这个方法能解决 #AI工具 #效率提升", "success": false, "status": "error", "message": "Cookie 已过期(需重新扫码登录)", "screenshot": "/tmp/channels_ss/AI最大的缺点是上下文太短这样来解决_login.png", "elapsed_sec": 8.979376077651978, "timestamp": "2026-03-11 09:39:56"}
{"platform": "视频号", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/AI每天剪1000个视频 M4电脑24T素材库全网分发.mp4", "title": "M4芯片+24T素材库AI每天剪1000条视频自动全网分发 #AI剪辑 #内容工厂", "success": false, "status": "error", "message": "Cookie 已过期(需重新扫码登录)", "screenshot": "/tmp/channels_ss/AI每天剪1000个视频 M4电脑24T素材库全网分发_login.png", "elapsed_sec": 8.737346172332764, "timestamp": "2026-03-11 09:40:13"}
{"platform": "视频号", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/Soul派对变现全链路 发视频就有钱,后端全解决.mp4", "title": "Soul派对怎么赚钱发视频就有收益后端体系全部搞定 #Soul派对 #副业收入", "success": false, "status": "error", "message": "Cookie 已过期(需重新扫码登录)", "screenshot": "/tmp/channels_ss/Soul派对变现全链路 发视频就有钱后端全解决_login.png", "elapsed_sec": 8.759697914123535, "timestamp": "2026-03-11 09:40:30"}
{"platform": "视频号", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/从0到切片发布 AI自动完成每天副业30条视频.mp4", "title": "从零到切片发布AI全自动完成每天副业产出30条视频 #AI副业 #切片分发", "success": false, "status": "error", "message": "Cookie 已过期(需重新扫码登录)", "screenshot": "/tmp/channels_ss/从0到切片发布 AI自动完成每天副业30条视频_login.png", "elapsed_sec": 8.611515760421753, "timestamp": "2026-03-11 09:40:46"}
{"platform": "视频号", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/做副业的基本条件 苹果电脑和特殊访问工具.mp4", "title": "做副业的两个基本条件一台Mac和一个上网工具 #副业入门 #工具推荐", "success": false, "status": "error", "message": "Cookie 已过期(需重新扫码登录)", "screenshot": "/tmp/channels_ss/做副业的基本条件 苹果电脑和特殊访问工具_login.png", "elapsed_sec": 8.463750123977661, "timestamp": "2026-03-11 09:41:03"}
{"platform": "视频号", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/切片分发全自动化 从视频到发布一键完成.mp4", "title": "从录制到发布全自动化,一键切片分发五大平台 #自动化 #内容分发", "success": false, "status": "error", "message": "Cookie 已过期(需重新扫码登录)", "screenshot": "/tmp/channels_ss/切片分发全自动化 从视频到发布一键完成_login.png", "elapsed_sec": 8.232975721359253, "timestamp": "2026-03-11 09:41:19"}
{"platform": "视频号", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/创业团队4人平分25有啥危险 先跑钱再谈股权.mp4", "title": "创业团队4人平分25%股权有啥风险?先跑出收入再谈分配 #创业股权 #团队管理", "success": false, "status": "error", "message": "Cookie 已过期(需重新扫码登录)", "screenshot": "/tmp/channels_ss/创业团队4人平分25有啥危险 先跑钱再谈股权_login.png", "elapsed_sec": 8.005096912384033, "timestamp": "2026-03-11 09:41:35"}
{"platform": "视频号", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/坚持到120场是什么感觉 方向越确定执行越坚决.mp4", "title": "坚持到第120场派对是什么感觉方向越清晰执行越坚决 #Soul派对 #坚持的力量", "success": false, "status": "error", "message": "Cookie 已过期(需重新扫码登录)", "screenshot": "/tmp/channels_ss/坚持到120场是什么感觉 方向越确定执行越坚决_login.png", "elapsed_sec": 8.886879920959473, "timestamp": "2026-03-11 09:41:52"}
{"platform": "视频号", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/帮人装AI一单300到1000块传统行业也能做.mp4", "title": "帮传统行业的人装AI工具一单收300到1000块简单好做 #AI服务 #传统行业", "success": false, "status": "error", "message": "Cookie 已过期(需重新扫码登录)", "screenshot": "/tmp/channels_ss/帮人装AI一单300到1000块传统行业也能做_login.png", "elapsed_sec": 7.907478094100952, "timestamp": "2026-03-11 09:42:08"}
{"platform": "视频号", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/深度AI模型对比 哪个才是真正的AI不是语言模型.mp4", "title": "深度对比各大AI模型哪个才是真正的智能而不只是语言模型 #AI对比 #深度思考", "success": false, "status": "error", "message": "Cookie 已过期(需重新扫码登录)", "screenshot": "/tmp/channels_ss/深度AI模型对比 哪个才是真正的AI不是语言模型_login.png", "elapsed_sec": 8.47471284866333, "timestamp": "2026-03-11 09:42:24"}
{"platform": "视频号", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/疗愈师配AI助手能收多少钱 一个小团队5万到10万.mp4", "title": "疗愈师+AI助手组合一个小团队月收5万到10万 #AI赋能 #疗愈商业", "success": false, "status": "error", "message": "Cookie 已过期(需重新扫码登录)", "screenshot": "/tmp/channels_ss/疗愈师配AI助手能收多少钱 一个小团队5万到10万_login.png", "elapsed_sec": 8.188108205795288, "timestamp": "2026-03-11 09:42:41"}
{"platform": "视频号", "video_path": "/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片/赚钱没那么复杂,自信心才是核心问题.mp4", "title": "赚钱真没那么复杂,自信心才是卡住你的核心问题 #创业心态 #自信", "success": false, "status": "error", "message": "Cookie 已过期(需重新扫码登录)", "screenshot": "/tmp/channels_ss/赚钱没那么复杂自信心才是核心问题_login.png", "elapsed_sec": 8.139084100723267, "timestamp": "2026-03-11 09:42:57"}

View File

@@ -1,334 +1,348 @@
#!/usr/bin/env python3
"""
视频号纯 API 发布 — 无浏览器
流程: 读 Cookie → 上传视频(分片) → 发布 → 验证
视频号纯 API 发布 v3 — 零 Playwright全 httpx
协议: helper_upload_params → snsuploadbig 分片上传 → post_create
需要 channels_login.py 先获取一次 Cookie只在过期时用
"""
import asyncio
import hashlib
import json
import math
import random
import sys
import time
import uuid
from pathlib import Path
import httpx
SCRIPT_DIR = Path(__file__).parent
COOKIE_FILE = SCRIPT_DIR / "channels_storage_state.json"
VIDEO_DIR = Path("/Users/karuo/Movies/soul视频/soul 派对 119场 20260309_output/成片")
VIDEO_DIR = Path("/Users/karuo/Movies/soul视频/soul 派对 120场 20260320_output/成片")
sys.path.insert(0, str(SCRIPT_DIR.parent.parent / "多平台分发" / "脚本"))
from publish_result import PublishResult, is_published, save_results, print_summary
BASE = "https://channels.weixin.qq.com"
UPLOAD_BASE = "https://finder-assistant.mp.video.tencent-cloud.com"
CHUNK_SIZE = 8 * 1024 * 1024 # 8MB
UA = (
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36"
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
)
DESC_SUFFIX = " #小程序 卡若创业派对"
CHUNK_SIZE = 1 * 1024 * 1024 # 1MB per chunk
CDN_HOST = "finder.video.qq.com"
CDN_REPLACE_HOST = f"https://{CDN_HOST}"
TITLES = {
"早起不是为了开派对,是不吵老婆睡觉.mp4":
"每天6点起床不是因为自律是因为老婆还在睡 #Soul派对 #创业日记",
"懒人的活法 动作简单有利可图正反馈.mp4":
"懒人也能赚钱?动作简单、有利可图、正反馈 #Soul派对 #副业思维",
"初期团队先找两个IS比钱好使 ENFJ链接人ENTJ指挥.mp4":
"创业初期先找两个IS型人格比融资好使十倍 #MBTI创业 #团队搭建",
"ICU出来一年多 活着要在互联网上留下东西.mp4":
"ICU出来一年多活着就要在互联网上留下东西 #人生感悟 #创业觉醒",
"MBTI疗愈SOUL 年轻人测MBTI40到60岁走五行八卦.mp4":
"20岁测MBTI40岁该学五行八卦了 #MBTI #认知觉醒",
"Soul业务模型 派对+切片+小程序全链路.mp4":
"派对获客→AI切片→小程序变现全链路拆解 #商业模式 #一人公司",
"Soul切片30秒到8分钟 AI半小时能剪10到30个.mp4":
"AI剪辑半小时出10到30条切片内容工厂效率密码 #AI剪辑 #内容效率",
"刷牙听业务逻辑 Soul切片变现怎么跑.mp4":
"刷牙3分钟听完一套变现逻辑 #碎片创业 #副业逻辑",
"国学易经怎么学 两小时七七八八,召唤作者对话.mp4":
"易经两小时学个七七八八,关键是跟古人对话 #国学 #易经入门",
"广点通能投Soul了1000曝光6到10块.mp4":
"广点通能投Soul了1000次曝光只要6到10块 #广点通 #低成本获客",
"建立信任不是求来的 卖外挂发邮件三个月拿下德国总代.mp4":
"信任不是求来的,发三个月邮件拿下德国总代理 #销售思维 #信任建立",
"核心就两个字 筛选。能开派对坚持7天的人再谈.mp4":
"核心就两个字筛选。能坚持7天的人才值得深聊 #筛选思维 #创业认知",
"睡眠不好?每天放下一件事,做减法.mp4":
"睡不好不是太累,是脑子装太多,每天做减法 #做减法 #心理健康",
"这套体系花了170万但前端几十块就能参与.mp4":
"后端花170万搭体系前端几十块就能参与 #商业认知 #体系思维",
"金融AI获客体系 后端30人沉淀12年前端丢手机.mp4":
"后端30人沉淀12年前端就丢个手机号 #AI获客 #系统思维",
"AI最大的缺点是上下文太短这样来解决.mp4":
"AI的短板是记忆太短上下文一长就废了这个方法能解决 #AI工具 #效率提升",
"AI每天剪1000个视频 M4电脑24T素材库全网分发.mp4":
"M4芯片+24T素材库AI每天剪1000条视频自动全网分发 #AI剪辑 #内容工厂",
"Soul派对变现全链路 发视频就有钱,后端全解决.mp4":
"Soul派对怎么赚钱发视频就有收益后端体系全部搞定 #Soul派对 #副业收入",
"从0到切片发布 AI自动完成每天副业30条视频.mp4":
"从零到切片发布AI全自动完成每天副业产出30条视频 #AI副业 #切片分发",
"做副业的基本条件 苹果电脑和特殊访问工具.mp4":
"做副业的两个基本条件一台Mac和一个上网工具 #副业入门 #工具推荐",
"切片分发全自动化 从视频到发布一键完成.mp4":
"从录制到发布全自动化,一键切片分发五大平台 #自动化 #内容分发",
"创业团队4人平分25有啥危险 先跑钱再谈股权.mp4":
"创业团队4人平分25%股权有啥风险?先跑出收入再谈分配 #创业股权 #团队管理",
"坚持到120场是什么感觉 方向越确定执行越坚决.mp4":
"坚持到第120场派对是什么感觉方向越清晰执行越坚决 #Soul派对 #坚持的力量",
"帮人装AI一单300到1000块传统行业也能做.mp4":
"帮传统行业的人装AI工具一单收300到1000块简单好做 #AI服务 #传统行业",
"深度AI模型对比 哪个才是真正的AI不是语言模型.mp4":
"深度对比各大AI模型哪个才是真正的智能而不只是语言模型 #AI对比 #深度思考",
"疗愈师配AI助手能收多少钱 一个小团队5万到10万.mp4":
"疗愈师+AI助手组合一个小团队月收5万到10万 #AI赋能 #疗愈商业",
"赚钱没那么复杂,自信心才是核心问题.mp4":
"赚钱真没那么复杂,自信心才是卡住你的核心问题 #创业心态 #自信",
}
def load_cookies() -> dict:
def load_cookies() -> str | None:
if not COOKIE_FILE.exists():
return {}
state = json.loads(COOKIE_FILE.read_text())
return {c["name"]: c["value"] for c in state.get("cookies", [])}
print("[✗] Cookie 文件不存在,请先运行 channels_login.py", flush=True)
return None
with open(COOKIE_FILE) as f:
state = json.load(f)
cookies = {c["name"]: c["value"] for c in state.get("cookies", [])}
if "sessionid" not in cookies:
print("[✗] Cookie 中无 sessionid", flush=True)
return None
return "; ".join(f"{k}={v}" for k, v in cookies.items())
def _build_client(cookies: dict) -> httpx.Client:
return httpx.Client(
cookies=cookies,
headers={
"User-Agent": UA,
"Origin": BASE,
"Referer": f"{BASE}/platform/post/create",
},
follow_redirects=True,
timeout=120,
def base_headers(cookie_str: str) -> dict:
return {
"Cookie": cookie_str,
"User-Agent": UA,
"Content-Type": "application/json",
"Referer": "https://channels.weixin.qq.com/platform/post/create",
"Origin": "https://channels.weixin.qq.com",
}
async def auth_check(client: httpx.AsyncClient) -> dict | None:
r = await client.post(
"https://channels.weixin.qq.com/cgi-bin/mmfinderassistant-bin/auth/auth_data",
json={},
)
def _api_post(client: httpx.Client, path: str, payload: dict | None = None) -> dict:
url = f"{BASE}/cgi-bin/mmfinderassistant-bin/{path}"
r = client.post(url, json=payload or {})
return r.json()
def _file_md5(path: str) -> str:
h = hashlib.md5()
with open(path, "rb") as f:
for chunk in iter(lambda: f.read(8192), b""):
h.update(chunk)
return h.hexdigest()
def check_auth(client: httpx.Client) -> dict | None:
"""验证 Cookie 有效性,返回用户信息"""
d = _api_post(client, "auth/auth_data")
if d.get("errCode") == 0:
return d.get("data", {}).get("finderUser", {})
data = r.json()
if data.get("errCode") == 0:
return data.get("data", {})
return None
def upload_video(client: httpx.Client, video_path: str) -> dict | None:
"""上传视频到腾讯云,返回 media 信息"""
async def get_upload_params(client: httpx.AsyncClient) -> dict | None:
r = await client.post(
"https://channels.weixin.qq.com/cgi-bin/mmfinderassistant-bin/helper/helper_upload_params",
json={"scene": 7, "force_login": False},
)
data = r.json()
if data.get("errCode") == 0:
return data.get("data", {})
print(f" [✗] upload_params: {data}", flush=True)
return None
async def cdn_upload_video(cookie_str: str, up: dict, video_path: str) -> dict | None:
"""分片上传视频到 CDN返回 {fileurl, thumburl, ...}"""
fpath = Path(video_path)
fsize = fpath.stat().st_size
fname = fpath.name
fmd5 = _file_md5(video_path)
n_parts = math.ceil(fsize / CHUNK_SIZE)
file_uuid = str(uuid.uuid4()).replace("-", "")
print(f" [上传] {fname} ({fsize / 1024 / 1024:.1f}MB, {n_parts} 分片)", flush=True)
cdn_url = f"https://{CDN_HOST}/snsuploadbig"
total_chunks = math.ceil(fsize / CHUNK_SIZE)
# Step 1: Apply for upload
apply_payload = {
"mediaName": fname,
"mediaSize": fsize,
"mediaMd5": fmd5,
"mediaType": "video/mp4",
"chunkSize": CHUNK_SIZE,
}
r = client.post(f"{UPLOAD_BASE}/applyuploaddfs", json=apply_payload)
try:
d = r.json()
except Exception:
print(f" [上传] applyuploaddfs 失败: status={r.status_code} body={r.text[:200]}", flush=True)
return None
print(f" [CDN] 上传 {fsize/1024/1024:.1f}MB{total_chunks} 个分片", flush=True)
if "data" not in d:
print(f" [上传] applyuploaddfs 无 data: {json.dumps(d, ensure_ascii=False)[:200]}", flush=True)
return None
with open(fpath, "rb") as f:
video_data = f.read()
upload_id = d["data"].get("uploadId") or d["data"].get("UploadId")
if not upload_id:
print(f" [上传] 未获取到 uploadId: {json.dumps(d['data'], ensure_ascii=False)[:200]}", flush=True)
return None
last_response = None
async with httpx.AsyncClient(timeout=60) as cdn_client:
for chunk_idx in range(total_chunks):
start = chunk_idx * CHUNK_SIZE
end = min(start + CHUNK_SIZE, fsize)
chunk = video_data[start:end]
chunk_md5 = hashlib.md5(chunk).hexdigest()
print(f" [上传] uploadId = {upload_id[:30]}...", flush=True)
# Step 2: Upload parts
parts = []
with open(video_path, "rb") as f:
for i in range(n_parts):
chunk = f.read(CHUNK_SIZE)
part_num = i + 1
print(f" [上传] 分片 {part_num}/{n_parts} ({len(chunk) / 1024:.0f}KB)...", flush=True)
r2 = client.post(
f"{UPLOAD_BASE}/uploadpartdfs",
data={"uploadId": upload_id, "partNumber": str(part_num)},
files={"file": (fname, chunk, "application/octet-stream")},
timeout=120,
)
try:
d2 = r2.json()
etag = d2.get("data", {}).get("ETag") or d2.get("data", {}).get("etag")
if etag:
parts.append({"PartNumber": part_num, "ETag": etag})
print(f" [上传] 分片 {part_num} 完成 (ETag={etag[:20]}...)", flush=True)
else:
print(f" [上传] 分片 {part_num} 无 ETag: {json.dumps(d2, ensure_ascii=False)[:150]}", flush=True)
except Exception:
print(f" [上传] 分片 {part_num} 失败: status={r2.status_code}", flush=True)
if len(parts) != n_parts:
print(f" [上传] 分片不完整: {len(parts)}/{n_parts}", flush=True)
return None
# Step 3: Complete upload
complete_payload = {
"uploadId": upload_id,
"partInfo": parts,
}
r3 = client.post(f"{UPLOAD_BASE}/completepartuploaddfs", json=complete_payload)
try:
d3 = r3.json()
media_url = d3.get("data", {}).get("httpsUrl") or d3.get("data", {}).get("DownloadURL")
if media_url:
print(f" [上传] 完成! URL = {media_url[:60]}...", flush=True)
return {
"url": media_url,
"uploadId": upload_id,
"md5": fmd5,
"size": fsize,
"parts": parts,
"completeResp": d3.get("data", {}),
form_data = {
"ver": "1",
"seq": str(random.random() + time.time()),
"weixinnum": str(up["uin"]),
"apptype": str(up["appType"]),
"filetype": str(up["videoFileType"]),
"authkey": up["authKey"],
"hasthumb": "0",
"filekey": fname,
"totalsize": str(fsize),
"fileuuid": file_uuid,
"rangestart": str(start),
"rangeend": str(end),
"blockmd5": chunk_md5,
"forcetranscode": "0",
}
else:
print(f" [上传] complete 无 URL: {json.dumps(d3, ensure_ascii=False)[:200]}", flush=True)
except Exception:
print(f" [上传] complete 失败: status={r3.status_code}", flush=True)
return None
files = {"filedata": (fname, chunk, "application/octet-stream")}
retry = 0
while retry < 3:
try:
r = await cdn_client.post(
cdn_url,
data=form_data,
files=files,
headers={
"User-Agent": UA,
"Cookie": cookie_str,
},
)
resp = r.json()
last_response = resp
if resp.get("retcode") and resp["retcode"] != 0:
print(f" [CDN] 分片 {chunk_idx+1} 失败: retcode={resp['retcode']}", flush=True)
retry += 1
await asyncio.sleep(2)
continue
if chunk_idx % 5 == 0 or chunk_idx == total_chunks - 1:
finish = "" if resp.get("uploadfinish") else f"{chunk_idx+1}/{total_chunks}"
print(f" [CDN] {finish}", flush=True)
if resp.get("uploadfinish"):
fileurl = resp.get("fileurl", "")
if "wxapp.tc.qq.com" in fileurl:
fileurl = fileurl.replace("http://wxapp.tc.qq.com", CDN_REPLACE_HOST)
resp["httpsUrl"] = fileurl
return resp
break
except Exception as e:
retry += 1
print(f" [CDN] 分片 {chunk_idx+1} 异常: {e}", flush=True)
if retry >= 3:
return None
await asyncio.sleep(2)
return last_response
def publish_video(client: httpx.Client, media_info: dict, description: str) -> dict:
"""调用发布 API"""
payload = {
"description": description,
"mediaInfo": media_info,
async def create_post(client: httpx.AsyncClient, desc: str, cdn_resp: dict, video_path: str) -> dict:
"""调用 post_create 发表"""
fileurl = cdn_resp.get("httpsUrl") or cdn_resp.get("fileurl", "")
thumburl = cdn_resp.get("thumburl", "")
fpath = Path(video_path)
media_item = {
"mediaType": 4,
"url": fileurl,
"thumbUrl": thumburl if thumburl else "",
"fileSize": str(fpath.stat().st_size),
}
return _api_post(client, "helper/helper_video_publish", payload)
payload = {
"objectDesc": {
"description": desc,
"mediaList": [media_item],
},
"postType": 9,
"scene": 7,
}
r = await client.post(
"https://channels.weixin.qq.com/cgi-bin/mmfinderassistant-bin/post/post_create",
json=payload,
)
return r.json()
def verify_published(client: httpx.Client, title_keyword: str) -> bool:
"""通过 post_list API 检查视频是否发布"""
d = _api_post(client, "post/post_list", {"currentPage": 1, "pageSize": 20})
if d.get("errCode") != 0:
return False
posts = d.get("data", {}).get("list", [])
kw = title_keyword[:15]
for p in posts:
desc = p.get("desc", p.get("description", ""))
if kw in desc:
return True
return False
def publish_one(
async def publish_one(
client: httpx.AsyncClient,
cookie_str: str,
up_params: dict,
video_path: str,
title: str,
idx: int = 1,
total: int = 1,
skip_dedup: bool = False,
idx: int,
total: int,
) -> PublishResult:
fname = Path(video_path).name
fsize = Path(video_path).stat().st_size
t0 = time.time()
print(f"\n[{idx}/{total}] {fname} ({fsize / 1024 / 1024:.1f}MB)", flush=True)
print(f"\n[{idx}/{total}] {fname} ({fsize/1024/1024:.1f}MB)", flush=True)
print(f" 标题: {title[:60]}", flush=True)
if not skip_dedup and is_published("视频号", video_path):
if is_published("视频号", video_path):
print(" [跳过] 已发布", flush=True)
return PublishResult(
platform="视频号", video_path=video_path, title=title,
success=True, status="skipped", message="去重跳过",
)
cookies = load_cookies()
if not cookies:
r = PublishResult(
# Step 1: CDN 上传
cdn_resp = await cdn_upload_video(cookie_str, up_params, video_path)
if not cdn_resp or not cdn_resp.get("uploadfinish"):
return PublishResult(
platform="视频号", video_path=video_path, title=title,
success=False, status="error", message="Cookie 不存在,请先运行 channels_api_login.py",
)
print(f" {r.log_line()}", flush=True)
return r
client = _build_client(cookies)
# 验证登录
user = check_auth(client)
if not user:
r = PublishResult(
platform="视频号", video_path=video_path, title=title,
success=False, status="error", message="Cookie 已过期",
success=False, status="error",
message=f"CDN 上传失败: {json.dumps(cdn_resp or {}, ensure_ascii=False)[:100]}",
elapsed_sec=time.time() - t0,
)
print(f" {r.log_line()}", flush=True)
return r
# 上传
media = upload_video(client, video_path)
if not media:
r = PublishResult(
platform="视频号", video_path=video_path, title=title,
success=False, status="error", message="视频上传失败",
elapsed_sec=time.time() - t0,
)
print(f" {r.log_line()}", flush=True)
return r
# 发布
print(" [发布] 调用 helper_video_publish...", flush=True)
pub_result = publish_video(client, media, title)
pub_code = pub_result.get("errCode", -1)
print(f" [发布] errCode={pub_code}", flush=True)
fileurl = cdn_resp.get("httpsUrl") or cdn_resp.get("fileurl", "")
print(f" [✓] CDN 上传完成: {fileurl[:80]}...", flush=True)
# Step 2: 发表
desc_full = title + DESC_SUFFIX
post_resp = await create_post(client, desc_full, cdn_resp, video_path)
elapsed = time.time() - t0
if pub_code == 0:
r = PublishResult(
err = post_resp.get("errCode", -1)
if err == 0:
result = PublishResult(
platform="视频号", video_path=video_path, title=title,
success=True, status="reviewing",
message=f"API 发布成功 (errCode=0)",
success=True, status="published",
message=f"API 发布成功 ({elapsed:.1f}s)",
elapsed_sec=elapsed,
)
else:
r = PublishResult(
msg = post_resp.get("errMsg", "")
result = PublishResult(
platform="视频号", video_path=video_path, title=title,
success=False, status="error",
message=f"发布失败: {json.dumps(pub_result, ensure_ascii=False)[:120]}",
message=f"post_create 失败: errCode={err} {msg} | resp={json.dumps(post_resp, ensure_ascii=False)[:150]}",
elapsed_sec=elapsed,
)
print(f" {r.log_line()}", flush=True)
return r
print(f" {result.log_line()}", flush=True)
return result
def main():
cookies = load_cookies()
if not cookies:
print("[✗] Cookie 不存在,请先运行: python3 channels_api_login.py", flush=True)
async def main():
print("=== 视频号纯 API 发布 ===\n", flush=True)
cookie_str = load_cookies()
if not cookie_str:
return 1
client = _build_client(cookies)
user = check_auth(client)
if not user:
print("[✗] Cookie 已过期,请重新运行: python3 channels_api_login.py", flush=True)
return 1
print(f"[✓] 已登录: {user.get('nickname', '?')} (作品数: {user.get('feedsCount', '?')})", flush=True)
videos = sorted(VIDEO_DIR.glob("*.mp4"))
if not videos:
print("[✗] 未找到视频", flush=True)
return 1
print(f"{len(videos)} 条视频\n", flush=True)
results = []
for i, vp in enumerate(videos):
t = TITLES.get(vp.name, f"{vp.stem} #Soul派对 #创业日记")
r = publish_one(str(vp), t, i + 1, len(videos))
results.append(r)
if r.status != "skipped":
save_results([r])
if i < len(videos) - 1:
time.sleep(5)
need_pub = [v for v in videos if not is_published("视频号", str(v))]
print(f"{len(videos)} 条视频,{len(need_pub)} 条待发布\n", flush=True)
if not need_pub:
print("[✓] 全部已发布", flush=True)
return 0
headers = base_headers(cookie_str)
async with httpx.AsyncClient(headers=headers, timeout=30) as client:
# 1. 验证身份
auth = await auth_check(client)
if not auth:
print("[✗] Cookie 无效,请重新运行 channels_login.py", flush=True)
return 1
fu = auth.get("finderUser", {})
print(f" 账号: {fu.get('nickname', '?')} | 粉丝: {fu.get('fansCount', 0)} | 作品: {fu.get('feedsCount', 0)}", flush=True)
# 2. 获取上传参数
up_params = await get_upload_params(client)
if not up_params:
return 1
print(f" 上传参数: authKey={up_params['authKey'][:20]}... uin={up_params['uin']} appType={up_params['appType']}\n", flush=True)
# 3. 逐条发布
results = []
consecutive_fail = 0
for i, vp in enumerate(videos):
t = TITLES.get(vp.name, f"{vp.stem} #Soul派对 #创业日记")
r = await publish_one(client, cookie_str, up_params, str(vp), t, i + 1, len(videos))
results.append(r)
if r.status != "skipped":
save_results([r])
if r.status == "skipped":
consecutive_fail = 0
elif r.success:
consecutive_fail = 0
else:
consecutive_fail += 1
if consecutive_fail >= 2:
print("\n[!] 连续 2 次失败,终止", flush=True)
break
if i < len(videos) - 1 and r.status != "skipped":
await asyncio.sleep(8)
actual = [r for r in results if r.status != "skipped"]
print_summary(actual)
@@ -337,4 +351,4 @@ def main():
if __name__ == "__main__":
sys.exit(main())
sys.exit(asyncio.run(main()))

View File

@@ -1,22 +1,22 @@
#!/usr/bin/env python3
"""视频号 Cookie 获取 - Playwright 扫码登录 → 保存 storage_state
v3: 登录后多次导航确保 Cookie 写入 + 验证 Cookie 存在
"""
"""视频号登录 v4 — 扫码后提取 token + Cookie供纯 API 发布使用"""
import asyncio
import json
import sys
from pathlib import Path
from urllib.parse import urlparse, parse_qs
from playwright.async_api import async_playwright
COOKIE_FILE = Path(__file__).parent / "channels_storage_state.json"
SCRIPT_DIR = Path(__file__).parent
COOKIE_FILE = SCRIPT_DIR / "channels_storage_state.json"
TOKEN_FILE = SCRIPT_DIR / "channels_token.json"
LOGIN_URL = "https://channels.weixin.qq.com/login"
PLATFORM_URL = "https://channels.weixin.qq.com/platform"
QR_SCREENSHOT = Path("/tmp/channels_qr.png")
UA = (
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36"
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
)
@@ -40,12 +40,17 @@ async def main():
print("请用微信扫描浏览器中的二维码...\n", flush=True)
logged_in = False
token = None
for i in range(60):
await asyncio.sleep(5)
url = page.url
if "platform" in url and "login" not in url:
logged_in = True
print(f"[✓] 检测到登录跳转: {url[:80]}", flush=True)
parsed = parse_qs(urlparse(url).query)
token = parsed.get("token", [None])[0]
print(f"[✓] 登录成功URL: {url[:100]}", flush=True)
if token:
print(f"[✓] 提取到 token: {token[:20]}...", flush=True)
break
cookies = await context.cookies()
has_session = any(c["name"] == "sessionid" for c in cookies)
@@ -57,59 +62,87 @@ async def main():
print(f" 等待扫码中... ({i * 5}s)", flush=True)
if not logged_in:
print("[✗] 5 分钟超时。请重新运行此脚本再试。", flush=True)
print("[✗] 5 分钟超时。", flush=True)
await browser.close()
return 1
# 确保 Cookie 完全写入:多导航几次
print("[...] 等待 Cookie 完全写入...", flush=True)
# 确保跳转完成并提取 token
await asyncio.sleep(5)
if not token:
try:
await page.goto(
"https://channels.weixin.qq.com/platform/post/list",
timeout=15000, wait_until="domcontentloaded",
)
await asyncio.sleep(5)
url = page.url
parsed = parse_qs(urlparse(url).query)
token = parsed.get("token", [None])[0]
if token:
print(f"[✓] 从 post/list 页提取 token: {token[:20]}...", flush=True)
except Exception:
pass
try:
await page.goto(
"https://channels.weixin.qq.com/platform/post/list",
timeout=15000,
wait_until="domcontentloaded",
)
await asyncio.sleep(3)
except Exception:
pass
# 如果 URL 里没 token尝试从页面 JS 提取
if not token:
try:
token = await page.evaluate("""() => {
if (window.__wxConfig && window.__wxConfig.token) return window.__wxConfig.token;
const m = document.cookie.match(/token=([^;]+)/);
if (m) return m[1];
const u = location.href;
const tm = u.match(/token=([^&]+)/);
if (tm) return tm[1];
return null;
}""")
if token:
print(f"[✓] 从 JS 提取 token: {token[:20]}...", flush=True)
except Exception:
pass
cookies = await context.cookies()
print(f"[Cookie] 共获取 {len(cookies)} 个 Cookie:", flush=True)
for c in cookies:
print(f" {c['name']} (domain={c['domain']}, expires={c.get('expires', 'N/A')})", flush=True)
if not any(c["name"] == "sessionid" for c in cookies):
print("[⚠] 未找到 sessionid Cookie可能登录不完整", flush=True)
print(" 尝试手动刷新页面后等待...", flush=True)
await page.reload()
await asyncio.sleep(5)
cookies = await context.cookies()
print(f"[Cookie] 刷新后共 {len(cookies)} 个 Cookie", flush=True)
# 尝试拦截 API 获取 token
if not token:
try:
r = await page.evaluate("""async () => {
const resp = await fetch('/cgi-bin/mmfinderassistant-bin/auth/auth_data', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({})
});
return await resp.json();
}""")
if r and r.get("errCode") == 0:
token = r.get("data", {}).get("token") or r.get("token")
print(f"[✓] 从 auth_data 获取: errCode=0", flush=True)
else:
print(f"[i] auth_data 返回: {json.dumps(r, ensure_ascii=False)[:200]}", flush=True)
except Exception as e:
print(f"[i] auth_data 异常: {e}", flush=True)
# 保存 storage_state
await context.storage_state(path=str(COOKIE_FILE))
# 验证保存结果
saved = json.loads(COOKIE_FILE.read_text())
saved_cookies = saved.get("cookies", [])
if not saved_cookies:
print("[✗] 警告:保存的 Cookie 为空!登录可能失败。", flush=True)
await browser.close()
return 1
# 保存 token 信息
cookies = await context.cookies()
cookie_dict = {c["name"]: c["value"] for c in cookies}
token_data = {
"token": token,
"sessionid": cookie_dict.get("sessionid", ""),
"wxuin": cookie_dict.get("wxuin", ""),
"cookie_str": "; ".join(f'{c["name"]}={c["value"]}' for c in cookies),
"url": page.url,
}
with open(TOKEN_FILE, "w") as f:
json.dump(token_data, f, ensure_ascii=False, indent=2)
await context.close()
await browser.close()
print(f"\n[✓] 视频号 Cookie 已保存: {COOKIE_FILE}", flush=True)
print(f" Cookie 数量: {len(saved_cookies)}", flush=True)
print(f" 文件大小: {COOKIE_FILE.stat().st_size} bytes", flush=True)
session = [c for c in saved_cookies if c["name"] == "sessionid"]
if session:
import datetime
exp = datetime.datetime.fromtimestamp(session[0].get("expires", 0))
print(f" sessionid 过期: {exp}", flush=True)
print("现在可运行 channels_publish.py 批量发布。", flush=True)
print(f"\n[✓] Cookie 已保存: {COOKIE_FILE}", flush=True)
print(f"[✓] Token 已保存: {TOKEN_FILE}", flush=True)
sc = json.loads(COOKIE_FILE.read_text()).get("cookies", [])
print(f" Cookie 数量: {len(sc)}", flush=True)
print(f" token: {'' if token else '✗ 未提取到(可能需要在浏览器页面交互后才出现)'}", flush=True)
return 0

View File

@@ -388,11 +388,14 @@ async def main():
from cookie_manager import check_cookie_valid
print("=== 账号预检 ===", flush=True)
ok, info = check_cookie_valid("视频号")
print(f" 视频号: {info}", flush=True)
if not ok:
print("[✗] 账号预检不通过,终止发布", flush=True)
if not COOKIE_FILE.exists():
print("[✗] Cookie 文件不存在,请先运行 channels_login.py 扫码", flush=True)
return 1
import os, time as _t
age_h = (_t.time() - os.path.getmtime(str(COOKIE_FILE))) / 3600
print(f" 视频号: Cookie 文件存在 (更新于 {age_h:.1f}h 前)", flush=True)
if age_h > 48:
print("[⚠] Cookie 超过 48h可能已过期", flush=True)
print()
videos = sorted(VIDEO_DIR.glob("*.mp4"))

View File

@@ -1 +1 @@
{"cookies": [{"name": "sessionid", "value": "BgAAXn42dDVxziLfiAgbkcIfNWJuq3q4eqUcsucKM6%2B22j8kyqgfK6EmAYjVKRnfRVF5H4ImiqYsYmA%2FHCKErGMPGj9qUIkciQgbCJitvtI%3D", "domain": "channels.weixin.qq.com", "path": "/", "expires": 1807752687.942864, "httpOnly": false, "secure": true, "sameSite": "None"}, {"name": "wxuin", "value": "3584477580", "domain": "channels.weixin.qq.com", "path": "/", "expires": 1807752687.942958, "httpOnly": false, "secure": true, "sameSite": "None"}], "origins": [{"origin": "https://channels.weixin.qq.com", "localStorage": [{"name": "finder_route_meta", "value": "micro.content/post/list;index;1;1773192699321"}, {"name": "__ml::hb_ts", "value": "1773192690709"}, {"name": "__ml::page_1819fde5-8cd1-4fc4-a0a0-02ccc76e5581", "value": "{\"pageId\":\"LoginForIframe\",\"accessId\":\"c11107b0-1b67-4ed6-86d1-641dde624ca0\",\"step\":1}"}, {"name": "__ml::page_5e0063e9-0029-467d-a08a-289bc33adc36", "value": "{\"pageId\":\"LoginForIframe\",\"accessId\":\"c386e434-b5d1-41e5-a2fd-4f0816f0b734\",\"step\":1}"}, {"name": "__rx::aid", "value": "\"703dddc3-441f-43df-af5a-4b45cad6672e\""}, {"name": "__ml::aid", "value": "\"703dddc3-441f-43df-af5a-4b45cad6672e\""}, {"name": "__ml::page", "value": "[\"5e0063e9-0029-467d-a08a-289bc33adc36\",\"1819fde5-8cd1-4fc4-a0a0-02ccc76e5581\",\"1868b17e-5980-4657-afd9-d0dcd1d69a66\",\"b5b449ff-c981-41e2-acce-928cd78ac655\"]"}, {"name": "finder_login_token", "value": ""}, {"name": "__ml::page_b5b449ff-c981-41e2-acce-928cd78ac655", "value": "{\"pageId\":\"PostList\",\"accessId\":\"6f900704-4b40-4c5d-9112-5dcc0eba3220\",\"step\":1}"}, {"name": "finder_username", "value": "v2_060000231003b20faec8c5e48919cbd5cb05e53db077dd1924028a806c10cffd891eb5a80ce7@finder"}, {"name": "_finger_print_device_id", "value": "7560eede9c907e094cee8c2d642456c1"}, {"name": "MICRO_VISITED_NAME", "value": "{\"content\":1}"}, {"name": "__ml::page_1868b17e-5980-4657-afd9-d0dcd1d69a66", "value": "{\"pageId\":\"MicroPost\",\"accessId\":\"783ab67d-d2aa-4007-9fed-50aa8a8f3757\",\"step\":1}"}, {"name": "UvFirstReportLocalKey", "value": "1773158400000"}, {"name": "finder_ua_report_data", "value": "{\"browser\":\"Chrome\",\"browserVersion\":\"143.0.0.0\",\"engine\":\"Webkit\",\"engineVersion\":\"537.36\",\"os\":\"Mac OS X\",\"osVersion\":\"10.15.7\",\"device\":\"desktop\",\"darkmode\":0}"}, {"name": "finder_uin", "value": ""}]}]}
{"cookies": [{"name": "sessionid", "value": "BgAAAF49A306%2BZXTPNOD8NWcslTni1y5Yd5rbk57LFPa7ef7Pz0phCkSQGKzd0tSrwWrTUU8e6fVq%2FJAAiRlE0vaJtoq0DYUVsu2KoVnA0Q%3D", "domain": "channels.weixin.qq.com", "path": "/", "expires": 1807753586.663472, "httpOnly": false, "secure": true, "sameSite": "None"}, {"name": "wxuin", "value": "2247032622", "domain": "channels.weixin.qq.com", "path": "/", "expires": 1807753586.663536, "httpOnly": false, "secure": true, "sameSite": "None"}], "origins": [{"origin": "https://channels.weixin.qq.com", "localStorage": [{"name": "finder_route_meta", "value": "micro.content/post/list;index;1;1773193599291"}, {"name": "__ml::hb_ts", "value": "1773193576807"}, {"name": "__ml::page_90bf107e-8dc7-4df0-af16-4f37a8453c48", "value": "{\"pageId\":\"LoginForIframe\",\"accessId\":\"e75bae67-04d4-44c7-9503-2567b55ea5a5\",\"step\":1}"}, {"name": "__ml::page_a74abce1-ba34-4561-af49-8ca41878b4e5", "value": "{\"pageId\":\"MicroPost\",\"accessId\":\"eb40f2d0-bb81-4c5a-9814-44b9e378e7cf\",\"step\":1}"}, {"name": "__rx::aid", "value": "\"64f343de-d72b-48fa-bbd2-86ae460b8a9c\""}, {"name": "__ml::aid", "value": "\"64f343de-d72b-48fa-bbd2-86ae460b8a9c\""}, {"name": "__ml::page", "value": "[\"90bf107e-8dc7-4df0-af16-4f37a8453c48\",\"d38330de-643b-47e9-b40e-63c3b3b294f5\",\"a74abce1-ba34-4561-af49-8ca41878b4e5\",\"a014ba09-1674-4c61-8252-72fbe0483884\"]"}, {"name": "finder_login_token", "value": ""}, {"name": "__ml::page_d38330de-643b-47e9-b40e-63c3b3b294f5", "value": "{\"pageId\":\"LoginForIframe\",\"accessId\":\"6995cc81-030d-45a1-a3b3-81a702f29890\",\"step\":1}"}, {"name": "finder_username", "value": "v2_060000231003b20faec8c5e48919cbd5cb05e53db077dd1924028a806c10cffd891eb5a80ce7@finder"}, {"name": "_finger_print_device_id", "value": "6fd704941768442b12a996d2652fc61e"}, {"name": "MICRO_VISITED_NAME", "value": "{\"content\":1}"}, {"name": "__ml::page_a014ba09-1674-4c61-8252-72fbe0483884", "value": "{\"pageId\":\"PostList\",\"accessId\":\"b9ab38d8-1f82-4bf3-96ca-1ce2d7ba2ec2\",\"step\":1}"}, {"name": "UvFirstReportLocalKey", "value": "1773158400000"}, {"name": "finder_ua_report_data", "value": "{\"browser\":\"Chrome\",\"browserVersion\":\"131.0.0.0\",\"engine\":\"Webkit\",\"engineVersion\":\"537.36\",\"os\":\"Mac OS X\",\"osVersion\":\"10.15.7\",\"device\":\"desktop\",\"darkmode\":0}"}, {"name": "finder_uin", "value": ""}]}]}

View File

@@ -0,0 +1,7 @@
{
"token": null,
"sessionid": "BgAAAF49A306%2BZXTPNOD8NWcslTni1y5Yd5rbk57LFPa7ef7Pz0phCkSQGKzd0tSrwWrTUU8e6fVq%2FJAAiRlE0vaJtoq0DYUVsu2KoVnA0Q%3D",
"wxuin": "2247032622",
"cookie_str": "sessionid=BgAAAF49A306%2BZXTPNOD8NWcslTni1y5Yd5rbk57LFPa7ef7Pz0phCkSQGKzd0tSrwWrTUU8e6fVq%2FJAAiRlE0vaJtoq0DYUVsu2KoVnA0Q%3D; wxuin=2247032622",
"url": "https://channels.weixin.qq.com/platform/post/list"
}

View File

@@ -282,3 +282,4 @@
| 2026-03-11 06:00:47 | 🔄 卡若AI 同步 2026-03-11 06:00 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 11 个 |
| 2026-03-11 06:14:29 | 🔄 卡若AI 同步 2026-03-11 06:14 | 更新:卡木、运营中枢工作台 | 排除 >20MB: 11 个 |
| 2026-03-11 06:22:48 | 🔄 卡若AI 同步 2026-03-11 06:22 | 更新:运营中枢工作台 | 排除 >20MB: 11 个 |
| 2026-03-11 09:35:20 | 🔄 卡若AI 同步 2026-03-11 09:35 | 更新:卡木、火炬、总索引与入口、运营中枢工作台 | 排除 >20MB: 11 个 |

View File

@@ -285,3 +285,4 @@
| 2026-03-11 06:00:47 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-11 06:00 | 更新:水桥平台对接、运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
| 2026-03-11 06:14:29 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-11 06:14 | 更新:卡木、运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
| 2026-03-11 06:22:48 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-11 06:22 | 更新:运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
| 2026-03-11 09:35:20 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-11 09:35 | 更新:卡木、火炬、总索引与入口、运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |