1. 为什么选择网易云评论作为爬虫学习目标
网易云音乐的评论区一直以"有故事"著称,这里汇聚了大量用户真实情感表达。从数据角度看,每条评论包含用户ID、昵称、评论内容、点赞数、时间戳等结构化数据,同时评论内容本身又具有丰富的非结构化特征,这种混合数据类型非常适合作为爬虫练手项目。
我最初选择这个项目,是因为它完美覆盖了爬虫技术的几个关键学习点:
- 需要处理动态加载内容(网易云采用Ajax分页)
- 涉及加密参数破解(常见的
params和encSecKey加密) - 需要模拟登录获取完整数据(部分敏感评论需登录)
- 数据清洗复杂度适中(包含HTML标签、特殊符号、emoji等)
2. 环境准备与工具选型
2.1 基础环境配置
推荐使用Python 3.8+环境,主要依赖库包括:
requests==2.28.1 # 网络请求 pycryptodome==3.15.0 # AES加密 pandas==1.5.3 # 数据存储 tqdm==4.64.1 # 进度条显示注意:不要使用最新版requests库,某些版本与网易云API存在兼容性问题。实测2.28.1版本最稳定。
2.2 开发工具选择
建议使用Chrome开发者工具分析网络请求,重点关注:
- XHR类型的请求(通常包含评论数据)
- Headers中的
csrf和Cookie字段 - Form Data中的加密参数
3. 逆向分析关键加密逻辑
3.1 加密参数定位
通过抓包可以发现,获取评论的API请求包含三个关键加密参数:
params = "加密字符串A" encSecKey = "加密字符串B" csrf_token = "从Cookie中获取"3.2 AES加密逆向
网易云使用AES-128-CBC模式加密,关键参数如下:
- 密钥:
0CoJUm6Qyw8W8jud - 初始向量:
0102030405060708 - 二次加密密钥:随机16位字符串
加密过程Python实现:
from Crypto.Cipher import AES import base64 def aes_encrypt(text, key, iv): pad = 16 - len(text) % 16 text = text + pad * chr(pad) cipher = AES.new(key.encode(), AES.MODE_CBC, iv.encode()) encrypted = cipher.encrypt(text.encode()) return base64.b64encode(encrypted).decode()3.3 RSA加密处理
encSecKey采用RSA加密,公钥固定为:
-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgtQn2JZ34ZC28NWYpAUd98iZ37BUrX/aKzmFbt7clFSs6sXqHauqKWqdtLkF2KexO40H1YTX8z2lSgBBOAxLsvaklV8k4cBFK9snQXE9/DDaFt6Rr7uVEBrdxR6aR5mDZU03kJ9b4IeA5sGTMp8YqomZ5HAYGHJDVd0s0qD0wIDAQAB -----END PUBLIC KEY-----4. 完整爬虫实现流程
4.1 获取歌曲ID
首先需要获取目标歌曲的ID,有两种方式:
- 从网页URL直接提取(如https://music.163.com/#/song?id=123456)
- 通过搜索API获取(需处理搜索结果的分页和排序)
推荐使用官方搜索接口:
search_url = "https://music.163.com/api/search/get/web" params = { "s": "歌曲名", "type": 1, # 1表示歌曲 "limit": 5 }4.2 构造加密请求
实现加密参数生成函数:
def generate_params(text): first_pass = aes_encrypt(text, primary_key, iv) second_pass = aes_encrypt(first_pass, random_key, iv) return second_pass def generate_encSecKey(random_key): # RSA加密实现 ...4.3 处理分页逻辑
网易云评论采用"瀑布流"加载方式,每页获取20条评论。关键参数:
offset: 起始位置total: 总评论数(首次请求返回)limit: 每页数量(固定20)
分页请求示例:
comment_url = "https://music.163.com/weapi/v1/resource/comments/R_SO_4_{song_id}" data = { "params": generate_params(json.dumps({ "rid": f"R_SO_4_{song_id}", "offset": offset, "total": "true" if offset == 0 else "false", "limit": 20 })), "encSecKey": generate_encSecKey(random_key) }5. 数据存储与分析
5.1 原始数据存储
建议使用CSV格式存储,字段包括:
[ "comment_id", "user_id", "nickname", "content", "liked_count", "time", "ip_location", "reply_count", "beReplied" ]5.2 数据清洗要点
常见清洗需求:
- 处理HTML标签(如
<em>表情标签) - 过滤特殊字符(换行符、制表符等)
- 提取emoji Unicode编码
- IP地址归属地解析
5.3 简单分析示例
使用pandas进行基础分析:
import pandas as pd df = pd.read_csv('comments.csv') # 点赞TOP10评论 top10 = df.sort_values('liked_count', ascending=False).head(10) # 按小时统计评论量 df['hour'] = pd.to_datetime(df['time']).dt.hour hour_dist = df.groupby('hour').size()6. 反爬策略与应对方案
6.1 常见反爬机制
网易云采用的多层防御:
- 请求频率限制(单IP约150次/分钟)
- 加密参数时效性(约30分钟失效)
- 用户行为检测(鼠标轨迹、点击模式)
6.2 应对建议
- 请求间隔优化:
import random time.sleep(random.uniform(0.5, 1.5)) # 随机延迟- IP代理池搭建:
- 使用免费代理(快代理、西刺代理)
- 付费代理服务(按需购买)
- 请求头随机化:
headers = { 'User-Agent': random.choice(user_agent_list), 'Referer': 'https://music.163.com/' }7. 项目扩展方向
7.1 情感分析应用
使用SnowNLP进行评论情感值计算:
from snownlp import SnowNLP def get_sentiment(text): return SnowNLP(text).sentiments df['sentiment'] = df['content'].apply(get_sentiment)7.2 用户画像构建
基于评论数据可以分析:
- 活跃时间段分布
- 常用表情/词汇
- 社交关系网络(通过回复关系)
7.3 可视化展示
使用Pyecharts生成:
- 热词云图
- 情感趋势折线图
- 地域分布地图
我在实际爬取中发现,凌晨时段的评论情感值普遍高于白天,这可能与用户夜间情绪状态有关。一个实用的技巧是:对于热门歌曲,可以先爬取前500条热评进行快速分析,再决定是否采集全量数据。