用 pyxianyu 打通闲鱼商品、搜索、消息能力
GitHub 仓库:DoLovya/pyxianyu
前言:闲鱼自动化先别急着写业务,先把签名、登录态和接口入口封稳定。
一、问题
直接调闲鱼 Web 端接口,基本都会卡在这 3 个点:
- 请求参数里有
sign,不能裸调 - Cookie 会刷新,常驻进程容易失效
- 商品、搜索、消息能力分散,业务代码很快写乱
目标:做一个可复用的 Python 库,把签名、请求、鉴权、业务 API统一起来。
二、方案
1. 统一签名和请求
所有业务 API 都走同一套签名链路,这层一定先收口。
importtimeimportrequestsfrompyxianyu.utils.xianyu_utilsimportgenerate_signclassXianyuClient:def__init__(self,cookies,device_id):self.session=requests.Session()self.session.cookies.update(cookies)# 登录态注入self.device_id=device_iddefbuild_mtop_params(self,api):return{"jsv":"2.7.2","appKey":"34839810","t":str(int(time.time())*1000),"sign":"","api":api,"type":"originaljson","dataType":"json",}defbuild_signed_form(self,params,data_val):token=self.session.cookies.get("_m_h5_tk","").split("_")[0]params["sign"]=generate_sign(params["t"],token,data_val)# 生成 signreturn{"data":data_val}defensure_api_success(self,payload):ret=payload.get("ret")or[]ifretandnotret[0].startswith("SUCCESS"):raiseRuntimeError(ret[0])# 统一失败出口returnpayload后面所有接口只管组装data,不用重复处理签名和异常。
2. 业务 API 模块化
登录态、商品、搜索、媒体分模块,对外只暴露一个入口。
classXianyuApis:def__init__(self,cookies,device_id):self.client=XianyuClient(cookies,device_id)self.auth_api=AuthApi(self.client)self.item_api=ItemApi(self.client)self.search_api=SearchApi(self.client)defget_token(self):returnself.auth_api.get_token()defget_item_info(self,item_id):returnself.item_api.get_item_info(item_id)defsearch_items(self,keyword,page_number=1,rows_per_page=20):returnself.search_api.search_items(keyword,page_number=page_number,rows_per_page=rows_per_page)调用层只面向XianyuApis,不用关心底层 URL 和签名细节。
3. 先安装再调用
1.0.0版本开始,对外入口已经统一为xianyu命名,直接安装即可。
# 方式1:安装正式版pipinstall-Upyxianyu# 方式2:uv 安装uv pipinstall-Upyxianyu如果你是本地调试仓库源码,也可以直接安装当前项目:
cdthird_party/pyxianyu pipinstall-e.环境变量准备:
exportXIANYU_COOKIE='你的完整Cookie'可直接运行的示例:
importosfrompyxianyu.xianyu_apisimportXianyuApisfrompyxianyu.utils.xianyu_utilsimportgenerate_device_id,trans_cookiesdefmain():cookie_str=os.environ["XIANYU_COOKIE"]# 完整 Cookiecookies=trans_cookies(cookie_str)user_id=cookies.get("unb","0")# 从 Cookie 中拿当前用户标识device_id=generate_device_id(user_id)api=XianyuApis(cookies,device_id)token_result=api.get_token()nav_result=api.get_user_page_nav()print("token ok:",bool(token_result.get("data")))print(nav_result)# 直接看接口原始返回if__name__=="__main__":main()运行方式:
python demo.py这个示例只依赖XIANYU_COOKIE,更适合先验证登录态和基础调用链路;如果字段结构有变化,先看print(nav_result)的原始结果最稳。
完整功能清单:
| 模块 | 功能 | 方法 |
|---|---|---|
| 鉴权 | 获取登录 token | get_token() |
| 鉴权 | 刷新登录态 | refresh_token() |
| 商品 | 获取商品详情 | get_item_info(item_id) |
| 商品 | 获取用户商品分页列表 | get_user_items(user_id, ...) |
| 商品 | 自动翻页拉取全部商品 | get_all_user_items(user_id, page_size=20) |
| 商品 | 下架商品 | downshelf_item(item_id) |
| 商品 | 发布前校验 | prepublish_check(item_id=None) |
| 商品 | 获取发布/编辑预置参数 | preget(item_id=None, source_id=None, publish_scene=None, bizcode=None) |
| 商品 | 获取商品编辑详情 | get_item_edit_detail(item_id) |
| 商品 | 编辑商品 | edit_item(payload) |
| 商品 | 发布全新商品 | publish_item(payload) |
| 商品 | 构造重新上架 payload | build_reshelf_payload(edit_detail_result, item_id=None, source_id=None) |
| 商品 | 一步重新上架商品 | reshelf_item(item_id, source_id=None) |
| 搜索 | 按关键词搜索商品 | search_items(keyword, page_number=1, rows_per_page=20, ...) |
| 用户 | 获取当前登录用户信息 | get_user_page_nav() |
| 媒体 | 上传图片/视频/音频 | upload_media(media_path) |
| 消息 | 创建单聊会话 | create_chat(ws, toid, item_id) |
| 消息 | 发送文本/图片消息 | send_msg(ws, cid, toid, message) |
| 消息 | 单次发送消息 | send_msg_once(toid, item_id, send_message) |
| 消息 | 拉取指定会话历史消息 | list_all_conversations(cid) |
| 消息 | WebSocket 初始化注册 | init(ws) |
| 消息 | 心跳保活 | heart_beat(ws) |
| 消息 | HTTP 登录态保活 | user_alive() |
| 消息 | 启动消息监听主循环 | main() |
| 消息 | 处理收到的消息 | handle_message(message, websocket) |
| 消息类型 | 构造文本消息 | make_text(text) |
| 消息类型 | 构造图片消息 | make_image(url, width=0, height=0) |
| 消息类型 | 构造音频消息 | make_audio(url, duration_ms=0) |
如果只想记住一件事,XianyuApis负责 HTTP 能力聚合,XianyuLive负责 WebSocket 消息收发。
三、踩坑
- ⚠️
sign依赖_m_h5_tk,Cookie 缺这个字段就会直接失败。 - ⚠️
get_token()要限制重试次数,别把“令牌过期”写成死循环。 - ⚠️ 编辑商品时部分布尔值是字符串,提交前要先归一化。
- ⚠️
XIANYU_COOKIE走环境变量,别写死在代码里。
四、总结
pyxianyu先解决的是签名、请求、鉴权,不是先堆接口数量。- 模块拆开,对外聚合成
XianyuApis,业务代码会干净很多。 - 底层库先封稳,后面接 MCP、机器人、运营脚本才省事。