闲鱼商品搜索采集
关键词 + 可选筛选 → 每页 30 条商品卡片(id、标题、价格、图片、所在地、想要人数)
语言约定
对用户的所有过程输出(进度提示、流程通知)跟随用户语言。
目标
从闲鱼关键词搜索结果页提取二手商品卡片,支持排序、价格区间、发布时间筛选,并逐页翻页采集。
前置条件
- 已打开闲鱼会话的浏览器(建议登录账号以获取完整结果)
- 目标页面已打开或即将打开:
https://www.goofish.com/search?q={关键词}
执行前检查
1. 工具就绪
若当前会话已确认浏览器自动化工具可用 → 跳过本步。
否则先确认浏览器自动化环境(如 browser-act / agent-browser / CDP 连接的浏览器)可用;若安装或配置有问题,按其指引解决后重试。
2. 登录核验
若当前会话已确认闲鱼登录状态 → 跳过本步。
否则打开 https://www.goofish.com/ 并观察页面:
- 出现用户头像或账号入口 → 已登录,继续
- 出现登录/注册提示 → 未登录;告知用户登录后才能获取完整结果,并协助登录
能力组件
本技能的操作边界 = 用户在浏览器里手动能做的事。只读取页面已展示给用户的数据。JS 代码封装在
scripts/目录的 Python 文件里,通过eval "$(python scripts/xxx.py {参数})"调用。$(...)是 bash 语法,建议用 bash 工具执行。
网络捕获:触发搜索并加载结果
搜索请求使用客户端计算的动态 sign 令牌——无法直接重构。导航到搜索 URL 即可自动触发 API。
navigate https://www.goofish.com/search?q={关键词}wait stable- 进入下方 DOM 提取
错误处理:若页面出现验证码滑块("请滑动验证")而非搜索结果,说明会话被限流。等待 5–10 分钟后重试,或换一个全新浏览器会话。
DOM:搜索结果商品卡片(数据提取)
导航并等待稳定后,提取当前页全部 30 张商品卡片:
eval "$(python scripts/extract-search-items.py)"
输出示例:
{
"items": [
{
"item_id": "1054668718340",
"category_id": "126862528",
"item_url": "https://www.goofish.com/item?id=1054668718340&categoryId=126862528",
"title": "美版iPhone 14 国行256G 纯原 原版原漆",
"image_url": "https://img.alicdn.com/bao/uploaded/...",
"price": "1810",
"service_tag": "Apple/苹果256GB无任何维修",
"price_desc": "2人想要",
"location": "广东"
}
],
"count": 30
}
DOM:应用排序与筛选(操作)
在提取前应用排序、发布时间筛选或价格区间。先调用本步,再运行 extract-search-items.py。调用后先 wait stable 再提取。
eval "$(python scripts/apply-search-filters.py --sort {排序} --publish-days {天数} --price-min {最低} --price-max {最高})"
参数:
--sort:排序选项——""默认(综合)、"reduce"新降价、"create"新发布、"price-asc"价格从低到高、"price-desc"价格从高到低。默认""--publish-days:按发布时间筛选——""全部、"1"1 天内、"3"3 天内、"7"7 天内、"14"14 天内。默认""--price-min:最低价(人民币整数串,如"500")。需与--price-max成对。默认""--price-max:最高价(人民币整数串,如"3000")。需与--price-min成对。默认""
输出示例:
{
"ok": true,
"applied": {
"sort": "reduce:desc",
"searchFilter": "publishDays:7;priceRange:500,3000;"
}
}
DOM:跳转到指定页(操作)
eval "$(python scripts/goto-page.py {页码})"
参数:
page_number:目标页码(整数,从 1 开始)
输出示例:
{ "ok": true, "clicked_page": 2 }
点击后 wait stable,再重跑 extract-search-items.py 获取新页商品。
枚举参数
[AI] 排序选项:""(综合/默认)、"reduce"(新降价)、"create"(新发布/最新)、"price-asc"(价格从低到高)、"price-desc"(价格从高到低)
[AI] 发布时间筛选:""(全部)、"1"、"3"、"7"、"14"
翻页
DOM 翻页:用 goto-page.py {页码} 点击目标页码按钮,wait stable 后重跑 extract-search-items.py。页码按钮出现在搜索结果底部的分页栏。
终止条件:当 goto-page.py 返回 error: Page N not found——没有更多页,或目标页超出分页栏显示范围(通常最多 25 页 / 750 条)。
成功标准
结果数 >= 1 且 item_id 非空率 = 100% 且 price 非空率 >= 80%
已知限制
- 每页固定 30 条(站点设定)
- 翻页最多可访问约 750 条(25 页 × 30)
- 搜索卡片中拿不到卖家用户名和用户 ID——只有卖家所在地
- 会话限流:大量搜索后快速访问详情页可能触发验证码滑块;缓解办法是页面导航之间加 1–2 秒延时
执行效率
- 批量编排:写 bash 脚本在同一会话内串行循环多个关键词;不要在单个浏览器里并行(容易触发反爬)。页面导航之间加 1–2 秒延时。要提升吞吐,可开多个隐身浏览器会话分流关键词
- 批量前先试跑:批量脚本写好后,先用 1–2 个关键词/页验证脚本正确,再跑全量
- 减少冗余前置操作:每个关键词导航一次,一次性应用全部筛选后再提取,不要多次导航
- 断点续采:批量处理时按关键词、按页保存结果;失败后从上次保存位置续采
经验记录
路径:{工作目录}/采集经验/xianyu-search-list.memory.md
执行前:若文件存在,先读一遍——里面记录了以往执行遇到的意外情况(如某策略已失效),据此调整策略顺序。
执行后:若遇到意外情况(策略失效、页面改版、反爬升级、发现更优路径),追加一行:
{YYYY-MM-DD}: {发生了什么} → {结论}
正常执行不写文件。不要记录用了哪些关键词、返回多少条——那些是任务输出,不是经验。
微信扫一扫