首页 / 资讯中心 / 文章详情

Python爬虫实战:抓取淘宝商品评论的完整流程与反爬策略

Python爬虫实战:抓取淘宝商品评论的完整流程与反爬策略 ★ FEATURED ARTICLE
在电商数据分析和竞品调研里商品评论一直是被低估的金矿。我做了六年爬虫相关的数据采集工作接得最多的需求之一就是帮我看看这款产品在淘宝上的评价到底怎么样。不管你是做产品调研、竞品分析、消费者舆情监控还是单纯想研究Python网络爬虫技术抓取淘宝商品评论都是一道绕不过去的坎。今天我就拿一个实际跑通过的项目来拆解完整走一遍利用Python爬虫获取淘宝商品评论的流程把这中间的接口分析、反爬应对、代码实现和数据清洗讲透。这个项目适合两类人来参考一是刚学完Python基础、想找一个真实爬虫练手项目的开发者二是有具体数据需求但不想用付费采集工具的产品运营和电商从业者。看完这篇你至少能掌握三个核心能力如何从网页和接口中定位数据源、如何用Python模拟用户请求拿到JSON数据、如何在触发反爬机制时通过不影响他人的方式守住自己的采集任务。1. 项目目标拆解与整体技术方案1.1 商品评论数据到底有什么价值先聊点实在的。为什么选淘宝商品评论作为爬虫对象因为淘宝商品评论是目前中文互联网里结构最丰富、密度最高的用户反馈数据集之一。一条完整的淘宝评价至少包含这几个维度用户昵称、评价内容、追评内容、商品评分、评价时间、购买的商品规格SKU信息、甚至还有卖家回复。这在做消费者画像、产品质量追踪和竞品分析时都是极其核心的字段。比如你真在做一个跨境选品项目与其在Google Trends上猜不如直接把淘宝上同类目销量前十的SKU评论全抓下来用jieba分词做一轮词频统计你会发现掉色这个词出现的频率远超你预期很多用户反馈根本不会出现在宣传页面里。这就是评论数据的直接价值——真实、即时、颗粒度细。当然光知道数据有价值还不够你得知道淘宝评论的数据藏在哪。这就要说回技术选型了。1.2 为什么选择Python做评论采集Python在这个场景里几乎是唯一合适的选择原因有三个第一爬虫生态成熟。网络请求有requests、httpx页面解析有BeautifulSoup、lxml、parsel异步采集有aiohttp整个工具链都是为这种高频请求、精细解析的任务设计的。换成Java或Go当然也能做但你得从更底层开始封装开发效率差很多。第二数据分析链路顺畅。抓下来的评论是结构化JSON直接转进pandas DataFrame然后清洗、分词、可视化全在Python里搞定不用来回倒腾数据格式。第三反爬机制调试方便。淘宝的Web端评论接口有签名参数、Cookie管理、频率限制等多重防护用Python的requests.Session维护会话状态比在浏览器控制台手动操作或者用其他语言封装HTTP协议都要灵活。1.3 总体架构从商品ID到CSV文件整个项目我拆成五个环节下面这张流程逻辑你记一下后面每个环节都得落地定位商品ID——通过商品详情页URL解析或搜索页面正则提取拿到唯一的商品标识。 寻找评论接口——分析商品详情页发起的XHR请求锁定返回评论数据的API地址。 构造请求参数——把商品ID、卖家ID、页码、排序方式等参数拼接进请求URL并处理签名。 模拟请求并解析——利用requests携带Cookie、User-Agent发起请求将返回的JSON数据提取为结构化字段。 数据清洗与存储——处理嵌套字段、缺省值最终落成CSV或Excel文件。这套流程不挑平台换到京东、拼多多、大众点评核心逻辑都是一样的区别只在于接口地址和参数规则不同这也是我为什么一直强调思路比代码重要。2. 环境准备与工具选型2.1 搭建Python爬虫开发环境这个项目对Python版本没有硬性要求我用的是Python 3.93.7以上版本基本都能跑通。如果你还没装Python直接去官网下载安装包安装时记得勾选Add Python to PATH这是新手最容易忽略的一步不勾的话后面在命令行敲python会提示找不到命令。装好之后强烈建议创建虚拟环境别图省事直接用全局环境依赖冲突的苦头我吃过太多次了mkdir taobao_review_spider cd taobao_review_spider python -m venv venv source venv/bin/activate # Windows下用 venv\Scripts\activate然后安装项目依赖pip install requests beautifulsoup4 lxml pandasrequests负责发HTTP请求pandas负责数据存储和清洗这两个是核心。BeautifulSoup和lxml是备用方案用于处理部分情况下返回的不是JSON而是HTML片段的情况。做爬虫有一个原则凡是接口能直接返回JSON就绝不用HTML解析去绕远路。2.2 requests库的核心用法与Session管理requests库是Python发送HTTP请求的标准工具它的用法非常简单绝大多数爬虫任务都离不开这三类操作import requests url https://example.com/api params {page: 1, size: 20} headers {User-Agent: Mozilla/5.0 ...} resp requests.get(url, paramsparams, headersheaders) print(resp.status_code) data resp.json()但如果只是这样用很快你就会被淘宝反爬机制拦住。原因在于requests.get每次都是独立请求服务器端每次看到的都是一个没有登录状态的陌生人。这时候必须用Session对象session requests.Session() session.headers.update({ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ..., }) session.cookies.update({cookie_key: cookie_value}) resp session.get(url, paramsparams)Session对象会自动保存服务器设置的Cookie并在一段时间内维持连接。它模拟的行为相当于你开着同一个浏览器在持续访问这样比反复创建新连接更贴近正常用户触发反爬的概率也会低一些。3. 寻找评论接口破解数据藏身之处3.1 从商品详情页定位核心请求淘宝的商品详情页URL一般是这样的结构https://item.taobao.com/item.htm?id724579123456当你在浏览器里打开这个链接会看到商品标题、价格、主图、详情描述等内容。但注意商品评论并不直接渲染在初始HTML里而是往下滚动页面到累计评价模块时页面才会通过JavaScript异步加载评论数据。这就是爬虫的第一个核心技巧数据不在HTML源码里而是藏在XHR请求中。在Chrome浏览器按F12打开开发者工具切换到Network面板刷新页面后往下滚动到评价区域你会发现网络请求列表里多出几条以rate开头的请求。这里面最关键的一条长这样https://rate.tmall.com/list_detail_rate.htm?itemId724579123456spuId...sellerId...order3currentPage1..._ksTS1699999999999_123接口路径里的list_detail_rate一看就知道是列表-详情-评分的意思正对应评论数据。现在需要做的就是从服务器的响应里拿到JSON数据。如果你在浏览器里直接访问这个URL大概率会返回一个JavaScript脚本包着JSON的响应体类似下面这种JSONP格式jsonp1699999999999_123({ ...评论数据的JSON... })JSONP是淘宝为了避免跨域问题使用的一种老式接口格式。对我们来说处理办法很简单剥掉外面的包装函数名剩下的就是标准JSON。这算是淘宝评论接口的第一层伪装后面还有更复杂的参数需要处理。3.2 核心请求参数逐项解析评论接口的参数不算特别多但有一半是必须动态获取的写死的话接口会直接拒绝访问。我把核心参数整理成了表格方便你对照检查参数名含义获取方式itemId商品ID商品详情页URL中的id一眼可见spuId商品SPU标识从详情页HTML或接口返回中提取sellerId卖家ID从详情页HTML的window.__INITIAL_DATA__中提取order排序方式固定值1按推荐、3按时间、4按追评最多currentPage页码循环递增pageSize每页条数一般传20部分接口支持100_ksTS时间戳当前毫秒级时间戳加下划线后缀新手最容易被卡住的是spuId和sellerId。这两个值不在页面URL里而是藏在详情页的JS变量中那怎么提取两个办法一是继续用开发者工具在详情页HTML源码里全局搜索sellerId通常能找到类似window.__INITIAL_DATA__的赋值语句用正则或字符串截取把值取出来。二是直接请求评论接口测试参数。我最早做的时候就用笨办法把sellerId先填成0试一次发现接口照常返回数据说明sellerId在某些情况下不是必传项。但注意这招现在不一定每次都灵最稳妥的方案还是老老实实从页面源码提取。_ksTS参数也有讲究它由当前时间戳和回调函数序号拼成比如_ksTS1700000000000_123。这个参数在部分接口校验中会参与签名如果你发现直接写死时间戳导致IP被限那就需要每次请求时用int(time.time() * 1000)动态生成。4. 反爬应对与请求策略4.1 淘宝评论接口的常规反爬手段淘宝的防爬体系在电商平台里属于第一梯队但只要不搞大规模并发、不以商业目的恶性抓取单纯拿个几百上千条评论做学习研究用常规手段完全可以应对。我遇到过的主要有这四类第一是User-Agent校验。默认的python-requests的UA头会被直接拒绝解决办法是伪装成主流的Chrome或者Edge浏览器的UA。这个处理起来最简单但也是最不能省的一步。第二是Cookie校验。淘宝的匿名状态下可以看评论但如果你请求频率稍微高一点接口就会要求登录之后才能继续返回。应对方案是先从浏览器里导出自己登录淘宝后的Cookie把它放进requests请求头里带上。这样服务器识别你就是已登录用户频率限制会放宽很多。需要注意的是Cookie有有效期一般三到五天会失效失效后重新从浏览器复制即可。第三是滑块验证。如果你请求频率过高或者IP被风控系统标记了接口返回的不再是JSON而是一个滑块验证页面的HTML。这种情况没有任何代码能直接绕过唯一的正确处理是立即停止该IP的请求等一段时间通常10到30分钟再恢复。为了降低触发概率我在代码里强制设置了请求间隔。第四是签名参数。淘宝的Web端评论接口目前没有太复杂的签名纵观整个请求你会发现主要是_ksTS这种时间戳参数。但如果后续接口升级遇到带sign参数的接口常规思路是通过JavaScript逆向找到签名算法或者直接用浏览器自动化框架配合执行。这属于进阶方向本期项目先不展开。4.2 采集频率控制与并发设计关于并发和使用频率我看很多教程一上来就教人用多线程、异步并发恨不得一秒发几十个请求把整站爬完。说实话在淘宝评论这种场景下这是最蠢的做法。你想想一个正常人浏览商品评论翻页也是每隔一两秒才点一下你程序里十毫秒连发好几次请求和正常用户行为差距太大风控不拦你拦谁。我在这类项目里用的频率策略是单线程循环每页之间sleep时间控制在1到2秒。如果需要提速我最多启3到5个线程每个线程维护不同的切换间隔。以默认每页20条评论计算抓取2000条评论的时间大约在3到6分钟这个速度已经完全够日常调研用了。没必要为了省那几分钟去冒封IP的风险。import time import random def safe_sleep(): # 在1.5~2.8秒之间随机休眠模拟人工翻页节奏 time.sleep(random.uniform(1.5, 2.8))这段代码的精髓在于random.uniform而不是固定sleep固定间隔本身也是一种机器行为特征。任何爬虫项目只要你把请求节奏控制得像人大部分反爬拦截都可以避开。5. 核心代码实现完成一次完整采集5.1 构造请求函数与数据解析现在把前面讲的思路全部落地成代码。下面这个函数是整个项目的核心我加了完整注释你直接复制就能跑通单页采集import requests import json import re import time import pandas as pd from urllib.parse import urlencode class TaobaoReviewSpider: def __init__(self, item_id, seller_id, cookie_str): self.item_id item_id self.seller_id seller_id self.session requests.Session() self.session.headers.update({ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36, Referer: fhttps://item.taobao.com/item.htm?id{item_id}, Accept: application/json, text/javascript, */*; q0.01, }) # 把浏览器中复制出来的Cookie文本传进来 for part in cookie_str.split(;): if in part: k, v part.strip().split(, 1) self.session.cookies.set(k, v) def fetch_review_page(self, page_num1, page_size20): base_url https://rate.tmall.com/list_detail_rate.htm params { itemId: self.item_id, spuId: 0, sellerId: self.seller_id, order: 3, currentPage: page_num, pageSize: page_size, _ksTS: f{int(time.time() * 1000)}_{page_num}, callback: fjsonp{page_num}, } url base_url ? urlencode(params) try: resp self.session.get(url, timeout10) resp.encoding utf-8 if resp.status_code ! 200: print(f请求失败状态码: {resp.status_code}) return None return self._parse_jsonp(resp.text) except requests.RequestException as e: print(f请求异常: {e}) return None def _parse_jsonp(self, text): # 去掉JSONP外层的回调函数包裹 text text.strip() start text.find(() end text.rfind()) if start ! -1 and end ! -1: text text[start 1:end] try: data json.loads(text) return data except json.JSONDecodeError: print(JSON解析失败返回内容可能被反爬拦截) return None这里有几个容易踩坑的细节我额外强调一下。首先是_callback参数它必须和_ksTS末尾的序号保持一致否则部分接口会返回格式错误。其次是请求头的Referer它必须指向对应的商品详情页这是淘宝校验请求来源的一个隐蔽字段。你如果拿掉Referer直接访问接口很可能返回一段空白JSON。5.2 提取评论字段并保存数据评论数据在返回的JSON里嵌套得比较深我第一次解析的时候也被绕晕过。这里直接把路径先铺出来从返回的data字段里取ratesList这个key它是一个数组数组里每个元素就是一条完整的评论。每条评论的字段结构如下注意带有星号的表示可能为空的字段JSON字段名提取到的含义是否常驻rateContent评论文本是appendComment.content追评内容否无追评时为空displayUserNick用户昵称是部分做脱敏处理ratings商品/服务的评分是rateDate评论时间是skuInfo购买的规格是格式如“颜色:黑色;尺码:L”reply.replyContent卖家回复内容否解析代码我用了一个习惯性写法用字典.get()一层层往下取取不到就给默认值。因为评论数据字段异常是家常便饭硬编码下标直接取很容易崩def parse_comment(item): append_comment item.get(appendComment) or {} reply_info item.get(reply) or {} return { 评论内容: item.get(rateContent, ).strip(), 追评: append_comment.get(content, ).strip(), 用户昵称: item.get(displayUserNick, ).replace(*, ), 评分: item.get(ratings, ), 评论时间: item.get(rateDate, ), 购买规格: item.get(skuInfo, ), 卖家回复: reply_info.get(replyContent, ).strip(), }所有评论数据解析完成后直接交给pandas存成文件all_reviews [] for page in range(1, total_pages 1): data spider.fetch_review_page(page_numpage) if data and data.get(data) and data[data].get(ratesList): for item in data[data][ratesList]: all_reviews.append(parse_comment(item)) safe_sleep() df pd.DataFrame(all_reviews) df[评论时间] pd.to_datetime(df[评论时间], errorscoerce) df.to_csv(taobao_reviews.csv, indexFalse, encodingutf-8-sig)注意CSV保存时用的编码是utf-8-sig而不是utf-8。这个细节特别重要用utf-8直接保存再拿Excel打开中文会乱码得一塌糊涂utf-8-sig会额外带一个BOM头Excel就能正常识别了。这个坑我最早爬天天基金评论区时遇到过从那以后所有CSV输出我统一都用utf-8-sig。6. 常见问题与排查技巧实录6.1 接口返回不是JSON而是HTML这是新手问得最多的问题。现象是打印resp.text看到的内容不是以jsonp开头而是一坨HTML标签且里面通常包含滑动验证或者访问异常这样的字眼。处理办法分两步。第一步停止请求让IP冷却一段时间通常15分钟起步。第二步检查自己的Cookie是否过期重新去浏览器复制一次。如果这两个都做了还是不行再检查请求头里是否有其他明显的机器特征比如Accept-Encoding是不是没有模拟浏览器的压缩方式。按照我的经验80%的情况是Cookie失效15%是请求频率太高只有5%是代码逻辑问题。6.2 部分评论丢失或者字段为空如果你发现抓下来的评论数量比页面上显示的少或者某些字段大量为空先别急着怀疑代码多半是页面做了懒加载或者接口做了分页截断。淘宝评论接口单次请求pageSize最多传100超出部分会静默丢弃。另外追评、卖家回复这些非核心字段并不是每条评论都有为空是正常现象清洗数据时空值统计一下就好。真正需要警惕的是评论顺序。评论接口的order参数决定了返回顺序order3是按时间排序order1是按综合推荐排序。同一商品下两种排序返回的结果不同做数据分析时一定要统一口径否则统计出来的情感分布可能完全不同。6.3 采集过程中触发滑块限制怎么办我再单独聊一下这个问题因为很多初学爬虫的同学把滑块验证想得太复杂了总想着怎么去模拟识别滑块缺口、计算拖拽轨迹。但说实话做数据采集的人都不会硬刚滑块因为没有任何意义滑块验证背后是IP维度的风控标识你这次破解了滑块下次它会用更复杂的策略甚至直接封掉这个IP。所以我的处理原则是能预判就预判触发就撤退绝不恋战。预判的方式就是前面说的频率控制把你每两次请求的间隔拉大不要在短时间内对同一接口高频访问。一旦触发暂停整个采集流程等待一段时间再换个时间段继续。有些时候晚上11点到第二天早上7点的风控策略会比白天松一些那是服务器负载低的原因不是规律但确实实测有效。7. 数据清洗与后续分析思路评论抓下来了代码能跑了事情才完成一半。说实话如果只是抓下来存到CSV里就完事那你用的还是Excel的活Python的价值根本没体现出来。我一般会顺手做两件事数据清洗和基础的角度分析。数据清洗这块重点处理重复评论。明明是同一条评论因为分页边界问题可能被抓了两遍用DataFrame的drop_duplicates按评论ID去个重。然后处理掉无意义评论比如大量回复中的【赠品】这类内容会严重拉低词频分析的准确度。评论文本里的HTML标签、表情符号直接用正则清掉就行import re df[清洗后评论] df[评论内容].apply(lambda x: re.sub(r[^], , x)) df df.drop_duplicates(subset评论内容, keepfirst) df df[df[评论内容].str.len() 2]做完清洗我会先跑一轮词频统计把高频词按正负面粗分一下再看时间维度上的趋势。比如某款电子产品在三月份突然出现了大量电流声相关的评论而二月份还没有那很大概率是那段时间的批次出了问题这就是评论分析对供应链反哺价值的直接体现。分词工具我常用的是jieba配合哈工大的停用词表简单几行就能出一个词云或者表格import jieba from collections import Counter text_list df[清洗后评论].tolist() words [] for text in text_list: words.extend([w for w in jieba.cut(text) if len(w) 2]) counter Counter(words).most_common(30) for word, count in counter: print(word, count)这段代码的效果很直观你可以在几秒钟内得到这个商品被提及最多的30个标签词。把这些词按评分高低分组对比基本就是这个产品核心卖点和核心槽点的全貌了。8. 关于数据边界与合规的实在提醒说句掏心窝子的话写爬虫教程的人很多愿意讲清楚边界的人很少。这个项目我反复强调的是所有请求频率、频率控制、请求字段背后都有一个前提只爬自己要用的数据量只把抓取行为控制在合理范围内不做大规模采集不用在商业或者任何盈利的用途上。淘宝的用户协议里对自动采集行为本身有明确态度各平台的反爬措施也在持续升级。我在自己的项目里始终保持这样一个原则凡是对电商平台公开页面中个人有权限看到的公开信息进行少量采集用于个人学习、学术研究严格控制访问频率这个行为本身是可以自洽的但如果要把数据打包出售或者做商业化服务那性质就完全变了。从技术角度来看以上所有代码的运行机制、反爬应对策略、接口分析思路更适合被视为一次Web请求与响应机制的学习范本。你掌握了这套方法论以后无论面对什么网站思路都会比别人清晰很多。这也是我把完整实战流程写出来的价值所在。9. 项目后续还能怎么扩展评论抓取的项目跑通之后可延展的方向比想象中多。我自己的经验是顺着这套代码改改你能做下面这类事情第一个方向是评论监控。把抓取脚本挂在服务器上每天固定时间跑一次用邮箱或者企业微信机器人推送新增评论摘要。做电商店铺运营的同学可以用这个方式实时掌握竞品的新评价动向比人工刷页面高效得多。第二个方向是评分分析与质量问题追踪。把某店铺全部商品评论抓下来按SKU维度聚合算出差评率和关键词命中率就能定位到具体哪个款式、哪个尺码存在集中投诉。之前一个做服装供应链的朋友就是通过评论分析发现某款裤子在褪色上被大量提及进而倒查是面料环节出了问题。第三个方向是情感分析与舆情预警。利用开源的中文预训练模型对当天新增评论做情感极性分类一旦负面评论占比超过设定阈值就报警。这套东西单独开发成本不低但在评论数据流已经打通的基础上等于在固定管线上再接一个处理节点增量成本很小。每次写这类实战总结我的体会都是一样的爬虫的难点从来不是发请求和解析数据的代码而是对整个数据管线的理解从如何找到接口、如何构造合法请求、如何控制采集节奏、如何清洗数据再到如何在规则边界内让数据产生价值。这套链路通了你换个平台、换个数据源差别只在于参数适配而思维模型是完全通用的。
阅读完成 · 觉得有帮助?
咨询建站