资讯动态

淘宝零食爬虫与数据分析实战:从参数解析到并发提速

发布时间:2026/9/15 5:28:22 来源:尧图企业网站定制
简介压缩包内含一套完整的淘宝零食热销商品数据采集与分析方案面向具备基础Python语法、希望进阶爬虫与数据分析的开发者及课程设计场景。代码以核心Python脚本与Jupyter Notebook为主配合清洗后的CSV数据文件与使用说明文档完整覆盖商品信息抓取、字段清洗、销量与店铺地区分布统计、商品词云可视化等流程抓取字段包括店铺省份城市、商品名称、价格销量、是否包邮及满减情况等淘宝公开信息。资源共16个文件大小约3.09MB除代码与说明文档外还包含工程配置、文本说明等辅助内容便于本地运行与二次扩展。目前已有87人学习下载适合用作爬虫综合练手或数据清洗课程的项目参考。说明文档标注了运行环境与注意事项代码注释详细遇到运行问题联系作者可获得售后支持。1. 为什么拿淘宝零食练手爬虫与数据分析最划算电商数据里零食类目几乎是公开信息最规整、更新频率又够高的样本。商品名、价格、销量、付款人数、店铺所在省市、是否天猫、包邮与否、满减门槛这些字段在页面结构中非常稳定抓下来之后几乎不用做太多结构化处理就能直接进入清洗和分析阶段。相比那些反爬策略变化频繁、字段嵌套混乱的垂直站点淘宝搜索页对入门者友好很多但对熟练工程师又留出了并发、去重、增量抓取这些可以做深的空间。这套资源里main.py是爬虫入口抓取结果落到product_info.csv分析部分在analysis.py与analysis.ipynb中完成涵盖数据清洗、销量排序、店铺地域分布和词云。整个链路从请求到出图是闭环的正好适合做课设、简历项目或者练手。本文按实际动手顺序拆解每个环节的参数、坑和可选优化最后给一个提速多倍而不影响数据质量的并发改造方案。2. 构造淘宝搜索爬虫参数、请求头与翻页逻辑2.1 搜索接口与参数映射淘宝搜索页的核心参数并不复杂但每个都直接影响返回结果。打开淘宝首页搜索零食后地址栏里的 URL 是关键线索。q是搜索词s是偏移量sort控制排序方式。这里的排序参数需要特别留意sortsale-desc表示按销量降序sortdefault是综合排序sortprice-asc和sortprice-desc分别对应价格升序和降序。默认资源抓取的是按销量排序的热销零食这在后文分析销量分布时能让数据更有区分度。page参数在淘宝搜索场景里不是直接生效的真正决定翻页的是s值。第一页s0第二页s44之后每页递增44而不是常见的48或60。这跟每页实际返回的商品条数有关抓取时如果用固定步长去翻页很容易出现重复商品或漏抓。建议用循环维护当前偏移量代码示例如下def build_params(keyword: str, offset: int) - dict: return { q: keyword, s: offset, sort: sale-desc, tab: all, filter: reserve_price[0.01], }filterreserve_price[0.01]的作用是过滤掉价格异常的标注商品比如价格显示为 0.01 的赠品或补差价链接。taball表示在全部商品类型中检索而不是只看天猫或只看淘宝店铺。偏移量从0开始44步进抓取深度由目标页码数决定。2.2 请求头与 Cookie 的处理策略淘宝对爬虫请求的识别主要靠请求头一致性、Cookie 的登录态以及访问频率。User-Agent必须使用真实浏览器的完整标识建议从自己浏览器复制一份完整的请求头而不是只贴一个裸的 UA。资源源码中headers字典包含了User-Agent、Referer、Accept-Language等字段其中Referer要指向搜索结果页本身否则部分接口会拒绝返回数据。Cookie 的处理是淘宝爬虫的核心。提示首次运行前需要先在浏览器中登录淘宝并访问一次搜索结果页再从开发者工具的 Network 面板复制请求的 Cookie填入代码中的COOKIE变量。不登录也能拿到部分推荐结果但销量数据和店铺信息会被截断。爬虫中请求公共逻辑通常封装成一个函数def fetch_html(url: str, headers: dict, cookies: str, retry: int 3) - str: for attempt in range(retry): try: resp requests.get(url, headersheaders, cookiescookies, timeout10) if resp.status_code 200: return resp.text except requests.RequestException as e: print(f第 {attempt 1} 次请求失败: {e}) time.sleep(2 ** attempt) return 这里采用指数退避重试机制首次失败后等待 2 秒第二次 4 秒第三次 8 秒。遇到页面跳转登录或滑块验证时接口返回的状态码往往是200但内容明显异常因此还需要检查返回文本中是否存在特定的验证特征。简单的做法是判断resp.text是否包含login或验证这类标记一旦出现就暂停当前线程并等待人工介入或更换 Cookie。2.3 HTML 解析与字段抽取淘宝搜索结果的商品信息嵌在 HTML 结构中解析方式选择上BeautifulSoup配合lxml在可读性和性能之间比较平衡。每一步都要先选定解析锚点再提取具体字段。from bs4 import BeautifulSoup soup BeautifulSoup(html, lxml) items soup.select(div[class*Content--content])Content--content是当前版本淘宝搜索页商品项的 CSS 类名片段。淘宝前端经常调整类名class*写法可以部分降低类名整体变化导致的选择器失效风险。如果发现解析结果为空需要重新检查页面结构并更新选择器。商品名称、价格、销量数字、店铺城市这些字段抽取完成后统一存入列表def single_page_parse(soup) - list: rows [] for item in soup.select(div[class*Content--content]): title_tag item.select_one(span[class*title]) price_tag item.select_one(span[class*price]) sales_tag item.select_one(span[class*realSales]) if title_tag is None or price_tag is None: continue row { 商品名称: title_tag.get_text(stripTrue), 价格: price_tag.get_text(stripTrue).replace(¥, ), 销量: sales_tag.get_text(stripTrue) if sales_tag else 0, 店铺: extract_shop_name(item), 省份: extract_province(item), 城市: extract_city(item), } rows.append(row) return rowsextract_shop_name、extract_province这类函数在源码中都有独立实现其思路是利用商品卡片上的独立标签定位比如div[class*shop]内部的文本再做字符串切分。销量字段需要注意淘宝页面上的销量文案可能是已售 1万这种格式需要清洗时统一处理。另外天猫商店和淘宝 C 店在页面上有不同的标识模板源码是通过检测是否存在天猫字样的图标或特定类名来生成布尔字段。3. 数据清洗销量还原、百亿价格复算与去重合并3.1 文本型数字的规范化抓取回来的字段基本是字符串直接做分析会得到错误结论。原始销量字段通常形如已售 900、已售 2.5万或者空白需要统一拆解成真实数值。这里常见做法是用正则提取数字部分再做单位换算。import re def normalize_sales(text: str) - int: if not text: return 0 m re.search(r([\d.])\s*([万]?), text.replace(,, )) if not m: return 0 num float(m.group(1)) if m.group(2) 万: num * 10000 return int(num)replace(,, )处理的是部分千分位带逗号的情况比如1,200不正则也可读。单位换算逻辑留了扩展位如果后续出现以亿为单位的销量文本追加一个分支即可。3.2 价格字段的多维校验淘宝商品的价格字段存在三种情况一口价区间17.8-39.9、促销价、以及基于 SKU 的无意义低价。数据清洗时如果只取字符串中的最小值会得到失真的均价。这里推荐一个过滤规则先把区间价格转换为最低价与最高价的均值然后和商品销量做交叉验证。def parse_price(price_text: str) - float: prices re.findall(r\d\.?\d*, price_text) if not prices: return 0.0 nums [float(p) for p in prices] return round(sum(nums) / len(nums), 2)如果某商品最低价低于 0.1 元但销量却高达几百多半是刷单或补差价链接。检测到这类异常时直接在清洗阶段剔除避免污染后续的销量均值。product_info.csv中原始价格列与清洗后的价格列建议都保留方便追溯。3.3 去重策略同一商品多店铺重复抓取翻页抓取时会出现同一个商品被重复收录的情况因为热门商品同时在搜索结果多个位置出现。常见的去重键选择上商品名称 店铺比单独商品名称更可靠因为不同店铺可能使用相似标题蹭搜索流量。df df.drop_duplicates(subset[商品名称, 店铺], keepfirst)keepfirst保留首次抓取到的记录。但更严谨的做法取决于分析目标如果要分析销量份额可以按商品名对销量做聚合能同时统计该商品在多个店铺的总销量如果只是排名展示直接去重即可。资源源码采用去重后再排序的策略代码看点是利用pandas链式调用完成多步清洗df_clean ( df.copy() .assign(销量lambda x: x[销量].map(normalize_sales)) .assign(价格lambda x: x[价格].map(parse_price)) .drop_duplicates(subset[商品名称, 店铺], keepfirst) .dropna(subset[省份, 城市]) )3.4 缺失值处理与地区字段拆分省份和城市字段可能为空或包含多余前缀。例如浙江 杭州、广东 广州、上海直辖市无城市这里必须区分处理。上面dropna会直接丢弃没有省市数据的行但直辖市的数据并不缺城市。更好的做法是用split并判长def split_region(loc_text: str): parts str(loc_text).replace( , ).split() if len(parts) 0: return , if len(parts) 1: return parts[0], parts[0] return parts[0], parts[1]清洗完成后建议做一个info()检查确保没有空字符串残留且各列类型正确。价格为float销量为int是否天猫为bool。这一步虽然机械化但放在任何分析前都能省掉不计其数的隐性问题。4. 热销排序、店铺地区分布与中文词云分析4.1 销量与价格的双维度排序热销零食排名不能只看销量绝对值还要考虑单价。同样的销售量单价高则营收高单价低则可能是在做引流。用价格 × 销量构造近似销售额字段再排序可以同时看到两种视角df_clean[销售额] df_clean[价格] * df_clean[销量] top_sales df_clean.sort_values(销量, ascendingFalse).head(20) top_revenue df_clean.sort_values(销售额, ascendingFalse).head(20)对比top_sales和top_revenue两个结果集常常会发现高销量产品的销售额排行并不靠前——这类观察很适合写进课设的分析结论部分。如果不做销售额字段直接分析销量最高的是谁其实信息量很低因为那不是商品综合表现的准确指标。4.2 店铺地区分布按省份聚合与图表绘制地区分布的经典输出是一张横向条形图加一张省份占比表。matplotlib画图时中文显示是常见问题需要显式配置中文字体import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei, Microsoft YaHei] plt.rcParams[axes.unicode_minus] False聚合逻辑为按省份分组统计店铺数量或商品数量并计算占比region_dist df_clean.groupby(省份)[商品名称].count().sort_values(ascendingFalse).head(15) region_dist.plot(kindbarh, figsize(10, 8))输出结果中最常见的产区分布是广东和浙江占大头与现实中零食厂家与电商运营团队的分布一致。分析文本里可以补充一句多数高销量零食的店铺注册地集中在食品产业带与电商发达地区这一步能连接业务背景和爬取数据。4.3 商品名称词云分词、停用词与词频控制词云部分用的是jieba分词加wordcloud库。零食商品名包含大量营销词例如包邮、特惠、网红、爆款这些词没有业务分析价值需要置入停用词集合。import jieba from wordcloud import WordCloud text .join(df_clean[商品名称].tolist()) words jieba.cut(text) filtered .join([w for w in words if w not in stopwords and len(w) 1])len(w) 1过滤掉单字避免装、鲜这类噪声字符单独成词干扰视觉。停用词表可以额外补充食品属性词例如零食、小吃、休闲等不然词云里最大的通常是这些产品词而非品牌或品类特征。wordcloud的生成参数注意字体路径wc WordCloud( width800, height600, background_colorwhite, font_pathC:/Windows/Fonts/simhei.ttf, max_words120, ).generate(filtered)如果运行环境没有simhei.ttf词云会出现方块乱码。Linux 服务器常见做法是指定/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc或自行上传一个中文字体文件并填对应路径。4.4 数据可视化布局与保存分析脚本结尾建议把三张图统一保存到本地而不是只plt.show()fig, axes plt.subplots(1, 3, figsize(18, 5)) top_sales.plot(kindbar, axaxes[0]) region_dist.plot(kindbarh, axaxes[1]) axes[2].imshow(wc) fig.tight_layout() plt.savefig(analysis_result.png, dpi150)5. 并发抓取提速改造与常见运行故障排查5.1 ThreadPoolExecutor 有节制地提速淘宝对单 IP 请求频次敏感不加控制的多线程会把本地代码跑出大量滑块验证。推荐的并发粒度是4到6个线程每个线程只负责不同偏移量的页面请求。核心改造点在main.py原有循环抓取的位置替换为以下模式from concurrent.futures import ThreadPoolExecutor, as_completed def fetch_one_page(offset: int, keyword: str): params build_params(keyword, offset) url https://s.taobao.com/search html fetch_html(url, paramsparams) rows parse_html(html) return rows all_rows [] with ThreadPoolExecutor(max_workers4) as executor: future_map {executor.submit(fetch_one_page, offset, 零食): offset for offset in range(0, 44 * total_pages, 44)} for future in as_completed(future_map): result future.result() all_rows.extend(result) time.sleep(0.5)每次请求完成后加 0.5 秒的间隔保证 QPS 控制在约 23 之间。这会比串行快接近 4 倍但不会立刻触发滑块。如果发现抓取过程中验证码开始出现降低并发到2并调大time.sleep。只追速度不管触发频率的做法在这类场景里会因小失大。注意运行多线程时Cookie 要保证多线程共用同一份不要为每条线程单独走一次登录逻辑否则登录态互相覆盖会导致全部请求 302 跳转。5.2 运行报错的高频原因与快速定位资源附带的说明文档要求先看再跑这一节把最常见的几个原因按出现概率排序说明。第一ModuleNotFoundError: No module named requests、lxml、pandas、jieba、wordcloud这类缺依赖错误。直接按说明文档中的requirements.txt执行安装pip install requests lxml pandas jieba wordcloud matplotlib beautifulsoup4如果环境里已经存在旧版本的pandas建议先升级到1.5以上否则DataFrame.assign链式调用时的类型推断表现会不一样。第二CSV 中文字符乱码。写入和读取时指定编码为utf-8-sigdf.to_csv(product_info.csv, indexFalse, encodingutf-8-sig)使用utf-8不带-sig在 Excel 双击打开时会出现中文列名乱码utf-8-sig能保证 Word、Excel 直接打开正常。第三翻页只抓到相同数据。检查偏移量生成逻辑确认不是把s固定成了0。调试方法是在循环里打印当前抓取页面的第一个商品名如果连续两页相同就说明参数拼接没生效。5.3 抓取结果的可用性验证与扩展方向清洗完成后用简单的描述性统计验证数据集是否健康print(df_clean.describe()) print(f商品总数: {len(df_clean)}) print(f平均价格: {df_clean[价格].mean():.2f} 元) print(f最高销量: {df_clean[销量].max()})如果平均价格在 1080 元区间、最高销量在数万到数十万之间基本可以断定抓取数据在合理范围。想扩展到零食外的其他类目只需要修改keyword参数并观察页面字段是否有格式变化。以这个资源为基础调整关键词和过滤条件完全可以复用到美妆、数码配件等同样公开信息的类目上数据分析部分几乎不用重写。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价