尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

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

Python爬虫实战:逆向天猫评论接口与数据清洗分析全流程

Python爬虫实战:逆向天猫评论接口与数据清洗分析全流程 1. 项目概述与核心价值最近在做一个电商数据分析的项目需要大量的用户评论数据作为支撑。市面上虽然有现成的数据服务但要么价格不菲要么数据维度不符合我的需求。于是我又一次把目光投向了“自给自足”的方案——用Python爬虫来搞定。这次的目标是天猫淘宝的商品评论。这个需求听起来简单但做过的人都知道这里面的水有多深。从动态加载的数据接口到复杂的反爬机制再到海量数据的清洗和分析每一步都可能是个坑。我花了差不多一周的时间从零开始搭建了一套完整的爬取与分析流程中间踩了不少雷也总结出一些非常实用的技巧。今天就把这个实战过程完整地分享出来无论你是想学习爬虫技术还是真的需要获取电商评论数据相信这篇内容都能给你提供一个清晰、可复现的路径。简单来说这个项目要解决的核心问题是如何自动化、稳定地获取指定天猫/淘宝商品的用户评论数据并将这些非结构化的文本数据转化为可供分析的、结构化的信息。它适合有一定Python基础对网络请求和数据处理有初步了解的朋友。如果你是完全的新手可能需要先补充一下requests库和pandas库的基础知识。整个流程我会拆解为几个核心部分前期侦察分析数据接口、核心爬取构建请求与解析、数据存储、以及最后的文本分析与可视化。我会重点讲解那些官方文档里不会写但实践中又至关重要的细节和避坑指南。2. 前期侦察逆向分析数据接口动手写代码之前最关键的一步是搞清楚数据从哪里来。直接打开一个淘宝商品页比如某个手机的详情页拉到评价区域。你会发现评价是点击“下一页”或者滚动时动态加载出来的这说明数据并非直接写在网页HTML里而是通过JavaScript异步请求接口获取的。这就是我们常说的“动态网页”对付它浏览器的开发者工具F12是我们的主要武器。2.1 定位评论数据接口打开Chrome的开发者工具切换到Network网络选项卡然后刷新商品页并点击评价区域的“下一页”。这时网络面板里会刷出一堆新的请求。我们的目标是找到那个携带了评论数据的请求。筛选请求类型通常评论数据接口是XHR或Fetch类型的。你可以直接在筛选栏里点击XHR。寻找关键特征在请求列表里寻找名称中包含rate、comment、list、detail等关键词的请求。淘宝/天猫的评论接口URL通常比较长包含很多参数。预览响应内容点击找到的疑似请求在Preview或Response标签页查看服务器返回的数据。如果你看到的是结构化的JSON数据里面包含了rateList、comments等字段并且字段值正是页面上显示的评论内容、用户昵称、购买时间、追评等信息那么恭喜你找到了目标接口。注意天猫和淘宝的接口可能不同甚至同一平台不同时期的接口也会有变化。我这次实战中遇到的天猫商品其核心评论接口是一个GET请求URL模式类似于https://rate.tmall.com/list_detail_rate.htm?itemIdxxxxxxsellerIdxxxxxxcurrentPage1。你需要以你实际侦察到的为准。2.2 解析接口参数与请求头找到接口后我们需要仔细研究它的Headers信息这是模拟请求、绕过反爬的关键。请求参数Query String Parameters在Headers的Query String Parameters部分你会看到一长串参数。常见的核心参数包括itemId: 商品ID这是唯一标识一个商品的。sellerId: 卖家ID。currentPage: 当前请求的页码。pageSize: 每页返回的评论数量通常固定为20。order: 排序方式如3可能表示按时间排序。此外还可能有一堆像_ksTS,callback,sign等用于防爬的参数。这些参数往往是动态生成的是爬虫最大的难点。请求头Request Headers这部分必须尽可能模拟得跟浏览器一样。User-Agent: 用户代理字符串用于标识浏览器身份。必须设置一个常见的桌面浏览器UA。Cookie: 这是身份验证和维持会话的关键。对于评论接口初期可能不需要登录态的Cookie也能获取部分数据如前几页但要获取全部或需要登录才能看的评论就必须携带有效的登录Cookie。如何获取和管理Cookie是一个大话题后文会详细讲。Referer: 通常需要设置为商品详情页的URL表明请求是从哪个页面发起的。其他如Accept,Accept-Language等也最好一并带上让请求看起来更“自然”。实操心得不要试图去完全逆向那些动态参数如_ksTS,sign的生成算法尤其是对于淘宝/天猫这种级别的网站其加密逻辑非常复杂且经常变动。更务实的策略是直接复制浏览器中成功请求时的完整URL和Headers尤其是Cookie来使用。这意味着我们的爬虫在短期内是“半自动化”的需要定期手动更新Cookie。对于中小规模、非实时的数据采集任务这个方法是最高效稳定的。3. 核心爬虫的构建与实现侦察工作完成后我们就可以开始编写爬虫代码了。我将使用requests库来发送HTTP请求用json库来解析返回的数据用pandas来存储和初步处理数据。3.1 环境准备与基础请求首先确保安装了必要的库。如果没安装在命令行执行pip install requests pandas。import requests import json import pandas as pd import time import random from typing import Dict, List, Optional class TMallCommentSpider: def __init__(self, item_id: str, seller_id: str): 初始化爬虫需要商品ID和卖家ID。 这两个ID可以从商品详情页的URL中提取。 例如https://detail.tmall.com/item.htm?id668741234567 item_id 就是 668741234567 seller_id 可能需要从页面源码或其他接口中找有时在URL参数里也有。 self.item_id item_id self.seller_id seller_id self.base_url https://rate.tmall.com/list_detail_rate.htm self.session requests.Session() # 使用Session保持会话 # 设置一个通用的请求头模板 self.headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36, Accept: application/json, text/javascript, */*; q0.01, Accept-Language: zh-CN,zh;q0.9,en;q0.8, Referer: fhttps://detail.tmall.com/item.htm?id{self.item_id}, # Cookie: 这里先留空需要手动更新 } self.session.headers.update(self.headers)3.2 处理动态参数与Cookie管理如前所述我们采用“复制粘贴”策略。你需要手动在浏览器中完成一次评论翻页操作然后从开发者工具里复制目标请求的Cookie和完整的URL。def update_cookie_from_browser(self, cookie_string: str): 将从浏览器复制来的Cookie字符串更新到Session中。 cookie_string 格式如name1value1; name2value2; ... cookie_dict {} for item in cookie_string.split(;): # 处理可能存在的空格和空值 if in item: key, value item.strip().split(, 1) cookie_dict[key] value # 更新到session的cookies self.session.cookies.update(cookie_dict) print(Cookie已更新。) def construct_params(self, page: int) - Dict: 构造请求参数。这里只包含最基础、相对固定的参数。 那些动态的、复杂的参数如callback, _ksTS我们直接使用完整URL不在这里构造。 因此这个函数返回的参数可能不完整最终请求时我们会使用侦察到的完整URL模式。 params { itemId: self.item_id, sellerId: self.seller_id, currentPage: str(page), pageSize: 20, order: 3, # 按时间排序可根据需要调整 } return params更实用的做法直接使用完整URL模板由于动态参数复杂我建议在侦察时直接复制第一页和第二页评论请求的完整URL观察其变化规律。你会发现基本上只有currentPage和个别时间戳参数在变。我们可以据此生成URL。def get_url_for_page(self, page: int) - str: 根据页码生成完整的请求URL。 这个URL模板需要你从浏览器中实际捕获至少两页的URL然后总结规律。 示例非真实可用URL仅展示格式 # 假设侦察到的URL模式如下参数顺序和名称请以你实际捕获的为准 base_pattern “https://rate.tmall.com/list_detail_rate.htm?itemId{itemId}sellerId{sellerId}order3currentPage{page}pageSize20_ksTS1629_1234567callbackjsonp1234” # 其中 _ksTS 和 callback 的值是动态的但规律可能是 _ksTS 的前缀是时间后缀是随机数。 # 一个简单的模拟方法是使用当前时间戳加随机数。 import time ksTS f{int(time.time()*1000)}_{random.randint(1000000, 9999999)} callback fjsonp{random.randint(1000, 9999)} url self.base_url f?itemId{self.item_id}sellerId{self.seller_id}order3¤tPage{page}pageSize20_ksTS{ksTS}callback{callback} return url3.3 发送请求与解析数据有了URL和携带Cookie的Session就可以发送请求了。需要注意的是返回的数据通常是JSONP格式即callback(...)包裹的JSON我们需要先将其转换为纯JSON。def fetch_page(self, page: int) - Optional[Dict]: 获取指定页码的评论数据。 url self.get_url_for_page(page) try: # 添加随机延迟模拟人工操作避免请求过快 time.sleep(random.uniform(1, 3)) response self.session.get(url) response.raise_for_status() # 检查请求是否成功 # 处理JSONP响应 resp_text response.text # 通常格式是jsonp1234({...})我们需要去掉头尾 if resp_text.startswith(jsonp) and resp_text.endswith()): # 找到第一个左括号和最后一个右括号 json_str resp_text[resp_text.find(()1: -1] data json.loads(json_str) return data else: # 如果不是JSONP尝试直接解析JSON return response.json() except requests.exceptions.RequestException as e: print(f请求第{page}页失败: {e}) return None except json.JSONDecodeError as e: print(f解析第{page}页JSON失败: {e}) print(f响应文本前500字符: {resp_text[:500]}) return None def parse_comment_data(self, data: Dict) - List[Dict]: 从接口返回的JSON数据中解析出我们需要的评论信息。 数据结构需要根据实际接口返回进行调整。 comments [] # 通常评论列表在 data[rateDetail][rateList] 或类似路径下 rate_list data.get(rateDetail, {}).get(rateList, []) if not rate_list: print(未找到评论列表数据结构可能已变化。) return comments for rate in rate_list: comment_info { id: rate.get(id), # 评论ID user_nick: rate.get(displayUserNick), # 用户昵称脱敏后 auction_sku: rate.get(auctionSku), # 购买的商品规格 rate_content: rate.get(rateContent), # 评论内容 rate_date: rate.get(rateDate), # 评论时间 append_comment: rate.get(appendComment, {}).get(content), # 追评内容 append_days: rate.get(appendDays), # 多少天后追评 photos: rate.get(photos, []), # 晒图列表 video: rate.get(video), # 视频信息 useful: rate.get(useful), # 点赞数 reply: rate.get(reply), # 商家回复 } # 处理匿名用户 if not comment_info[user_nick]: comment_info[user_nick] 匿名用户 comments.append(comment_info) return comments3.4 循环爬取与数据存储我们需要一个循环来翻页直到抓取完所有评论或达到设定的页数上限。同时将每页的数据追加存储起来。def crawl(self, max_pages: int 100, start_page: int 1): 主爬取循环。 max_pages: 最大爬取页数防止无限循环。 start_page: 起始页码。 all_comments [] current_page start_page while current_page max_pages: print(f正在爬取第 {current_page} 页...) page_data self.fetch_page(current_page) if not page_data: print(f第 {current_page} 页数据获取失败可能已无更多数据或遇到反爬。) break # 检查是否还有数据 rate_detail page_data.get(rateDetail, {}) if not rate_detail.get(rateList): print(评论列表为空爬取结束。) break comments self.parse_comment_data(page_data) if comments: all_comments.extend(comments) print(f 解析到 {len(comments)} 条评论。) else: print(f 第 {current_page} 页未解析到评论。) # 判断是否还有下一页根据接口返回的paginator字段或根据当前页条数判断 # 这里简单根据当前页是否满20条来判断更严谨应解析接口的hasNext等字段 if len(comments) 20: print(当前页评论数不足20条可能是最后一页。) break current_page 1 # 将所有评论数据转换为DataFrame并保存 if all_comments: df pd.DataFrame(all_comments) # 保存为CSV文件编码用utf-8-sig解决Excel打开乱码问题 filename ftmall_comments_{self.item_id}_{time.strftime(%Y%m%d_%H%M%S)}.csv df.to_csv(filename, indexFalse, encodingutf-8-sig) print(f爬取完成共获取 {len(all_comments)} 条评论。数据已保存至 {filename}) return df else: print(未爬取到任何评论数据。) return pd.DataFrame()注意事项反爬与封禁这是最大的风险。过于频繁的请求会导致IP被封或Cookie失效。务必在请求间添加随机延时如time.sleep(random.uniform(2, 5))。对于大规模爬取必须使用代理IP池。Cookie失效登录态的Cookie通常有有效期几天到几周。如果爬虫运行中途发现返回的数据为空或请求被重定向到登录页说明Cookie已失效需要重新从浏览器复制更新。数据字段变化电商平台的接口数据结构可能调整。如果某天爬虫解析不到数据了第一件事就是重新用开发者工具侦察一下接口返回的数据格式是否变了然后调整parse_comment_data函数。4. 评论数据的清洗与预处理爬取到的原始数据是“脏”的直接进行分析效果会很差。数据清洗是数据分析中耗时但至关重要的一步。4.1 常见数据问题与处理我们将清洗工作封装成函数作用于之前爬取得到的DataFrame上。def clean_comment_data(df: pd.DataFrame) - pd.DataFrame: 对爬取到的评论DataFrame进行清洗。 df_clean df.copy() # 1. 处理缺失值 # 评论内容为空或为系统默认文本的视为无效 default_texts [此用户没有填写评价。, 评价方未及时做出评价系统默认好评。] df_clean[rate_content] df_clean[rate_content].replace(default_texts, pd.NA) # 删除评论内容为空的记录但保留有追评或晒图的记录因为可能有价值 # 我们可以先标记不急于删除 df_clean[is_content_missing] df_clean[rate_content].isna() # 2. 处理重复值根据评论ID去重 df_clean df_clean.drop_duplicates(subset[id]) # 3. 统一时间格式 df_clean[rate_date] pd.to_datetime(df_clean[rate_date], errorscoerce) # 如果有追评时间字段也做同样处理 # 4. 文本清洗 import re def clean_text(text): if pd.isna(text): return text # 去除HTML标签 text re.sub(r[^], , text) # 去除网址、用户名等 text re.sub(rhttp\S, , text) text re.sub(r\S, , text) # 去除多余空白字符包括全角空格 text re.sub(r\s, , text) text re.sub(r , , text) # 全角空格 return text.strip() df_clean[rate_content_cleaned] df_clean[rate_content].apply(clean_text) df_clean[append_comment_cleaned] df_clean[append_comment].apply(clean_text) # 5. 提取有用信息 # 例如从auction_sku中提取颜色、尺寸等属性如果格式规整 # 这里需要根据实际字符串格式写正则表达式示例 # df_clean[color] df_clean[auction_sku].str.extract(r颜色分类([^;])) # 6. 情感倾向标记初步后续可用模型细化 # 定义简单的情感词库 positive_words [好, 不错, 满意, 喜欢, 划算, 正品, 快递快, 好用] negative_words [差, 不好, 不满意, 垃圾, 慢, 贵, 瑕疵, 破损] def simple_sentiment(text): if pd.isna(text): return neutral pos_count sum([1 for word in positive_words if word in text]) neg_count sum([1 for word in negative_words if word in text]) if pos_count neg_count: return positive elif neg_count pos_count: return negative else: return neutral df_clean[sentiment] df_clean[rate_content_cleaned].apply(simple_sentiment) print(f数据清洗完成。原始记录 {len(df)} 条清洗后 {len(df_clean)} 条。) return df_clean4.2 数据探索与质量检查清洗后应该对数据做一个快速的探索性分析了解其基本情况。def explore_data(df): 快速查看数据概况 print( 数据概览 ) print(df.info()) print(\n 前几条记录 ) print(df.head()) print(\n 评论情感分布 ) if sentiment in df.columns: print(df[sentiment].value_counts()) print(\n 评论时间范围 ) if rate_date in df.columns: print(f最早评论: {df[rate_date].min()}) print(f最新评论: {df[rate_date].max()}) print(\n 晒图评论占比 ) # 假设photos字段是列表非空表示有图 df[has_photo] df[photos].apply(lambda x: len(x) 0 if isinstance(x, list) else False) print(f有晒图的评论: {df[has_photo].sum()} ({df[has_photo].mean():.2%})) print(\n 追评占比 ) df[has_append] df[append_comment_cleaned].notna() print(f有追评的评论: {df[has_append].sum()} ({df[has_append].mean():.2%}))5. 评论数据的多维度分析实战数据清洗干净后就可以进行真正的分析了。电商评论分析通常围绕几个核心维度情感倾向、话题聚焦、时间趋势、用户行为。5.1 情感分析进阶使用SnowNLP前面我们用了简单词库做情感判断精度有限。对于中文文本SnowNLP是一个不错的情感分析库它基于机器学习模型效果比简单词库好很多。from snownlp import SnowNLP def sentiment_analysis_with_snownlp(df, text_colrate_content_cleaned): 使用SnowNLP进行情感分析。 情感得分在0-1之间越接近1表示越积极。 print(正在使用SnowNLP进行情感分析可能较慢...) sentiments [] for text in df[text_col]: if pd.isna(text): sentiments.append(0.5) # 中性 else: try: s SnowNLP(text) sentiments.append(s.sentiments) # 情感极性得分 except: sentiments.append(0.5) # 分析失败时设为中性 df[sentiment_score] sentiments # 根据得分划分情感类别 df[sentiment_category] pd.cut(df[sentiment_score], bins[0, 0.4, 0.6, 1], labels[negative, neutral, positive], include_lowestTrue) return df5.2 关键词与话题提取了解用户都在讨论什么是评论分析的核心。我们可以通过词频统计和TF-IDF来提取关键词。import jieba from collections import Counter from sklearn.feature_extraction.text import TfidfVectorizer def extract_keywords(df, text_colrate_content_cleaned, top_n30): 提取评论中的高频关键词和TF-IDF关键词。 # 1. 分词并过滤停用词 all_text .join(df[text_col].dropna().astype(str).tolist()) # 加载停用词表需要准备一个中文停用词文件 stopwords.txt try: with open(stopwords.txt, r, encodingutf-8) as f: stopwords set([line.strip() for line in f]) except FileNotFoundError: stopwords set() print(未找到停用词文件将不过滤停用词。) words [word for word in jieba.lcut(all_text) if word not in stopwords and len(word) 1] # 2. 词频统计 word_freq Counter(words) print(f\n 高频词Top {top_n}) for word, freq in word_freq.most_common(top_n): print(f{word}: {freq}) # 3. TF-IDF 提取按每条评论作为文档 corpus df[text_col].fillna().tolist() vectorizer TfidfVectorizer(tokenizerjieba.lcut, stop_wordslist(stopwords), max_features100) try: tfidf_matrix vectorizer.fit_transform(corpus) feature_names vectorizer.get_feature_names_out() # 计算所有文档的平均TF-IDF权重 avg_tfidf tfidf_matrix.mean(axis0).A1 word_tfidf dict(zip(feature_names, avg_tfidf)) sorted_tfidf sorted(word_tfidf.items(), keylambda x: x[1], reverseTrue) print(f\n TF-IDF 关键词Top {top_n}) for word, score in sorted_tfidf[:top_n]: print(f{word}: {score:.4f}) except ValueError as e: print(fTF-IDF计算失败可能语料过少或分词全部被过滤: {e}) return word_freq5.3 时间序列分析与可视化观察评论在时间上的分布可以了解产品热度变化、促销活动效果等。import matplotlib.pyplot as plt import seaborn as sns plt.rcParams[font.sans-serif] [SimHei] # 用来正常显示中文标签 plt.rcParams[axes.unicode_minus] False # 用来正常显示负号 def visualize_time_trend(df, date_colrate_date): 绘制评论数量随时间变化的趋势图。 if date_col not in df.columns or df[date_col].isna().all(): print(无有效日期数据无法绘制趋势图。) return df_temp df.copy() df_temp[date_col] pd.to_datetime(df_temp[date_col]) # 按天/周/月聚合 df_temp[date_day] df_temp[date_col].dt.date daily_counts df_temp.groupby(date_day).size() plt.figure(figsize(14, 6)) daily_counts.plot(kindline, markero, linestyle-) plt.title(每日评论数量趋势) plt.xlabel(日期) plt.ylabel(评论数) plt.grid(True, linestyle--, alpha0.7) plt.tight_layout() plt.show() # 还可以按情感分类看趋势 if sentiment_category in df_temp.columns: df_temp[date_week] df_temp[date_col].dt.to_period(W).dt.start_time weekly_sentiment pd.crosstab(df_temp[date_week], df_temp[sentiment_category]) weekly_sentiment.plot(kindarea, stackedTrue, figsize(14,6)) plt.title(每周评论情感分布趋势堆叠面积图) plt.xlabel(周起始日期) plt.ylabel(评论数) plt.tight_layout() plt.show()5.4 用户行为关联分析分析哪些因素会影响评论的情感或内容。def analyze_user_behavior(df): 分析用户行为之间的关联。 # 1. 晒图与情感的关系 if has_photo in df.columns and sentiment_category in df.columns: print(\n 晒图与情感倾向交叉分析 ) cross_tab pd.crosstab(df[has_photo], df[sentiment_category], normalizeindex) * 100 print(cross_tab.round(2).astype(str) %) # 2. 追评与初始情感的关系通常不满意的用户更可能追评 if has_append in df.columns and sentiment_category in df.columns: print(\n 是否追评与初始情感倾向交叉分析 ) cross_tab2 pd.crosstab(df[has_append], df[sentiment_category], normalizeindex) * 100 print(cross_tab2.round(2).astype(str) %) # 3. 评论长度与情感的关系可假设负面情绪可能表达更详细 df[content_length] df[rate_content_cleaned].fillna().apply(len) if sentiment_category in df.columns: print(\n 不同情感倾向的评论平均长度 ) length_by_sentiment df.groupby(sentiment_category)[content_length].mean() print(length_by_sentiment.round(2))6. 项目集成与自动化运行将以上所有步骤整合成一个完整的脚本并考虑一些工程化问题。6.1 主程序流程def main(): 主函数串联整个流程 # 步骤1: 初始化爬虫并更新Cookie需要手动操作一次 item_id 668741234567 # 替换为实际商品ID seller_id 123456789 # 替换为实际卖家ID spider TMallCommentSpider(item_id, seller_id) # 关键步骤手动从浏览器复制Cookie字符串替换下面的引号内容 # 格式cookie1value1; cookie2value2; ... your_cookie_string 这里粘贴你从浏览器复制的完整Cookie字符串 spider.update_cookie_from_browser(your_cookie_string) # 步骤2: 爬取数据例如前50页 print(开始爬取评论数据...) comments_df spider.crawl(max_pages50, start_page1) if comments_df.empty: print(爬取失败程序退出。) return # 步骤3: 数据清洗 print(\n开始数据清洗...) cleaned_df clean_comment_data(comments_df) # 步骤4: 数据探索 print(\n进行数据探索...) explore_data(cleaned_df) # 步骤5: 情感分析使用SnowNLP可选较慢 # print(\n进行SnowNLP情感分析...) # cleaned_df sentiment_analysis_with_snownlp(cleaned_df) # 步骤6: 关键词提取 print(\n提取关键词...) extract_keywords(cleaned_df, top_n20) # 步骤7: 可视化 print(\n生成可视化图表...) visualize_time_trend(cleaned_df) # 步骤8: 用户行为分析 print(\n分析用户行为关联...) analyze_user_behavior(cleaned_df) # 步骤9: 保存最终清洗和分析后的数据 final_filename ftmall_comments_analyzed_{item_id}.csv cleaned_df.to_csv(final_filename, indexFalse, encodingutf-8-sig) print(f\n所有分析完成最终数据已保存至: {final_filename}) if __name__ __main__: main()6.2 常见问题排查与优化建议在实际运行中你几乎一定会遇到下面这些问题。这里是我的排查清单和经验总结问题现象可能原因解决方案与排查步骤请求返回空数据或rateList为空1. Cookie已失效。2. 请求头不完整或被识别为爬虫。3. 接口URL或参数已更新。4. IP被暂时限制。1.首要检查重新从浏览器复制Cookie更新。2. 检查User-Agent,Referer等请求头是否与浏览器一致。3. 重新用开发者工具抓包确认当前有效的接口URL和参数格式。4. 增加请求延迟或更换IP地址使用代理。返回jsonp回调函数错误或数据被截断1. 动态参数如callback,_ksTS生成逻辑不对。2. 响应被干扰。1. 采用“复制粘贴”策略直接从浏览器成功的请求中提取完整URL观察页码变化规律来生成。2. 检查网络环境是否有中间件篡改响应。只能爬到前几页数据后面返回空白1. 未登录状态下只能查看部分评论。2. 翻页参数有校验。1.必须使用登录后的Cookie。确保复制的Cookie是登录状态下的。2. 检查翻页时除了currentPage是否还有其他参数如last需要变化。爬取速度慢单线程请求且延迟设置过长。1. 在遵守网站robots.txt和不对服务器造成压力的前提下可适当减少延迟如1-2秒。2. 对于大规模爬取必须使用代理IP池和多线程/异步IO如aiohttp库但复杂度会急剧上升。数据分析结果不理想1. 数据清洗不彻底噪声多。2. 简单情感词库不准。3. 分词效果差。1. 优化清洗函数针对你的评论数据特点如大量“默认好评”定制过滤规则。2. 使用更专业的工具如SnowNLP,BosonNLP商业API或自己训练模型。3. 为jieba加载自定义词典包含产品名、型号、特性词并优化停用词表。给新手的终极建议不要试图第一次就写出一个能爬几万条评论的完美爬虫。先从爬取单页、手动更新Cookie、解析数据这个最小可行流程跑通。然后逐步增加翻页逻辑、错误处理、数据清洗。最后再考虑代理、并发、持久化Cookie等高级话题。这个项目最宝贵的不是最终的代码而是你通过F12开发者工具进行侦察、分析网络请求、模拟浏览器行为这一整套解决问题的思路和能力。
返回列表