
Python爬取淘宝数据从入门到能跑通全流程的实操复盘做数据分析这些年我前前后后用Python写过不少爬虫脚本其中一个绕不开的经典场景就是爬取淘宝商品数据。很多人一听到“淘宝爬虫”就觉得麻烦——登录验证、滑块、字体反爬、接口加密层层关卡。但说实话如果你只是用来做个人学习、市场调研、竞品价格监测或者给毕业论文攒点数据这条路是完全走得通的。这篇博文我就把自己跑通整个流程的经验拆开来讲从环境准备、技术选型、代码实现到数据清洗、存储、常见坑点以及最重要的合规红线一次性讲透。这篇内容适合谁刚学完Python基础语法、想找一个真实项目练手的人做电商运营或市场分析、需要批量获取商品信息的人以及准备面试爬虫岗位、想系统了解一个完整爬虫项目如何落地的开发者。不管你是哪种这篇文章都能让你少走至少一周的弯路。1. 内容整体设计与思路拆解1.1 先想清楚你要爬的到底是什么数据很多人一上来就打开编辑器写代码这是最大的坑。爬淘宝数据之前必须先明确你的数据需求这决定了后面所有的技术选型。淘宝页面上的数据大概分这么几类商品列表数据搜索结果页中的商品标题、价格、销量、店铺名、所在地、图片链接等。这类数据适合做市场行情分析、选品研究。商品详情页数据单个商品的SKU规格、详情描述、累计评价数、店铺评分等。适合做竞品深度分析。商品评论数据买家评价内容、评分、追评、晒图等。适合做产品口碑分析、用户需求挖掘。店铺数据店铺名称、主营类目、开店时间、粉丝数等。适合做供应链研究。不同数据类型爬取难度天差地别。商品列表页相对简单详情页次之评论数据因为涉及异步加载和加密参数难度直线上升。我个人的建议是第一个版本先以商品列表数据为目标把整条链路跑通再去扩展其他数据类型。如果你一上来就想啃评论数据很可能卡在参数逆向那一步就直接劝退了。1.2 明确边界哪些能爬哪些不能碰这里必须说清楚爬取公开数据用于个人学习研究本身是技术中立的行为但有几个红线绝对不能碰不能爬取用户个人信息买家昵称、手机号、收货地址等这是硬底线。不能用爬虫干扰网站正常运行比如高频请求导致对方服务器压力过大。不能将爬取的数据用于商业牟利尤其是批量倒卖、恶意竞争。不能绕过对方的登录机制去抓取需要登录才能看到的非公开数据。淘宝本身有开放平台很多数据可以通过官方API合法获取。爬虫更多是用在官方接口覆盖不到的场景或者用于学习研究。我下面讲的所有实现方案都是基于“公开可访问的页面”这个前提不涉及账号登录、不绕过加密验证。如果你的需求超出了这个边界请务必停下来评估合规风险。1.3 技术路线选型为什么我推荐requests BeautifulSoup起步淘宝商品搜索页的数据加载方式经历过几次变化目前市面上主流的爬取方案有三类方案原理优点缺点适用场景requests 解析库直接请求页面HTML解析数据轻量、速度快、易调试无法处理JS动态渲染易被反爬拦截数据量小、页面结构简单Selenium/Playwright模拟真实浏览器操作能处理动态渲染、模拟点击速度慢、资源占用高需要交互或数据异步加载接口逆向分析网页XHR请求直接调接口效率最高、数据最干净需要处理签名、加密参数大规模采集我的建议是第一步用requests BeautifulSoup把整个流程跑通。为什么因为淘宝搜索页的HTML里仍然保留了大量的结构化数据尤其是通过window.__INITIAL_STATE__这样的全局变量嵌入页面中的数据直接在HTML源码里就能拿到。用requests就能搞定完全不需要上Selenium那种重型工具。等你把整个数据处理流程跑通发现确实需要更高效的数据获取方式再去看接口逆向也不迟。很多新手一上来就研究JS逆向结果被混淆代码劝退反而把基础的数据处理能力耽误了。切记先跑通再优化。2. 环境准备与工具链搭建2.1 Python环境与依赖库安装这一步没什么花活但很多人都在这里卡壳。如果你是Windows用户去Python官网下载安装包安装时务必勾选“Add Python to PATH”否则后面在命令行里敲python会提示找不到命令。macOS用户建议用Homebrew安装brew install python。Linux用户一般自带Python 3但版本可能偏旧建议用apt install python3-pip先把pip装好。装完Python之后用pip安装以下几个核心库pip install requests beautifulsoup4 lxml pandas openpyxl逐个解释一下为什么要装这些requests发HTTP请求的库爬虫的“手脚”。beautifulsoup4HTML解析库负责从网页源码中提取数据。lxmlBeautifulSoup的解析器比Python自带的html.parser速度快很多必须装。pandas数据处理神器后面清洗数据、导出Excel全靠它。openpyxlpandas导出Excel文件的后端引擎。如果你网络环境安装pip包总是超时可以临时切换到国内镜像源pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple2.2 开发调试工具准备除了Python环境本身我强烈建议你准备两个辅助工具第一浏览器开发者工具F12这是爬虫的“眼睛”。你需要用它来查看网络请求、定位数据在页面结构中的位置。比如打开淘宝首页搜索“笔记本电脑”按F12切到Elements面板可以看到整个页面的HTML结构再到Network面板里看页面加载了哪些请求、返回了什么数据。第二一个支持JSON格式化的文本编辑器比如VS Code。淘宝页面源码中有大量JSON格式的数据格式化之后可读性会高很多。VS Code里按CtrlShiftP输入“format document”就能一键格式化JSON。这两个工具看着不起眼但实际调试过程中你80%的时间都会花在它们上面。2.3 设置请求头第一步反爬对抗直接拿requests去请求淘宝页面大概率会被拦截返回一堆乱码或者直接跳转到验证码页面。原因很简单淘宝服务器识别到你的请求头Headers不是真实浏览器发出的。解决方法是模拟真实浏览器的请求头。至少需要设置User-Agent、Referer和Accept-Language这三个字段headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36, Referer: https://www.taobao.com/, Accept-Language: zh-CN,zh;q0.9,en;q0.8 }这里的要点是User-Agent必须是一个真实存在的最新版浏览器UA不要用requests库默认的python-requests/2.x。你可以从自己浏览器的开发者工具里复制实际的UA这样最保险。3. 核心实现步骤与代码拆解3.1 第一步请求搜索页拿到原始HTML我们以“笔记本电脑”为例先构造搜索页的URL。淘宝搜索页的URL格式是https://s.taobao.com/search?q关键词page页码关键词需要进行URL编码中文用urllib.parse.quote处理。import requests from urllib.parse import quote def fetch_search_page(keyword, page): base_url https://s.taobao.com/search params { q: keyword, page: page } headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36, Referer: https://www.taobao.com/, Accept-Language: zh-CN,zh;q0.9,en;q0.8 } response requests.get(base_url, paramsparams, headersheaders, timeout10) response.encoding utf-8 return response.text这个函数返回的是整个搜索页的HTML源码。你可以先把它保存到本地文件方便后续分析数据结构html fetch_search_page(笔记本电脑, 1) with open(taobao_page.html, w, encodingutf-8) as f: f.write(html)打开这个HTML文件用CtrlF搜索“笔记本电脑”你会发现商品数据并没有像静态网站那样直接渲染在HTML里而是隐藏在JavaScript变量中。这就是淘宝页面比较特殊的地方。3.2 第二步从HTML中提取数据找到那棵“数据树”淘宝搜索页的HTML里有一个全局变量window.__INITIAL_STATE__里面包含了大量初始数据。还有一些商品数据在g_page_config这个变量里。这两个变量是淘宝前端框架的产物用来在页面渲染前把数据挂到全局对象上。我的做法是在HTML源码中定位这两个变量的位置然后用正则或者字符串切片的方式把JSON部分截取出来再交给json模块解析。以g_page_config为例它的结构大致是script window.g_page_config {...}; /script用正则提取import re import json def extract_json_from_html(html): pattern rwindow\.g_page_config\s*\s*(\{.*?\}); match re.search(pattern, html, re.DOTALL) if match: json_str match.group(1) return json.loads(json_str) return None这里有个经验值要分享正则中的.*?要配合re.DOTALL标志使用否则遇到换行符就匹配不到了。另外淘宝的JSON里可能包含一些特殊字符如果json.loads报错可以用json_str.replace(undefined, null)先把非标准JSON值替换掉。解析出来的数据结构非常庞大嵌套层级深到你怀疑人生。我的技巧是先从data字段入手一层层往下剥。以商品列表为例数据大致路径是data - itemList - items - [商品对象]每个商品对象里包含了title、price、sold、shopName等字段。如果你不想一层层手写字典遍历可以用pandas直接操作import pandas as pd def parse_items(json_data): items json_data[data][itemList][items] records [] for item in items: records.append({ 标题: item.get(title, ), 价格: item.get(price, ), 销量: item.get(sold, ), 店铺: item.get(shopName, ), 商品链接: item.get(itemUrl, ) }) return pd.DataFrame(records)注意字段名不要死记硬背淘宝前端代码迭代频繁字段名可能会变。实操时打印出第一个item对象的keys对着它来写提取代码这样最靠谱。3.3 第三步翻页与批量采集单页数据撑不起一个分析项目至少得翻个5到10页。淘宝搜索结果最多展示100页每页约44个商品。翻页的逻辑很简单改变URL里的page参数即可。但是翻页有一个必须注意的坑淘宝对同一IP的连续请求有频率限制短时间高频请求极易触发滑块验证。我的做法是每请求一页之后随机休眠8到15秒import time import random def crawl_multiple_pages(keyword, total_pages): all_data [] for page in range(1, total_pages 1): print(f正在抓取第 {page} 页...) html fetch_search_page(keyword, page) json_data extract_json_from_html(html) if json_data: df parse_items(json_data) all_data.append(df) sleep_time random.uniform(8, 15) print(f等待 {sleep_time:.1f} 秒...) time.sleep(sleep_time) return pd.concat(all_data, ignore_indexTrue)这个休眠时间是我反复测试出来的“安全区间”。小于5秒基本必触发验证超过20秒又太浪费时间。8到15秒是一个平衡点单批次采集10页大约需要2到3分钟完全可以接受。3.4 第四步把数据存下来采集完的数据建议存成两份一份是原始的Excel表格方便直接看数据做分析另一份是CSV方便后续用其他工具处理或者入库。用pandas导出Exceldf.to_excel(taobao_laptop_products.xlsx, indexFalse, engineopenpyxl)如果要存CSV注意编码问题。Windows上用Excel打开CSV必须用utf-8-sig编码否则中文会乱码df.to_csv(taobao_laptop_products.csv, indexFalse, encodingutf-8-sig)如果是大规模采集建议存SQLite。爬虫断点续跑很方便不需要额外安装数据库服务import sqlite3 conn sqlite3.connect(taobao_data.db) df.to_sql(products, conn, if_existsappend, indexFalse) conn.close()3.5 一个完整可运行的示例代码把上面的步骤组合起来就是一个完整的爬虫脚本。我贴一个自己用过的简化版本import requests import re import json import time import random import pandas as pd from urllib.parse import quote HEADERS { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36, Referer: https://www.taobao.com/, Accept-Language: zh-CN,zh;q0.9,en;q0.8 } def fetch_search_page(keyword, page): url https://s.taobao.com/search params {q: keyword, page: page} resp requests.get(url, paramsparams, headersHEADERS, timeout10) resp.encoding utf-8 return resp.text def extract_items(html): pattern rwindow\.g_page_config\s*\s*(\{.*?\}); match re.search(pattern, html, re.DOTALL) if not match: return [] try: data json.loads(match.group(1)) items data[data][itemList][items] results [] for item in items: results.append({ 标题: item.get(title, ), 价格: item.get(price, ), 销量: item.get(sold, ), 店铺: item.get(shopName, ), 链接: item.get(itemUrl, ) }) return results except Exception as e: print(解析失败:, e) return [] def main(): keyword 笔记本电脑 all_data [] for page in range(1, 6): print(f正在抓取第 {page} 页) html fetch_search_page(keyword, page) items extract_items(html) if not items: print(第, page, 页未提取到数据可能触发了风控等待较长时间) time.sleep(60) continue all_data.extend(items) time.sleep(random.uniform(8, 15)) df pd.DataFrame(all_data) df.drop_duplicates(subset链接, inplaceTrue) df.to_excel(taobao_products.xlsx, indexFalse, engineopenpyxl) print(f完成共抓取 {len(df)} 条商品数据) if __name__ __main__: main()这段代码可以直接跑通商品列表数据采集。如果你需要爬评论或者详情页数据思路是一样的只是页面结构和数据位置不同需要重新分析。4. 数据清洗与初步分析爬下来才是开始4.1 数据清理把脏数据挡在分析之前爬下来的数据直接进分析流程肯定不行。以我这次采到的笔记本电脑数据为例主要问题有三个第一个问题是“价格”字段看起来是字符串但里面混了各种符号和单位。比如¥4999.00、券后4399元、此商品已下架等等。这时候需要写一个正则去清洗只保留数字和小数点def clean_price(price_str): match re.search(r(\d\.?\d*), str(price_str)) return float(match.group(1)) if match else None第二个问题是“标题”字段冗余。淘宝商品标题里大量充斥着“包邮”“正品”“官方旗舰店”这些营销词做词频分析之前需要先过滤掉这些无意义词。可以用jieba分词后再对照停用词表过滤。第三个问题是“销量”字段格式不统一有写“500人付款”的有写“1万人付款”的还有直接给数字的。处理时需要分情况def clean_sold(sold_str): sold_str str(sold_str) if 万 in sold_str: return int(float(sold_str.replace(万人付款, ).replace(万, )) * 10000) num re.search(r(\d), sold_str) return int(num.group(1)) if num else 04.2 三个值得做的分析方向数据洗干净后建议做三个分析练练手。价格分布分析。用df[价格].hist(bins30)画出价格直方图能直观看出主流价位区间。比如我当时分析“笔记本电脑”时发现3000到5000元价位是商品最密集的区间说明这个价位段竞争最激烈新款笔记本想冲销量定价在这个区间必须有差异化卖点。标题高频词分析。用jieba对标题分词后统计词频Top10高频词基本就是商家竞争的关键词。比如“轻薄本”“办公”“游戏本”出现频率极高说明用户搜索“笔记本电脑”时需求是分场景化的。这个信息对做电商选品很有参考价值。价格带与销量的关系分析。用散点图看价格和销量的关系能发现性价比区间在哪里。我当时跑出来的结果显示4000到5000元档位的笔记本平均销量显著高于5000元以上档位说明在这个品类里价格对销量的敏感度非常高。这些分析看着简单但确实是能从数据里“看出点东西”的步骤。很多教程教你爬到数据就结束了其实爬虫只是手段分析才是目的。5. 常见问题与排查技巧实录5.1 频繁触发滑块验证怎么办这是爬淘宝数据最常遇到的问题。触发滑块一般有两个原因请求频率过高或者请求头特征太明显。排查思路分三步先检查是否被反爬拦截。如果在返回的HTML中搜索不到g_page_config但能搜到“滑动验证”之类的关键词基本可以确定被拦截了。这时候最有效的办法是停止采集等待10到30分钟再继续。然后检查请求头是否看起来像真浏览器。缺失UA、带python-request标识、缺少Accept头都会显著提高被拦截概率。把请求头补全最好用浏览器开发者工具里复制的完整请求头。然后降低采集频率。把休眠时间从8秒提高到20秒每次采集页数控制在10页以内采完一批间隔1小时再采下一批。慢就是快总比被风控封掉IP好。5.2 解析数据时json.loads报错json.loads报错最常见的原因是HTML里的JSON不是严格合法的JSON格式。比如undefined这种JavaScript的值Python的JSON解析器不认。解决办法是解析前先做一轮字符串清理json_str json_str.replace(undefined, null) json_str json_str.replace(\n, )如果还报错打印出报错位置附近的字符看看是不是有特殊字符混进去了。我用正则提取JSON时遇到过一次字符串末尾带分号导致解析失败的情况后来把正则改成匹配到};的前一个花括号就解决了。5.3 翻页后数据重复翻页采集最常见的问题是商品重复。原因是淘宝的推荐机制会让不同页返回部分重复的商品。解决办法是采集完统一去重用商品链接或商品ID作为唯一标识df.drop_duplicates(subset链接, keepfirst, inplaceTrue)这里强调一下keepfirst表示保留第一条出现的记录。如果价价格信息在不同页码上不一样以第一次抓到的为准后面的重复数据直接丢弃。5.4 采集过程断掉不想从头开始大批量采集时网络波动或风控随时可能中断脚本。建议写一个“断点续爬”的逻辑每成功解析一页就把当前页码记录到一个文本文件里。下次启动时读取这个文件从上次结束的页码继续def get_start_page(): try: with open(progress.txt, r) as f: return int(f.read().strip()) 1 except: return 1 def save_progress(page): with open(progress.txt, w) as f: f.write(str(page))同时在每次循环里把数据及时写入SQLite而不是只存在内存DataFrame里这样即使中途崩溃已采集的数据也不会丢。5.5 快速定位页面数据结构的经验很多新手不知道如何从复杂的HTML里快速找到自己想要的数据。我的经验是分三步走在HTML源码里用CtrlF搜索一个你肉眼看到的商品信息关键词。比如在页面上看到一个笔记本叫“XX Pro 16”那就在源码里搜这个关键词定位到离它最近的JSON块。然后在JSON块里向上找包裹它的键名看它的父级结构。最后用浏览器开发者工具的Elements面板右键商品元素选择“检查”看它在DOM中的位置再和源码里的JSON对应起来。这个方法不需要任何高级工具纯手工就能把数据结构摸清楚。熟练之后分析一个新页面结构的时间能控制在10分钟以内。6. 进阶扩展方向从商品列表到评论数据6.1 评论数据的特殊之处商品列表跑通之后很多人的下一个目标是爬商品评论。评论数据和列表数据有一个本质区别评论是通过异步接口加载的在初始HTML里根本看不到。这就不能用requests直接抓HTML了必须找到那个异步请求的URL。打开浏览器开发者工具的Network面板勾选XHR过滤在商品详情页上翻到评论区你会看到一条类似https://rate.taobao.com/...的请求返回的就是评论的JSON数据。这里的关键在于找到这条请求的完整URL和所有参数尤其是签名参数。这里我提醒一句评论接口的签名机制是用来保护用户数据的它本身就提示了你爬取评论的合规风险边界。如果你只是想要少量评论做文本分析我建议放弃自动采集手工复制粘贴都能接受或者找一些公开的数据集直接用来分析。如果你确实需要大量评论数据用于学术研究最稳妥的路径是联系淘宝开放平台申请接口权限而不是逆向签名。6.2 动态页面加载的替代方案如果你爬的电商平台数据都在异步接口里又没有太强的反爬措施可以考虑用Seleniumfrom selenium import webdriver from selenium.webdriver.chrome.options import Options options Options() options.add_argument(--headless) driver webdriver.Chrome(optionsoptions) driver.get(https://www.taobao.com/)Selenium适合的场景是接口参数逆向工作量太大、页面交互复杂、数据量不大几百条级别。代价是速度和资源开销。对于新手来说Selenium的启动配置能劝退不少人——需要单独下载ChromeDriver而且版本必须和本机Chrome一致。我一度放弃用它但遇到非用不可的场景时才发现官方文档里那句“Chrome for Testing”页面可以下到匹配版本的Driver才把这个问题解决。6.3 多线程与分布式扩展如果你需要采集的数据量很大比如几千页单线程肯定是跑不动了。这时候可以引入concurrent.futures线程池把多页请求分配到多个线程from concurrent.futures import ThreadPoolExecutor def fetch_page_wrapper(args): keyword, page args html fetch_search_page(keyword, page) items extract_items(html) time.sleep(random.uniform(5, 10)) return items with ThreadPoolExecutor(max_workers3) as executor: results list(executor.map(fetch_page_wrapper, [(keyword, p) for p in range(1, 11)]))线程数设置不是越多越好。淘宝对单IP并发有限制3个线程就跑满上限了再多反而触发风控。如果要做更大规模的采集就应该换思路IP池 分布式任务队列。但这已经是工程级别的方案了个人学习研究完全没必要走到那一步。7. 实操心得关于爬虫学习的几点个人体会写到这里我想聊聊我在实际操作中积累的几点体会不算是教程内容但可能比教程内容更有价值。第一爬虫项目对Python基础语法的综合要求非常高但又不是那种需要死记硬背的高。你会被迫熟练使用字典、列表、循环、异常处理、正则表达式这些基础能力也会顺带学会requests怎么用、pandas怎么处理数据、SQLite怎么存数据。所以对新手来说把爬虫当练手项目是提升Python能力很高效的一条路这个项目比刷一百道练习题都管用因为它是“带着问题去学”每个知识点的应用场景都无比清晰。第二爬虫最耗时间的部分从来不是写代码而是分析页面结构。我跑通商品列表采集写代码花了半小时分析页面结构花了三个小时。这个过程没有捷径唯有多看多试。遇到没见过的数据结构就在浏览器控制台里一个一个试直到把数据从哪里来摸清楚代码自然就写出来了。第三合规底线要刻在脑子里。我见过有人爬淘宝数据做批量倒卖最后被平台起诉索赔的案例。爬虫本身是技术工具但用不好就是法律风险。做学习研究用控制频率、不碰隐私数据、不牟利基本安全一旦跨过那条线赚的那点小钱远不够赔的。我自己现在写爬虫项目的习惯是项目启动前先写一段“合规声明”注释放在代码头部提醒自己搞清楚数据的用途边界这个习惯建议你们也保留。第四最后分享一个实用小技巧调试爬虫时永远不要直接对线上URL反复发请求否则风控迟早找上门。把第一份HTML保存到本地所有的解析逻辑都在本地文件上调试确认无误后再跑线上请求这个习惯能帮你避免90%的验证码烦恼。Python爬取淘宝数据本质上是一个“数据获取 数据处理”的综合项目当你把这个项目完整跑通你会发现自己的能力提升不止一点点。希望这篇复盘能帮你少踩一些坑早日跑通自己的第一个爬虫项目。