Files
Auto-Redbook-Skills/scripts/publish_xhs.py
2026-01-18 21:56:39 +08:00

203 lines
5.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
小红书笔记发布脚本
将生成的图片卡片发布到小红书
使用方法:
python publish_xhs.py --title "标题" --desc "描述" --images cover.png card_1.png card_2.png
环境变量:
在同目录下创建 .env 文件,配置 XHS_COOKIE
XHS_COOKIE=your_cookie_string_here
依赖安装:
pip install xhs python-dotenv
"""
import argparse
import os
import sys
from pathlib import Path
try:
from dotenv import load_dotenv
from xhs import XhsClient
except ImportError as e:
print(f"缺少依赖: {e}")
print("请运行: pip install xhs python-dotenv")
sys.exit(1)
def load_cookie():
"""从 .env 文件加载 Cookie"""
# 尝试从当前目录加载 .env
env_path = Path.cwd() / '.env'
if env_path.exists():
load_dotenv(env_path)
# 也尝试从脚本目录加载
script_env = Path(__file__).parent.parent / '.env'
if script_env.exists():
load_dotenv(script_env)
cookie = os.getenv('XHS_COOKIE')
if not cookie:
print("❌ 错误: 未找到 XHS_COOKIE 环境变量")
print("请在当前目录创建 .env 文件,添加以下内容:")
print("XHS_COOKIE=your_cookie_string_here")
sys.exit(1)
return cookie
def create_client(cookie: str) -> XhsClient:
"""创建小红书客户端"""
try:
# 使用本地签名
from xhs.help import sign as local_sign
def sign_func(uri, data=None, a1="", web_session=""):
return local_sign(uri, data, a1=a1)
client = XhsClient(cookie=cookie, sign=sign_func)
return client
except Exception as e:
print(f"❌ 创建客户端失败: {e}")
sys.exit(1)
def validate_images(image_paths: list) -> list:
"""验证图片文件是否存在"""
valid_images = []
for path in image_paths:
if os.path.exists(path):
valid_images.append(os.path.abspath(path))
else:
print(f"⚠️ 警告: 图片不存在 - {path}")
if not valid_images:
print("❌ 错误: 没有有效的图片文件")
sys.exit(1)
return valid_images
def publish_note(client: XhsClient, title: str, desc: str, images: list,
is_private: bool = False, post_time: str = None):
"""发布图文笔记"""
try:
print(f"\n🚀 准备发布笔记...")
print(f" 📌 标题: {title}")
print(f" 📝 描述: {desc[:50]}..." if len(desc) > 50 else f" 📝 描述: {desc}")
print(f" 🖼️ 图片数量: {len(images)}")
result = client.create_image_note(
title=title,
desc=desc,
files=images,
is_private=is_private,
post_time=post_time
)
print("\n✨ 笔记发布成功!")
if isinstance(result, dict):
note_id = result.get('note_id') or result.get('id')
if note_id:
print(f" 📎 笔记ID: {note_id}")
print(f" 🔗 链接: https://www.xiaohongshu.com/explore/{note_id}")
return result
except Exception as e:
print(f"\n❌ 发布失败: {e}")
sys.exit(1)
def get_user_info(client: XhsClient):
"""获取当前登录用户信息"""
try:
info = client.get_self_info()
print(f"\n👤 当前用户: {info.get('nickname', '未知')}")
return info
except Exception as e:
print(f"⚠️ 无法获取用户信息: {e}")
return None
def main():
parser = argparse.ArgumentParser(
description='将图片发布为小红书笔记'
)
parser.add_argument(
'--title', '-t',
required=True,
help='笔记标题不超过20字'
)
parser.add_argument(
'--desc', '-d',
default='',
help='笔记描述/正文内容'
)
parser.add_argument(
'--images', '-i',
nargs='+',
required=True,
help='图片文件路径(可以多个)'
)
parser.add_argument(
'--private',
action='store_true',
help='是否设为私密笔记'
)
parser.add_argument(
'--post-time',
default=None,
help='定时发布时间格式2024-01-01 12:00:00'
)
parser.add_argument(
'--dry-run',
action='store_true',
help='仅验证,不实际发布'
)
args = parser.parse_args()
# 验证标题长度
if len(args.title) > 20:
print(f"⚠️ 警告: 标题超过20字将被截断")
args.title = args.title[:20]
# 加载 Cookie
cookie = load_cookie()
# 验证图片
valid_images = validate_images(args.images)
# 创建客户端
client = create_client(cookie)
# 获取用户信息(验证 Cookie 有效性)
get_user_info(client)
if args.dry_run:
print("\n🔍 验证模式 - 不会实际发布")
print(f" 📌 标题: {args.title}")
print(f" 📝 描述: {args.desc}")
print(f" 🖼️ 图片: {valid_images}")
print("\n✅ 验证通过,可以发布")
return
# 发布笔记
publish_note(
client=client,
title=args.title,
desc=args.desc,
images=valid_images,
is_private=args.private,
post_time=args.post_time
)
if __name__ == '__main__':
main()