微博 API 的纯异步客户端
Project description
weibo-cli
简洁的微博 API 异步客户端。类型安全,基于本地 Playwright profile 复用登录态。
安装
uv pip install -e .
uv run weibo-cli install-browser
install-browser 不再自动安装任何东西,只会打印手动安装提示。你需要自己执行:
uv pip install playwright
PLAYWRIGHT_DOWNLOAD_HOST=https://npmmirror.com/mirrors/playwright uv run playwright install chromium
uv run playwright install-deps
快速开始
首次使用前,先准备本地浏览器会话:
uv run weibo-cli login --cache-dir ~/.weibo-api/cache
登录成功后,正常 API 只读取本地导出的 Cookie:
import asyncio
from weibo_cli import WeiboClient
async def main():
async with WeiboClient(cache_dir="~/.weibo-api/cache") as client:
# 获取用户信息
user = await client.get_user("1749127163")
print(f"用户: {user.screen_name}")
# 获取用户微博
posts = await client.get_user_posts("1749127163", page=1)
print(f"微博数: {len(posts)}")
# 获取微博详情
post = await client.get_post("5226761046462968")
print(f"内容: {post.text}")
# 获取评论
comments = await client.get_post_comments("5226761046462968")
print(f"评论数: {len(comments)}")
# 获取好友圈时间线(每次都会先查 allGroups 再解析分组)
timeline = await client.get_group_timeline("互相关注", count=25)
print(f"好友圈微博数: {len(timeline)}")
asyncio.run(main())
浏览器会话与缓存目录
- 默认缓存目录是
~/.weibo-api/cache - 这个目录是单账号、单 profile 的本地真源
- 调用者如果想手动管理多个账号,直接传不同的
cache_dir即可 - 浏览器 profile 存在
cache_dir/profile/ - 导出的 HTTP Cookie 存在
cache_dir/export/cookie_header.txt - 库运行状态和刷新调度存在
cache_dir/state.json - 库自己的元数据存在
cache_dir/meta.json
会话生命周期
- 认证方式改为
Playwright persistent context - Cookie 来源是单向的:只从本地 Playwright profile 导出,不接受手工 Cookie 注入
- 用户手动在浏览器里登录微博,库只负责保存和复用浏览器状态
- 普通 API 请求只读取本地导出的 Cookie,不会在主请求路径里隐式访问 Hugging Face
cookie_ttl是成功登录/刷新后的固定刷新间隔;普通 API 使用只更新last_access_at,不会顺延next_refresh_at- 如果
state.json的next_refresh_at到期,请求前会触发一次 Playwright 刷新:打开weibo.com、等待页面加载、再探测微博 timeline 是否可访问 - 如果请求过程中遇到登录失效/验证码拦截,读接口会再触发一次 Playwright 刷新探测;如果 profile 已失效,则直接报错,不做自动登录
- 写接口不会在鉴权失败后自动重放,避免重复写入
backup push/pull会同步完整会话缓存:profile/、export/、meta.json、state.jsonlock/和archive/不会同步
常用命令
# 打印 Playwright/Chromium 手工安装提示
uv run weibo-cli install-browser
# 首次手动登录,初始化本地 profile
uv run weibo-cli login --cache-dir ~/.weibo-api/cache
# 复用现有 profile 刷新 Cookie
uv run weibo-cli refresh --cache-dir ~/.weibo-api/cache
# 查看本地缓存状态
uv run weibo-cli status --cache-dir ~/.weibo-api/cache
# 手动备份完整缓存到 Hugging Face Bucket
uv run weibo-cli backup push --cache-dir ~/.weibo-api/cache --token <token>
# 手动从 Hugging Face Bucket 恢复完整缓存
uv run weibo-cli backup pull --cache-dir ~/.weibo-api/cache --token <token>
API
WeiboClient
异步上下文管理器,自动处理连接生命周期。
async with WeiboClient(
config=None,
logger=None,
max_concurrent_requests=4,
requests_per_interval=10,
rate_interval_seconds=1.0,
cache_dir=None,
) as client:
...
参数
config:WeiboConfig实例,默认使用标准配置logger: 自定义 logger,默认使用模块 loggermax_concurrent_requests: 并发请求上限requests_per_interval: 每时间窗口的请求数上限rate_interval_seconds: 速率限制窗口(秒)rate_limiter: 传入自定义RateLimiter,覆盖默认策略cache_dir: 浏览器会话缓存目录,默认是~/.weibo-api/cache
会话方法
await get_cookies() -> str:返回当前导出的Cookie头,必要时会触发刷新await refresh_cookies() -> str:强制触发一次 Playwright 刷新并重新导出 Cookieawait validate_cookies() -> bool:验证当前导出的浏览器会话是否仍可访问微博 APIget_cached_cookies() -> str | None:只读返回当前缓存的 Cookie 头,不触发刷新await get_cookie_snapshot() -> dict[str, float | str | None]:返回当前会话快照信息
业务方法与实际接口
| 方法 | HTTP 接口 | 返回 | 说明 |
|---|---|---|---|
get_basic_info() |
GET /ajax/setting/getBasicInfo |
BasicInfo |
获取当前账号资料设置 |
get_user(user_id) |
GET /ajax/profile/info?uid=<user_id> |
User |
获取用户资料 |
get_user_posts(user_id, page=1) |
GET /ajax/statuses/mymblog?uid=<user_id>&page=<page> |
list[Post] |
获取用户微博时间线 |
get_groups() |
GET /ajax/feed/allGroups |
list[Group] |
获取好友圈/分组列表 |
get_group_timeline(group, count=25, refresh=4, fast_refresh=1) |
GET /ajax/feed/groupstimeline |
list[Post] |
获取指定分组时间线 |
get_post(post_id) |
GET /ajax/statuses/show?id=<post_id> |
Post |
获取微博详情 |
get_post_comments(post_id) |
GET /ajax/statuses/buildComments?...&id=<post_id> |
list[Comment] |
获取微博评论 |
get_mentions(page=1) |
GET /ajax/statuses/mentions?page=<page> |
list[Post] |
获取 @我 的微博列表 |
get_received_comments(page=1) |
GET /ajax/message/cmt?page=<page> |
list[Comment] |
获取收到的评论 |
upload_comment_image(image_path) |
POST https://picupload.weibo.com/interface/upload.php |
str |
上传评论图片并返回 pic_id |
reply_comment(post_id, comment_id, content, image_path=None, pic_id=None) |
POST /ajax/comments/reply |
CommentActionResult |
回复评论,可附图 |
post_comment(post_id, content, image_path=None, pic_id=None) |
POST /ajax/comments/create |
CommentActionResult |
发表评论,可附图 |
Playwright 刷新探针
- Playwright 刷新会先访问桌面首页(
config.api.home_url,默认是https://weibo.com/) - 页面加载后,再探测
GET /ajax/statuses/mymblog?uid=1642909335&page=1 - 只有探针返回
ok=1且 timeline 非空,才认为当前 profile 仍然有效
WeiboConfig
配置类,控制 HTTP、认证、API 行为。
from weibo_cli import WeiboConfig
# 默认配置
config = WeiboConfig()
# 快速配置(低延迟,低重试)
config = WeiboConfig.create_fast()
# 保守配置(高超时,高重试)
config = WeiboConfig.create_conservative()
配置字段
@dataclass
class WeiboConfig:
http: HttpConfig # HTTP 配置
auth: AuthConfig # 认证配置
api: ApiConfig # API 端点配置
HttpConfig
timeout: float = 10.0 # 请求超时(秒)
max_retries: int = 3 # 最大重试次数
base_delay: float = 1.0 # 基础延迟(秒)
max_delay: float = 60.0 # 最大延迟(秒)
max_connections: int = 20 # 最大连接数
max_keepalive_connections: int = 5 # 保持活跃连接数
AuthConfig
cookie_ttl: float = 1800.0 # 固定 Cookie 刷新间隔(秒),默认 30 分钟
ApiConfig
base_url: str = "https://weibo.com"
mobile_url: str = "https://m.weibo.cn"
user_agent: str = "Mozilla/5.0 ..."
数据模型
所有模型都基于 Pydantic v2 的 BaseModel,自动完成类型转换、校验与序列化。
User
from weibo_cli.models import User
user = User(
id=123,
screen_name="Test User",
profile_image_url="https://example.com/avatar.jpg",
followers_count=100,
)
# Pydantic API 同样可用
user_dict = user.model_dump()
Post
from datetime import datetime
from weibo_cli.models import Post, Image, Video
post = Post(
id=1,
created_at=datetime.utcnow(),
text="Hello Weibo",
user=user,
images=[Image(id="pic1", thumbnail_url="...", large_url="...", original_url="...")],
video=Video(duration=10.5, play_count=999),
reposts_count=1,
comments_count=2,
attitudes_count=3,
)
# 每个模型都带有 `raw` 字段,保存原始结构化 payload 的深拷贝快照
print(post.raw)
BasicInfo / Group / CommentActionResult
from weibo_cli import CommentActionResult, Group, WeiboClient
async with WeiboClient(cache_dir="~/.weibo-api/cache") as client:
info = await client.get_basic_info()
print(info.screen_name)
groups: list[Group] = await client.get_groups()
print(groups[0].name, groups[0].list_id)
result: CommentActionResult = await client.post_comment("5226761046462968", "Hello")
if result.comment is not None:
print(result.comment.id)
pic_id = await client.upload_comment_image("./comment.gif")
await client.post_comment("5226761046462968", "Hello with image", pic_id=pic_id)
await client.post_comment("5226761046462968", "Hello with image", image_path="./comment.gif")
upload_comment_image 使用微博网页端评论图上传接口。实测必需参数是
ent=miniblog 和按图片原始 bytes 计算的 cs=crc32(image_bytes);
ori=1 会保留,用于请求原图上传语义。
异常
from weibo_cli.exceptions import (
WeiboError, # 基础异常
AuthError, # 认证失败
NetworkError, # 网络错误
ParseError, # 解析错误
)
测试
uv run pytest -v
发布前清理
发布/打包前运行 scripts/prep_release.sh,脚本会:
- 执行
python -m compileall -q src tests,提前暴露语法错误 - 清理
__pycache__目录,确保工作区干净
bash scripts/prep_release.sh
验证会话导出
执行 weibo-cli refresh 后,可以直接检查本地导出文件:
uv run weibo-cli refresh --cache-dir ~/.weibo-api/cache
cat ~/.weibo-api/cache/export/cookie_header.txt
cat ~/.weibo-api/cache/state.json
如果导出成功,cookie_header.txt 会包含 SUB / SUBP 等微博登录 Cookie,state.json 会记录最近一次刷新、下次刷新和访问时间戳。
# 运行所有测试
uv run pytest -v
# 带覆盖率
uv run pytest --cov -v
架构
WeiboClient # Facade 入口
├── HttpClient # HTTP 请求
├── AuthProvider # 认证材料抽象
├── BrowserSessionManager# Playwright 持久浏览器会话
├── LocalCache # 本地 cache_dir 真源
├── RetryStrategy # 重试策略(指数退避)
├── UserParser # 用户数据解析
├── PostParser # 微博数据解析
└── CommentParser # 评论数据解析
设计原则:
- 单一职责:每个类只做一件事
- 组合优于堆叠:
WeiboClient只是把 HTTP、认证、解析串起来 - 无全局状态:线程安全
- 显式优于隐式:所有配置都可见
许可证
GNU Affero General Public License v3.0
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file weibo_cli-1.0.5.tar.gz.
File metadata
- Download URL: weibo_cli-1.0.5.tar.gz
- Upload date:
- Size: 72.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
adb0a17663ac710192dfc366bd6008a2e6f315d1cf3fea2748bb0f47c9daa8b3
|
|
| MD5 |
884e5ecd52a83105985bb390b743319e
|
|
| BLAKE2b-256 |
d57b6bacf59a49529d28f00d66c0db694f6951ffea04c79737e8cd0541e37cbb
|
File details
Details for the file weibo_cli-1.0.5-py3-none-any.whl.
File metadata
- Download URL: weibo_cli-1.0.5-py3-none-any.whl
- Upload date:
- Size: 62.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4b5618b8fc918c087eed4765e09cb7fc7da6e18cfdec313ed96c7d1418805aff
|
|
| MD5 |
6d7c1278f5e16c38202fc27fe7a6cfbb
|
|
| BLAKE2b-256 |
179c2371d5596d5c45a3ba3535279098b52fecc8fecc0f0c2f377f30ca97c293
|