xianyu-goofish-cli
极简的闲鱼(Goofish)只读 CLI:扫码登录 → 搜索商品 → 会话列表 → IM 实时流。
许可证 Apache-2.0。仓库:https://git.weisanju.fun/weisanju/xianyu-cli。
实现上刻意避开了两件最麻烦的事:
- 不自己复刻 mtop 签名/风控:搜索时用 Patchright 打开真实 Chrome,监听页面自己发出的
mtop.taobao.idlemtopsearch.pc.search响应,直接解析 JSON。 - 不逆向 IM 私有二进制:闲鱼 WebSocket 实际是 LWP(JSON)协议,
wss://wss-goofish.dingtalk.com/, 本 CLI 只做注册、心跳、ack 和解码。
本项目是非官方实现,仅用于个人学习与低频只读场景。请遵守闲鱼用户协议;账号风控、封号等后果自负。
安装
pip install xianyu-goofish-cli
patchright install chrome # 或直接使用系统 Chrome(channel="chrome")
从源码:
git clone https://git.weisanju.fun/weisanju/xianyu-cli.git
cd xianyu-cli
python -m venv .venv
source .venv/bin/activate
pip install -e .
需要本机有 Chrome/Chromium。
Linux 下有头模式默认优先走 Xvfb(等价于内置 xvfb-run 思路),以减少图形环境依赖。
CLI 会对异常终端尺寸环境变量(如 COLUMNS=131072)做清洗,减少“屏幕尺寸不真实”类提示对登录流程的干扰。
从本版本起,CLI 全部通过内置 server 调用:
- 默认 server 地址:
http://127.0.0.1:17357 - 若本地 server 不存在,CLI 会自动拉起并复用
- 启动时会检查本地 server
/health返回的version,若与当前 CLI 版本不一致会自动重启本地 server - 也可通过
--server/XIANYU_SERVER指向远程 server
使用
# 扫码登录:默认有头 Chrome 打开登录页,终端会在拿到二维码后立即渲染,PNG 存在 ~/.xianyu-cli/qr.png
# 若已有有效登录态会直接复用并跳过扫码;Linux 默认优先启用 Xvfb 有头模式
xianyu login
# 显式启动 server(可用于远程部署)
xianyu serve --host 127.0.0.1 --port 17357
# 强制重新扫码(忽略已缓存登录态)
xianyu login --force
# 关闭终端二维码渲染
xianyu login --no-render-qr
# 调小终端二维码(例如 28;仅图片渲染 fallback 时生效)
xianyu login --qr-width 28
# 机器可读:返回登录结果 + 二维码路径(尽力附带 png_base64)
xianyu login --json
# 检查登录态
xianyu whoami
# 搜索(默认无头;若命中风控会自动重试一次 --no-headless)
xianyu search "iPad Pro" --limit 10
xianyu search "相机" --pages 2 --json
# 筛选:价格区间 / 包邮 / 排除关键词 / 有原价(划线价)/ 排序
xianyu search "iPad Pro" --price-min 1000 --price-max 3500 --shipping free
xianyu search "相机" --exclude 配件 --sort price_asc --limit 20
xianyu search "显卡" --has-original-price --sort price_desc
# 指向远程 server
xianyu --server http://10.0.0.8:17357 search "相机" --limit 10
# 会话列表(支持区分私聊/非私聊;可按 cid 过滤)
xianyu chats --limit 50
xianyu chats --private --limit 50
xianyu chats --non-private --limit 50
xianyu chats --cid 1234567890
xianyu chats --json
# 实时监听私信 60 秒(可只看某个 cid)
xianyu watch --seconds 60
xianyu watch --seconds 60 --cid 1234567890
xianyu watch --seconds 60 --json
# 检查更新(只报告)/ 执行升级(pip 安装到当前解释器环境)
xianyu update --check
xianyu update --yes
# 给 AI agent 的用法说明:终端打印 SKILL.md
xianyu skill
xianyu skill --install # 写入 ~/.xianyu-cli/skills/xianyu/SKILL.md
xianyu skill --install ~/.claude/skills/xianyu # 写入指定目录的 SKILL.md
全局 --json 可用于所有命令。全局 --server 可切换到远程 server。
login --json 成功时会返回:
{
"logged_in": true,
"cookies": 12,
"qr": {
"path": "/home/you/.xianyu-cli/qr.png",
"png_base64": "iVBORw0KGgoAAA..."
}
}
其中 png_base64 为尽力返回(读取失败时可能不存在)。
CLI 默认优先用 Python 库 segno 根据二维码原文重渲染终端码(更易扫);若失败则回退 qrencode,最后回退到图片像素渲染。
login --json 时二维码渲染和提示信息会输出到 stderr,stdout 保持纯 JSON。
命令与退出码
| 命令 | 说明 |
|---|---|
login [--timeout N] [--no-headless] [--no-render-qr] [--qr-width N] [--force] |
扫码登录,保存 cookie + storage_state;默认优先复用有效登录态并跳过扫码,渲染时优先用 segno;--json 时返回二维码信息 |
whoami |
调用 loginuser.get 验证登录态 |
search <query> [--limit] [--pages] [--price-min] [--price-max] [--shipping any|free|no] [--exclude WORD] [--has-original-price] [--sort default|price_asc|price_desc] [--no-headless] |
拦截搜索响应并解析;筛选在 server 端对已抓取结果进行(先筛选再截断到 --limit) |
| `chats [--limit] [--private | --non-private] [--cid]` |
watch [--seconds] [--cid] |
IM WebSocket 实时事件,可只监听指定会话 CID |
update [--check] [--yes] |
读取 PyPI 上 xianyu-goofish-cli 的最新版本;默认只报告升级命令,--yes 才用当前 Python 执行 pip install --upgrade |
skill [--install [DIR]] |
打印给 AI agent 的用法说明(SKILL.md);--install [DIR] 写入 DIR/SKILL.md(默认 ~/.xianyu-cli/skills/xianyu/) |
serve [--host] [--port] |
启动 RPC server(CLI 默认会自动拉起本地 server) |
退出码:0 成功,1 普通错误,2 未登录/登录失效,3 风控拦截,130 Ctrl-C。
数据位置
~/.xianyu-cli/
cookies.json # 登录 cookie(0600)
profile/ # 扫码登录用的 Chrome profile
storage_state.json
qr.png # 最近一次登录二维码
device.json # IM 设备 ID(按账号固定)
im_token.json # IM accessToken 缓存(30 分钟)
可用 XIANYU_HOME 改根目录。
发布(维护者)
PyPI 分发包名是 xianyu-goofish-cli(xianyu-cli 已被占用),导入包仍为 xianyu_cli,命令为 xianyu。
- 仓库 Settings → Actions → Secrets 添加
PYPI_API_TOKEN(PyPI API token,scope 建议只限本项目)。 - 改
pyproject.toml里的version,提交后打同名 tag:
git tag v0.1.0
git push origin v0.1.0
.forgejo/workflows/release.yml 会校验 tag 与版本一致、构建 sdist/wheel、跑 twine check,再上传 PyPI。
本地手动发布等价命令:
python -m pip install --upgrade build twine
python -m build
TWINE_USERNAME=__token__ TWINE_PASSWORD=pypi-... python -m twine upload dist/*
已知限制
- 只读:v1 不提供发消息、发布、自动回复。
search依赖页面实际发出搜索请求;未登录/登录失效时页面会弹登录框,CLI 会报“未捕获到搜索响应”。- 二维码 canvas 被中心 logo 跨域污染,不能
toDataURL(),本实现用元素截图。 - 会话列表来自
session.sync,可能与 App 端不完全一致。 - IM 协议随时可能变化;
watch目前只处理文本/图片/已读/新消息通知。 - 高频请求会触发
RGV587,CLI 会直接报错退出,不做自动重试风暴。
参考与致谢
协议常量与解析思路参考了以下 Apache-2.0 / MIT 项目:
- fancyboi999/goofish-cli(Apache-2.0):浏览器拦截搜索响应、LWP 注册/ack、
session.sync字段。 - cv-cat/XianYuApis(MIT):IM WebSocket 与 mtop 常量。
- superboyyy/xianyu_spider:IM 解码思路。
本项目为独立实现,未复制上述项目的完整代码;详见 NOTICE。
Metadata
Release files for xianyu-goofish-cli 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| xianyu_goofish_cli-0.2.0.tar.gz | 44.0 kB | Without provenance | Details for xianyu_goofish_cli-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| xianyu_goofish_cli-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for xianyu_goofish_cli-0.2.0-py3-none-any.whl |
Total release size: 86.9 kB
Release files / xianyu_goofish_cli-0.2.0.tar.gz
| Download URL | xianyu_goofish_cli-0.2.0.tar.gz |
|---|---|
| Size | 44.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
29cf1619ea8edbf9df34d4760d64a1b3bedbe1574e85fe181316123854f4290c
|
|
BLAKE2b-256 checksum How to use checksums |
13b00b3c54a0bf67a65d8111be094c89bc71ea36875b0987275d6637e781c102
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / xianyu_goofish_cli-0.2.0-py3-none-any.whl
| Download URL | xianyu_goofish_cli-0.2.0-py3-none-any.whl |
|---|---|
| Size | 42.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
355f4dd3b315ceae66b38c79ff0935298cba30309e99166dbaa50dbc0035115e
|
|
BLAKE2b-256 checksum How to use checksums |
07d180fa359277f2d633da4c576ba413f1ab3036d0f57dd01a54108ede12d09b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Security for xianyu-goofish-cli 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.