news 2026/10/11 18:14:00

闲鱼商品爬虫实战:从关键词监控到数据落库的工程化方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
闲鱼商品爬虫实战:从关键词监控到数据落库的工程化方案

简介:这份资源是面向计算机相关专业学生与Python爬虫初学者的一套闲鱼平台商品数据抓取实战项目,可作为课程设计、期末大作业或毕设参考,也适合想通过完整案例巩固爬虫与前后端联调能力的开发者。压缩包共28个文件,约9.33MB,以11个Python源码为核心,配合4个JSON配置、3个Markdown说明文档,以及Vue与JavaScript前端文件、HTML页面和少量图标、截图等静态资源,整体结构覆盖后端接口、前端展示与项目说明。项目基于FastAPI与Vue搭建,围绕二手商品数据的采集与可视化展开,目录划分清晰,便于按模块阅读与二次修改。目前已有222人学习下载,说明其具备一定参考价值。对于需要快速搭建爬虫项目框架、理解数据抓取到可视化完整链路的读者,可从中获取可运行的代码结构、依赖配置与说明文档,并借助作者答疑解决开发中的具体问题。

1. 闲鱼商品爬虫到底抓什么:从关键词监控到数据落库的真实链路

做闲鱼关键词监控的人,十有八九一开始都以为「爬虫」就是 requests 加个循环。真上手才发现,闲鱼 PC 端和 App 端的数据根本不是静态 HTML,搜索页、详情页、卖家主页各自走不同的接口,返回结构还随版本变。这个标题里的「闲鱼商品爬虫-xianyu平台数据抓取」,本质是一套围绕商品维度做采集、清洗、入库的工程方案,核心产出是结构化的商品数据:标题、价格、发布时间、卖家 ID、想要人数、浏览量、商品状态。它解决的是「人工刷闲鱼找货、盯价格、追竞品」的低效问题,适合做二手电商选品、价格监控、竞品分析、关键词预警的从业者。新手能照着把最小链路跑通,熟手更该关注的是频率控制、字段稳定性和长期可维护性——这三样决定你的爬虫是能跑一周还是能跑一年。

2. 抓取链路拆解:从搜索入口到商品详情的四段式设计

2.1 为什么不能只抓搜索页,必须补详情页

搜索列表接口返回的字段通常只有商品 ID、标题、价格区间、封面图和「想要」数,缺发布时间、卖家信用、商品描述、图片列表这些做选品判断的关键信息。只抓列表,你拿到的是一堆「看起来便宜」的标题,没法判断是不是钓鱼价、是不是已售、卖家靠不靠谱。所以标准链路是四段:关键词搜索拿 ID 列表 → 详情接口补全字段 → 卖家维度做去重和信誉聚合 → 落库打时间戳做价格追踪。这个设计的好处是每段可独立重试,搜索页挂了不影响已拿到的 ID 继续补详情。

2.2 请求头与签名参数:最容易被忽略的翻车点

闲鱼接口对请求头敏感,尤其是User-Agent、Referer、Cookie里的登录态字段。很多新手直接拿浏览器复制的 cURL 跑,第一次成功,跑几十次就返回空数据或跳验证。常见做法是把移动端 UA 固定下来,Referer 指向对应商品或搜索页,Cookie 定期更新。签名参数(如sign、t、appKey)随接口版本变化,不要硬编码,抽成独立函数方便替换。

import requests, time, random HEADERS = { "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) " "AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148", "Referer": "https://www.goofish.com/", "Accept": "application/json", } def fetch(url, params, cookie): headers = dict(HEADERS) headers["Cookie"] = cookie # 每次请求间隔随机化,降低被识别为机器的概率 time.sleep(random.uniform(1.5, 3.5)) resp = requests.get(url, headers=headers, params=params, timeout=10) if resp.status_code != 200: raise RuntimeError(f"HTTP {resp.status_code}") return resp.json()

这段代码的关键点有三个:UA 用移动端而非桌面端,Referer 必须和请求的资源同域,sleep 用随机区间而不是固定值。参数timeout=10防止卡死,cookie作为参数传入而不是写死,方便后续接 Cookie 池。失败时先看状态码,403 多半是头或签名问题,200 但返回空 data 通常是频率触发或登录态失效。

2.3 分页与去重:用商品 ID 做主键

搜索接口一般用page或offset翻页,但闲鱼的结果排序会随时间和个性化变化,同一关键词两次翻页可能拿到重复或遗漏。稳妥做法是每页都记录商品 ID,用集合去重,翻到连续两页无新 ID 就停。入库时以商品 ID 为唯一键,用 upsert 更新价格和状态,这样同一商品多次出现只保留最新快照,历史价格另存一张表。

seen = set() def crawl_keyword(keyword, max_page=20): for page in range(1, max_page + 1): data = fetch(SEARCH_URL, {"q": keyword, "page": page}, COOKIE) items = data.get("data", {}).get("items", []) if not items: break new_count = 0 for it in items: gid = it["itemId"] if gid in seen: continue seen.add(gid) new_count += 1 yield gid # 连续无新增说明结果已翻到底或触发限制 if new_count == 0: break

max_page是保护性上限,避免死循环;new_count判断比单纯看items是否为空更可靠,因为闲鱼有时会返回重复页。yield让抓取和入库解耦,后面可以接队列做分布式。

2.4 字段清洗:价格和时间的坑最多

价格字段可能是「¥100」「100元」「面议」,时间可能是「刚刚」「3小时前」「2024-05-01」。清洗时统一转成数值和时间戳,无法解析的标记为 None 而不是丢弃整条记录。卖家 ID 要做脱敏存储,只保留哈希值用于聚合,避免原始信息泄露。

原始字段问题处理方式
price含符号、单位、面议正则提取数字,面议置 None
publish_time相对时间按抓取时间反推绝对时间
want_count可能是「1万+」解析为数值,万乘 10000
seller_id敏感SHA256 后存储

3. 工程化落地:存储、调度与反爬对抗的取舍

3.1 存储选型:SQLite 起步,PostgreSQL 收尾

个人做关键词监控,SQLite 足够跑几个月,单文件、零配置、方便迁移。数据量上到百万级或要做多关键词并发写入,换 PostgreSQL,用ON CONFLICT做 upsert,配合时间分区表存价格历史。MySQL 也行,但 JSON 字段处理不如 PG 顺手。表结构至少两张:items存商品最新状态,price_history存每次抓到的价格快照。

CREATE TABLE items ( item_id TEXT PRIMARY KEY, title TEXT, price NUMERIC, seller_hash TEXT, status TEXT, first_seen TIMESTAMP, last_seen TIMESTAMP ); CREATE TABLE price_history ( item_id TEXT, price NUMERIC, seen_at TIMESTAMP, PRIMARY KEY (item_id, seen_at) );

item_id做主键保证幂等,seller_hash用于按卖家聚合,status记录在售/已售,first_seen和last_seen能算出商品存活周期,这对判断「是不是长期挂着的钓鱼价」很有用。

3.2 调度频率:别把「稳定」理解成越快越好

很多人问爬虫多久跑一次合适。我的血泪经验是:单关键词 10 到 15 分钟一轮,全天不超过 100 轮,夜间降到 30 分钟一轮。频率越高,触发验证的概率越大,维护成本指数上升。用 APScheduler 或系统 cron 都行,关键是加随机抖动,别整点整分跑。

from apscheduler.schedulers.blocking import BlockingScheduler import random sched = BlockingScheduler() @sched.scheduled_job("interval", minutes=15) def job(): # 抖动 0-5 分钟,打散请求峰值 time.sleep(random.uniform(0, 300)) for kw in KEYWORDS: for gid in crawl_keyword(kw): save_item(gid) sched.start()

interval=15是基准,抖动让实际间隔在 15 到 20 分钟之间浮动。关键词多的时候串行跑,别开线程池猛冲,串行反而更稳。

3.3 反爬对抗的边界:哪些能做,哪些别碰

能做的:换 UA、加 Referer、控制频率、Cookie 池轮换、失败重试退避。别碰的:破解验证码、模拟登录批量养号、高频压测式抓取。前者是工程优化,后者既不稳定也不可持续。遇到验证页就停,记录时间点,等一段时间再试,比硬刚划算。分布式爬虫听起来高级,但对闲鱼这种强登录态的场景,多 IP 不如多 Cookie,且 Cookie 质量比数量重要。

4. 避坑与排查:五个真实踩过的坑

4.1 现象:第一次跑通,第二次全空

原因:Cookie 或签名参数有时效,浏览器复制的 cURL 里的t和sign只对当次有效。解决:把签名逻辑抽成函数,每次请求重新生成;Cookie 单独维护,失效时手动更新或接刷新流程。

4.2 现象:价格抓回来全是「面议」

原因:搜索列表页的价格字段和详情页不一致,列表页对部分商品只给占位符。解决:以详情接口为准,列表页价格仅作初筛,入库前用详情数据覆盖。

4.3 现象:翻页到第 5 页后全是重复

原因:闲鱼搜索结果的个性化排序导致翻页不稳定,page参数在深页失效。解决:改用offset或时间游标,或者只抓前 3 页高频结果,深页用关键词变体覆盖。

4.4 现象:跑一晚上被封,第二天全 403

原因:固定间隔 + 固定 UA + 无重试退避,被识别为机器。解决:随机 sleep、UA 池、失败后指数退避(1s、2s、4s、8s),连续失败 5 次停 30 分钟。

4.5 现象:数据库里同一商品几十条记录

原因:没用唯一键,每次插入新行。解决:item_id做主键,用 upsert 更新,价格历史单独表按时间追加。

5. 进阶技巧:用价格历史做关键词预警

跑通基础链路后,真正有价值的是价格历史带来的预警能力。我的习惯是每天凌晨跑一次全量关键词,把价格变动超过 15% 的商品挑出来,推送到自己的通知渠道。实现上不复杂:查price_history里同一item_id最近两条记录,算变动率,超阈值就触发。

def detect_price_drop(conn, threshold=0.15): sql = """ SELECT item_id, price, LAG(price) OVER (PARTITION BY item_id ORDER BY seen_at) AS prev_price FROM price_history """ rows = conn.execute(sql).fetchall() alerts = [] for item_id, price, prev in rows: if prev and prev > 0: change = (price - prev) / prev if abs(change) >= threshold: alerts.append((item_id, prev, price, change)) return alerts

LAG窗口函数拿上一条价格,threshold=0.15是经验值,二手商品波动大,设太低会天天报警。abs(change)同时抓涨价和降价,涨价有时意味着同款稀缺,也是信号。验证方法很简单:手动找几个你关注的商品,看预警是否和实际吻合,跑一周调阈值。

另一个技巧是给关键词分组,比如「相机」「镜头」「配件」分开跑,每组独立频率和阈值。相机类更新慢,30 分钟一轮够;配件类上新快,10 分钟一轮。这样资源花在刀刃上,也不容易触发限制。

最后说个我自己的教训:别追求一次抓全,先让一条链路稳定跑两周,再扩关键词和字段。我最早贪多,一次上二十个关键词,结果第三天全挂,排查花了两天。后来改成一次加两个,稳定了再加,反而省时间。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/11 18:13:57

双NVMe硬盘装Windows 11与Ubuntu双系统:引导隔离与GRUB美化教程

现在的笔记本,基本都是两个M.2接口起步,但很多人在装双系统时还是沿用“一块盘上分区分出两个系统”的老思路,结果Windows和Ubuntu互相踩脚,引导崩了都不知道去哪儿修。我这次趁着升级硬盘,直接采用了双NVMe硬盘方案&a…

作者头像 李华
网站建设 2026/10/11 18:12:39

工控机 Mini PCIe 无线模块部署实践:Wi-Fi 7 双频并发与射频规划

在工控机上集成 Wi-Fi 7 无线能力,模块选型与射频规划是两条主线。本文以一款 Mini PCIe 双频并发 Wi-Fi 7 模块(QCN6224 平台,型号 WLE7002E25)为例,梳理组网架构、核心机制与射频指标,供做工业无线集成的…

作者头像 李华
网站建设 2026/10/11 18:12:39

虚拟机驱动安装全指南:从VMware Tools到内核模块与USB透传

1. 项目背景:虚拟机里的“驱动安装”到底在装什么 先说个很多同学容易误解的地方。我给不少高校的实验机房维护过环境,每次给虚拟机装驱动,总有人问:“虚拟机里的网卡、显卡不都是虚拟出来的吗,为什么还要装驱动&#…

作者头像 李华
网站建设 2026/10/11 18:08:29

ITOM和ITSM有什么区别?运维监控与服务管理如何配合

ITOM(IT Operations Management,IT运营管理)关注的是"基础设施和应用是否健康运行",通过监控、告警、自动化运维等手段保障系统本身;ITSM(IT服务管理)关注的是"IT服务如何被交付…

作者头像 李华
网站建设 2026/10/11 18:07:12

MySQL学习笔记 04、MySQL进阶(索引、事务、锁)

文章目录 前言 一、MySQL的目录结构 1.1、认识目录文件 1.2、配置文件设置 windows平台下设置 linux环境下设置 二、MySQL的系统架构 2.1、MySQL系统的逻辑架构: 2.2、MySQL系统架构(包含每个部分介绍) 2.3、MySQL的查询过程 三、学习I/O原理以及数据库选型 3.1、学习计算机硬…

作者头像 李华
网站建设 2026/10/11 18:05:52

Windows Server 2019下Oracle 11g与19c安装部署及客户端配置实践

简介:Windows Server 2019 环境下 Oracle 数据库的部署常让不少运维新手头疼,这份图文文档正好补上了从零到可用的关键环节。与常见仅讲解 Linux 平台的教程不同,它完整走通了 Windows Server 2019 系统安装、磁盘分区、管理员初始化等前置环…

作者头像 李华