ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

shopee_crawler 0.1.2实战:Python爬虫稳定采集Shopee商品数据

shopee_crawler 0.1.2实战:Python爬虫稳定采集Shopee商品数据 简介这是一份面向 Python 爬虫开发者与电商数据分析师的轻量级爬虫库 Shopee Crawler版本 0.1.2。它基于 Shopee 平台商品抓取场景封装了爬虫主逻辑、工具函数与模块初始化配置可用于商品列表、详情、关键词等数据的定向采集也可作为电商爬虫框架的参考样例。资源包共包含 16 个文件以 Python 源码为核心8 个 .py 文件配合 4 个文本说明、2 个包元数据文件、1 个 Markdown 文档和 1 个配置文件整体体积仅 4KB结构非常精简。核心源码覆盖爬虫入口、抓取流程及辅助工具配置文件与包元数据便于安装分发文档可帮助快速上手。目前已有 609 人学习下载适合希望快速掌握电商爬虫实现、或需要参考轻量级爬虫封装思路的初中级 Python 开发者拿到后可直接阅读源码、二次修改并应用于自身数据采集项目。1. 用 shopee_crawler 0.1.2 之前先知道它解决什么问题做电商数据分析、竞品比价或者选品调研时Shopee 平台上的商品标题、价格、销量、评价散落在页面各处手工复制撑不过几十条。shopee_crawler 就是为这个场景准备的一组 Python 工具库0.1.2 版本以 tar.gz 源码包形式分发安装后提供搜索、详情、评价等采集入口。这篇会从解压安装开始走到请求封装与参数解析最后给出一套限速、重试和断点续爬的稳定性方案。适合刚接触爬虫的 Python 开发者也适合需要把采集任务长期跑下去的工程师。重点不是直接拿到现成数据而是理解这个库在请求、解析、容错上替我们做了什么。2. 把 shopee_crawler-0.1.2.tar.gz 解压装进 Python 环境2.1 从下载目录到 site-packagestar.gz 的三种安装路径Linux 下最常见的安装报错是路径打错终端直接提示tar.gz没有那个文件或目录。shell 里逐字敲版本号时0.1.2 很容易被看成 0.1.20或者 cd 进了解压目录但文件名不匹配。我一般先执行ls -l shopee_crawler*确认实际文件名再决定用哪种方式安装。# 方式一先解压再手动安装 tar -xzf shopee_crawler-0.1.2.tar.gz cd shopee_crawler-0.1.2 python setup.py install # 方式二跳过手动解压pip 直接消费压缩包 pip install ./shopee_crawler-0.1.2.tar.gz # 方式三解压后以可编辑模式安装便于边读源码边改 pip install -e ./shopee_crawler-0.1.2三种方式的差别在可维护性。方式一是老派做法适合想在 setup.py 里确认依赖清单的环境方式二最省事pip 会先解压再执行构建日常使用首选方式三的-e表示 editable 模式源码改动立即生效适合要二次开发这个库的人。无论选哪种装完都要验证包是否真正进入当前环境。python -c import shopee_crawler; print(shopee_crawler.__version__)输出 0.1.2 才算成功。这里有个高频坑如果 shell 还停留在解压出来的源码目录import优先命中当前目录测的是源码而不是已安装的包建议切到 /tmp 或任意空目录再验证。Python 版本方面0.1.2 这类早期库通常要求 3.7 以上建了虚拟环境就必须先激活再装否则包落进系统环境依赖隔离形同虚设。对照常见 python 安装教程里的习惯爬虫项目最好单独建 venv不要和开发机上的其他项目共用解释器。2.2 setup.py 里藏着的依赖与元信息解压后先别急着执行安装打开shopee_crawler-0.1.2/setup.py看 install_requires 列表。这个列表直接决定运行环境还缺哪些包。CPU 密集的解析任务常用 lxml轻量抓取用 requests某些反爬场景可能还需要 curl_cffi 一类能模拟浏览器指纹的请求库。# setup.py 常见结构以实际包为准 from setuptools import setup, find_packages setup( nameshopee_crawler, version0.1.2, packagesfind_packages(wheresrc), install_requires[ requests2.28, beautifulsoup44.11, lxml4.9, ], python_requires3.7, )packagesfind_packages(wheresrc)表示源码采用 src 目录布局安装时会把 src 下的包复制到 site-packages。install_requires 里的版本下限是硬约束系统已有 requests 2.20 时pip 会自动升级到满足条件的版本如果某些包和公司内部源冲突安装就会停下来报错。依赖与用途对应关系可以按下面这张表排查。依赖包用途缺失时的典型报错requests发起 HTTP 请求ModuleNotFoundError: requestsbeautifulsoup4解析 HTML 页面片段No module named bs4lxml加速 HTML/XML 解析ImportError: lxml not found看明白这一步后面遇到 ImportError 就知道先去查依赖版本而不是反复重装主包。0.1.2 是早期版本依赖写得往往偏保守项目里已有更高版本时通常可以直接复用不用降级。2.3 目录结构请求、解析、工具三层各管一段进入 src 目录后通常会看到 crawlers、parsers、utils 三个子目录。crawlers 负责发请求parsers 负责从 HTML 或 JSON 里抽字段utils 负责写文件、格式化时间这类杂活。理解这个分层对后续调参很重要改请求头在 crawlers 里改字段提取在 parsers 里改输出路径在 utils 里不要拿着文件全局搜。我习惯先跑一次python -m shopee_crawler --help看有没有 CLI 入口。0.x 版本很多库只提供 Python API没有命令行工具这时就去 README 找示例代码。0.1.2 这个版本号意味着接口可能还在变化示例里的函数签名务必以实际安装包为准遇到TypeError: unexpected keyword argument时就去查源码签名不是示例写错是版本已经动了。提示pip 安装后找不到包优先执行pip show shopee_crawler看 Location 字段确认它落在当前虚拟环境的 site-packages 里。3. shopee_crawler 的请求封装与商品 URL 参数解析3.1 为什么直接请求 HTML 不如调 API 端点稳定在浏览器里翻 Shopee 商品页拿到的是渲染后的 HTML里面夹着大量脚本、样式和埋点字段解析成本高页面一改版就全挂。处理这类电商平台时我优先找页面背后真正返回数据的接口通常是 JSON字段稳定、体积小、层级路径可预测。shopee_crawler 的设计思路也在这个方向它把 URL 拼装逻辑收敛到 crawlers 模块对外暴露参数化方法。from shopee_crawler.crawlers import SearchCrawler crawler SearchCrawler() items crawler.search(keywordwireless earphone, limit50)这句调用背后至少做了三件事拼接带查询参数的 URL、携带浏览器特征的请求头、把返回内容按统一结构交还给调用方。所以用这个库时不要绕过封装自己用 requests.get直接调方法才能享受到超时、重试这些内置行为。同步 for 循环适合先把链路跑通采集量上去之后再考虑协程或者多进程分片那是另一层优化。3.2 关键请求参数keyword、limit、page 与 shopidsearch 方法内部会构造类似下面的请求参数名是常见实现具体以库源码为准。理解每个字段的含义调参才有的放矢不至于对着翻页数据发愣。params { keyword: keyword, limit: limit, page: page, sort: sort, by: relevancy, } headers { user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64), referer: https://shopee.sg/, } response requests.get( https://shopee.sg/api/v4/search/search_items, paramsparams, headersheaders, timeout10, )参数说明集中在下面这张表方便对照修改。参数常见取值作用keyword字符串URL 自动编码搜索关键词核心过滤条件limit10 / 20 / 50单页返回条数过大可能被拒绝page从 0 开始的整数分页游标配合 limit 翻页sortrelevancy / sales / price排序方式运营看爆款常用 salesbyrelevancy / ctime配合 sort 使用的排序依据limit 和 page 必须成对出现每翻一页 page 加 1limit 保持不变。新手只调 limit 不调 page就会反复拿到第一页的重复数据看起来像是抓取 bug其实是分页参数没接上。网络请求要带 timeout10 秒是合理起步值被限流时响应变慢提到 15 秒可以但不建议超过 30否则单个慢请求会拖垮整轮采集的节奏。注意limit 设为 100 不代表一定返回 100 条服务端有最大上限超限时以实际返回条数为准。3.3 解析层为什么比正则稳商品列表 JSON 的字段层级比较深例如data.items[i].item_basic.name存商品名price 字段通常按分存储而不是元。shopee_crawler 的 parsers 模块把这些路径封装成方法外部拿到的已经是整理好的 dict业务代码里就不用到处写[data][items][0]这种脆弱索引。from shopee_crawler.parsers import parse_search_items raw crawler.search(smart watch, limit20) parsed parse_search_items(raw) print(parsed[0][name], parsed[0][price])如果解析层输出 dataclass字段会带类型提示写起来更安心。遇到解析结果为空先检查原始返回是不是登录墙或验证码页面这一步用库内置的 response 文本日志确认比在 UI 上瞎猜有效得多。另外要注意解析层不负责重试网络层的重试在 crawlers 里配置两块逻辑别混在一起否则排错时无从下手。4. 用 shopee_crawler 抓商品搜索与详情的最小可行代码4.1 搭一个能跑通的主流程前两章把安装和原理讲完这里给一个能直接落盘的最小脚本。假定已按第二章装好包把下面代码保存为run_demo.py在虚拟环境里执行。import json from shopee_crawler.crawlers import SearchCrawler, DetailCrawler from shopee_crawler.parsers import parse_search_items, parse_detail def main(): # 搜索阶段抓前 3 页每页 20 条 search SearchCrawler() all_items [] for page in range(3): raw search.search(phone grip, limit20, pagepage) all_items.extend(parse_search_items(raw)) # 详情阶段取前 5 个商品抓详情 detail DetailCrawler() details [] for item in all_items[:5]: d detail.get(item[shopid], item[itemid]) details.append(parse_detail(d)) with open(output.json, w, encodingutf-8) as f: json.dump({search_count: len(all_items), details: details}, f, ensure_asciiFalse, indent2) print(fdone: {len(all_items)} search items, {len(details)} details) if __name__ __main__: main()代码里SearchCrawler.search返回原始响应parse_search_items把商品列表解析成结构化数据可以安全地取item[shopid]和item[itemid]。detail 方法用这两个 ID 作为商品唯一标识这是电商数据去重的关键。page 从 0 到 2 是为了演示多页抓取真实任务里翻页深度建议用配置文件控制不要写死在脚本里。同步循环在这里是有意的先确认每一步的结果再考虑并发避免一上来就把请求频率拉满。4.2 商品详情与评价的字段取舍详情接口的字段远多于搜索列表完整标题、分类路径、库存、销量、历史价格、店铺信息都有。如果全量落盘一天跑几万条就会膨胀出大量无用字段后续清洗反而更费时间。我一般只挑关键字段按分析目标裁剪下面是一份可直接用的切片。detail_slice { itemid: d[itemid], name: d[name], price: d[price], historical_sold: d[historical_sold], stock: d[stock], rating_star: d[rating_star], categories: d.get(categories, []), }price 从分转成元就在这一步处理保留两位小数categories 用get加默认空列表避免个别商品缺字段时抛 KeyError。评价数据一般走独立接口字段包括评分、评价文本、图片、追评内容文本适合做情感分析评分适合做质量统计。这两类建议分文件落盘不要混进商品主表评价是随时间增长的数据和商品快照的更新频率完全不一样。4.3 落盘格式JSON 还是 CSV商品详情是嵌套结构categories 是列表存 CSV 要么拍平、要么用分隔符拼都很别扭。我的原则是原始全量数据用 JSON 存档用于二次分析字段少、结构平的评价数据用 CSV方便 Excel 直接打开。两类文件用同一时间前缀命名按采集轮次对齐。python run_demo.py ls -lh *.json *.csv跑完先看输出文件大小。search_count 远小于预期优先检查网络是否稳定details 为空多半是 shopid 和 itemid 的类型不对回第三章节把参数类型对齐。示例里的 print 只是演示正式任务建议换 logging 模块把每轮抓取时间、条数、失败数量记录下来后面调限速参数时这些日志就是判断依据。CSV 落盘记得指定encodingutf-8-sig否则数据里有中文时Windows 上的 Excel 打开会乱码。5. shopee_crawler 的稳定性控制限速、重试与断点续爬5.1 用一个任务类把限速做进去爬虫跑到第 2000 条时被限流比解析报错更难排查。shopee_crawler 的封装不会帮你做等待这部分逻辑必须放在业务层。常见做法是循环里按随机间隔休眠固定间隔容易被识别成脚本行为。import time, random for page in range(10): raw search.search(phone grip, limit20, pagepage) time.sleep(random.uniform(2.0, 5.0))随机区间的上限不要拉太大1 到 30 秒的跨度会让整个任务慢到无法接受。配合重试机制返回内容为空或状态码不是 200 时暂停 60 秒再重试连续失败 3 次就放弃当前页记录到失败清单。5.2 断点续爬的落盘策略整批任务中断后从零开始抓既浪费配额又浪费时间。断点续爬的核心是记录已完成页码或 itemid启动时跳过已处理的部分状态记录方式如下。记录内容作用更新时机page 游标重入搜索循环每页成功后itemid 集合跳过已抓详情每次详情落盘后时间戳评估采集耗时每批结束后已完成的 itemid 写进done.txt每行一个 ID启动脚本时读成 set详情请求前先判断 ID 是否在集合中。任务中断后重跑只会补抓缺失部分日志里同时输出新抓和跳过的数量一眼确认断点是否生效。实际调限速参数时从 sleep(2) 起步观察返回码分布没有出现 429 或 403 再逐步收紧到 1.5 秒这是最稳的节奏。本文还有配套的精品资源点击获取
返回列表