python爬取网易云音乐歌曲评论

本文详细解析了如何使用Python和Selenium爬取网易云音乐的歌曲评论,重点介绍了处理JS异步加载评论数据的方法,以及如何逆向工程获取加密参数params和encSecKey,实现自动化批量抓取。

以魏如萱为例,爬取热门前50首歌曲的评论

首先因为js异步加载的原因,直接获取源代码只能得到脚本自动生成的代码,因此我用的是selenium+chromdriver

来访问,这样就可以得到加载好的框架代码,然后找到各首歌曲对应的链接就好

之后,在network(以chrome为例)刷新页面,就能看到network的动作

我们可以发现,点击下一页评论,只有评论会刷新,而页面的URL却不会变化,因此后台向服务器发送的请求是xhr(XMLHttpRequset)对象,即在后台与服务器交换数据,而在不重新加载页面的情况下更新网页内容。

之后就可以找到这个R_SO_4_93465...文件,可以找到评论的数据包

然后就有两个参数 params以及encSecKey

观察可知只有这两个参数 params和encSecKey会随页面改变,进而response也刷新出下一页的评论。因此这是通过不同页面的params以及encSecKey参数的不同变化来向服务器发起请求并获取相应评论。

下一步就是搞清楚不同页面的params以及encSecKey参数是如何改变的

方法来源于 @平胸小仙女的知乎回复 https://www.zhihu.com/question/36081767

first_param = '{rid:"", offset:"0", total:"true", limit:"20", csrf_token:""}'
second_param = "010001"
third_param = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"
forth_param = "0CoJUm6Qyw8W8jud"

def get_params(page):
        #获取encText,也就是params
    iv = "0102030405060708"
    first_key = forth_param
    second_key = 'F' * 16
    if page == 0:
        first_param = '{rid:"", offset:"0", total:"true", limit:"20", csrf_token:""}'
    else:
        offset = str((page - 1) * 20)
        first_param = '{rid:"", offset:"%s", total:"%s", limit:"20", csrf_token:""}' % (offset, 'false')
        encText = AES_encrypt(first_param, first_key, iv)
        encText = AES_encrypt(encText.decode('utf-8'), second_key, iv)
        return encText

def AES_encrypt(text, key, iv):
        #AES加密
    pad = 16 - len(text) % 16
    text = text + pad * chr(pad)
    encryptor = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))
    encrypt_text = encryptor.encrypt(text.encode('utf-8'))
    encrypt_text = base64.b64encode(encrypt_text)
    return encrypt_text


def get_encSecKey():
    encSecKey = "257348aecb5e556c066de214e531faadd1c55d814f9be95fd06d6bff9f4c7a41f831f6394d5a3fd2e3881736d94a02ca919d952872e7d0a50ebfa1769a7a62d512f5f1ca21aec60bc3819a9c3ffca5eca9a0dba6d6f7249b06f5965ecfff3695b54e1c28f3f624750ed39e7de08fc8493242e26dbc4484a01c76f739e135637c"
    return encSecKey

然后就可以程序生成这两个参数,之后获取各页的评论即可

代码如下:

import requests
from lxml import html
from bs4 import BeautifulSoup
from urllib import request
import time
from selenium import webdriver
import json
import base64
from Crypto.Cipher import AES
headers = {
    'Accept': '*/*',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36',
    'Connection': 'keep-alive',
    'cookie': '_ntes_nnid=f16bde86c506341f618fb99fdcc28d9e,1558509782535; _ntes_nuid=f16bde86c506341f618fb99fdcc28d9e; UM_distinctid=16c3e03a59b30b-091fb473f85019-e343166-100200-16c3e03a59c508; vinfo_n_f_l_n3=0eb845b1983b4757.1.0.1564408522345.0.1564408656227; JSESSIONID-WYYY=EbCTdI3GfX3zDVzVMRH2onZAiwIlJY6ddjGkKybs%5CFq7BSWSxFa1Jd%2FYMHE21RM3cp%2BViO%5CGHUkVo6q3ATjDacBPJ4FzN%5C4lKKffCHv9Zq9wElns%5CH84KHj9kxy9FaSDWtK99vrmW2Z3P%2BFtek4k%2BOAmmHCX0saY075wUoMCGqFveCm2%3A1566818588491; _iuqxldmzr_=32; WM_NI=dZSL%2B10AySvKGLv7nOxMeWMoNaegj6guS15s40hBTma%2F2PO2RusphiVGJorUYHdedWsbShcsGx6xO8IsI0zafzCh3g3YGydFIoyGNmNMjH%2BQTbD%2B5sZq5vUllYhi7qWDQkg%3D; WM_NIKE=9ca17ae2e6ffcda170e2e6eea7ec67a89bb7bad672a7a88fb3c14f828a8aaab865898da699e839fcb98997f42af0fea7c3b92aa8869dadaa3bf49fb7b4f5418594bad8ed45bc93abb8d0658ebfab88e93ea5ab9dd2b879f8f0a8a3d767a3f1feb1ce3a92abbd91eb6396998690f15f9b98ac86e75db1be9d89e27985a8fa99ce348bad87d1f96ba6a68d89b26df187899ae74e8bb1b7a8cd678e93a6a9aa5b98be8cccb8799aaffb97d868b087a88ab67b959c9f8ce637e2a3; WM_TID=iht%2BODmvLFFEFEAQQQc4pPGyhOns1Tq%2B',
    'origin': 'https://music.163.com',
    'referer': 'https://music.163.com/'
}

first_param = '{rid:"", offset:"0", total:"true", limit:"20", csrf_token:""}'
second_param = "010001"
third_param = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7"
forth_param = "0CoJUm6Qyw8W8jud"

def get_params(page):
        #获取encText,也就是params
    iv = "0102030405060708"
    first_key = forth_param
    second_key = 'F' * 16
    if page == 0:
        first_param = '{rid:"", offset:"0", total:"true", limit:"20", csrf_token:""}'
    else:
        offset = str((page - 1) * 20)
        first_param = '{rid:"", offset:"%s", total:"%s", limit:"20", csrf_token:""}' % (offset, 'false')
        encText = AES_encrypt(first_param, first_key, iv)
        encText = AES_encrypt(encText.decode('utf-8'), second_key, iv)
        return encText

def AES_encrypt(text, key, iv):
        #AES加密
    pad = 16 - len(text) % 16
    text = text + pad * chr(pad)
    encryptor = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))
    encrypt_text = encryptor.encrypt(text.encode('utf-8'))
    encrypt_text = base64.b64encode(encrypt_text)
    return encrypt_text


def get_encSecKey():
    encSecKey = "257348aecb5e556c066de214e531faadd1c55d814f9be95fd06d6bff9f4c7a41f831f6394d5a3fd2e3881736d94a02ca919d952872e7d0a50ebfa1769a7a62d512f5f1ca21aec60bc3819a9c3ffca5eca9a0dba6d6f7249b06f5965ecfff3695b54e1c28f3f624750ed39e7de08fc8493242e26dbc4484a01c76f739e135637c"
    return encSecKey
    


def get_json(url, params, encSecKey):
    data = {
         "params": params,
         "encSecKey": encSecKey
    }
    try:
        response = requests.post(url, headers=headers, data=data)
    except requests.RequestException as e:
        print('error')
    content = response.content.decode('utf-8')
    return content

    

path = 'test.txt'


def main():
    url = 'https://music.163.com/#/artist?id=9609'
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument('--headless')
    brower = webdriver.Chrome(chrome_options=chrome_options)
    brower.get(url)
    iframe = brower.find_element_by_class_name('g-iframe')
    brower.switch_to.frame(iframe)
    soup = BeautifulSoup(brower.page_source, 'lxml')
    items = soup.find_all('span', 'txt')
    for item in items:
        item = item.a['href'].replace('/song?id=', '')
        songUrl = 'https://music.163.com/weapi/v1/resource/comments/R_SO_4_'+item+'?csrf_token='
        params = get_params(1)
        encSecKey = get_encSecKey()
        content = get_json(songUrl,params,encSecKey)
        json_dict = json.loads(content)
        comments = int(json_dict['total'])
        if comments % 20 == 0:
            pages = comments/20
        else:
            pages = int(comments/20)+1
        f = open(path,'a',encoding='utf-8')
        f.write('total'+str(comments)+'\n\n')
        f.close()
        for i in range(pages):
            f = open(path,'a',encoding='utf-8')
            params = get_params(i+1)
            encSecKey = get_encSecKey()
            text = get_json(songUrl,params,encSecKey)
            json_dict = json.loads(text)
            for item in json_dict['comments']:
                f.write(item['user']['nickname']+':'+item['content']+'\n\n')
            f.close()
        
    brower.quit()        
       
        

if __name__ == "__main__":
    main()

 

<think>好的,我现在需要帮助用户解决如何用Python爬取网易云音乐歌曲评论区,并将结果保存为txt和xlsx文件的问题。用户之前已经提出过类似的问题,并且得到了详细的回答,包含数据分析、可视化和词云生成的部分,但这次用户的需求更简单,只需要输出这两个文件。因此,我需要调整之前的回答,去掉不必要的部分,专注于爬取和保存数据的功能。首先,我需要确认用户的需求。用户希望爬取评论,保存为txt和xlsx,不需要生成图表或词云。这意味着我需要简化之前的代码,移除分析模块和词云模块,只保留爬虫和文件存储部分。接下来,我需要确保代码的正确性。网易云音乐的API可能会化,所以需要验证当前的请求方式是否有效。之前的代码中使用的是POST请求,参数包括rid、offset和limit,这些可能需要检查是否仍然适用。另外,headers中的User-Agent和Referer是否正确,是否需要其他反爬措施,比如Cookie或加密参数?然后,考虑用户可能的潜在需求。虽然用户现在只需要保存txt和xlsx,但可能希望代码尽可能高效和稳定。例如,处理网络请求时的异常处理,分页爬取时的延迟设置,以及数据存储时的格式问题。此外,是否需要处理评论中的特殊字符或换行符,避免影响文件格式? 接下来,我需要简化代码。移除analyze_comments和generate_wordcloud函数,只保留get_music_comments、save_to_txt和save_to_excel。同时,确保文件存储函数正确,比如txt文件是否按行写入评论内容,Excel文件是否包含正确的列名和数据。 测试部分也很重要。需要提供一个示例歌曲ID,并确保代码能够运行,获取评论数据。同时,考虑用户可能遇到的常见问题,比如依赖库的安装(requests,openpyxl,jieba等),以及中文字符的编码问题,确保文件保存时使用utf-8编码。 另外,用户可能没有提到的一些细节,比如分页爬取的页数设置,是否需要用户自定义,或者代码中默认的页数。在示例中,可以设置pages=5作为默认值,但用户可能需要根据实际情况调整。 最后,确保代码的注释和文档清晰,说明每个函数的作用,以及如何运行代码,包括安装依赖和准备必要的参数(如歌曲ID)。此外,提醒用户注意法律和道德规范,遵守网站的使用条款,避免过度请求导致IP被封禁。 总结来说,我需要提供一个精简、高效的爬虫脚本,专注于获取评论并保存为指定格式的文件,同时确保代码的健壮性和用户友好性。</think>以下是精简版的网易云音乐评论爬取与保存方案: ```python import requests import csv import time from datetime import datetime from openpyxl import Workbook def get_comments(song_id, max_pages=5): """获取歌曲评论""" comments = [] base_url = "https://music.163.com/api/v1/resource/comments/R_SO_4_{}" 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", "Referer": f"https://music.163.com/song?id={song_id}" } for page in range(max_pages): try: params = { "rid": f"R_SO_4_{song_id}", "offset": page * 20, "limit": 20 } response = requests.post( base_url.format(song_id), params=params, headers=headers ) data = response.json() for comment in data["comments"]: comments.append({ "用户": comment["user"]["nickname"], "内容": comment["content"].replace('\n', ' '), "时间": datetime.fromtimestamp(comment["time"]/1000).strftime('%Y-%m-%d %H:%M'), "点赞": comment["likedCount"] }) time.sleep(1.5) # 降低请求频率 except Exception as e: print(f"第 {page+1} 页获取失败: {str(e)}") break return comments def save_to_txt(comments, filename): """保存为文本文件""" with open(filename, 'w', encoding='utf-8') as f: for comment in comments: f.write(f"{comment['内容']}\n") def save_to_xlsx(comments, filename): """保存为Excel文件""" wb = Workbook() ws = wb.active ws.title = "歌曲评论" # 写入表头 headers = ["用户", "内容", "时间", "点赞"] ws.append(headers) # 写入数据 for comment in comments: ws.append([ comment["用户"], comment["内容"], comment["时间"], comment["点赞"] ]) wb.save(filename) if __name__ == "__main__": # 示例歌曲:周杰伦《晴天》ID=386538 song_id = input("请输入歌曲ID:").strip() comments = get_comments(song_id) print(f"成功获取 {len(comments)} 条评论") save_to_txt(comments, "comments.txt") save_to_xlsx(comments, "comments.xlsx") print("文件已保存") ``` ### 代码说明 1. **核心功能**: - `get_comments()`:通过网易云音乐API获取评论数据 - `save_to_txt()`:保存纯文本评论内容 - `save_to_xlsx()`:保存结构化数据到Excel 2. **技术细节**: - 使用请求间隔(1.5秒)和User-Agent避免反爬 - 处理时间戳转换(毫秒→标准时间格式) - 自动处理换行符(替换为空格) - Excel文件包含完整元数据(用户、时间、点赞数) 3. **使用方式**: ```bash # 安装依赖 pip install requests openpyxl # 运行程序 python music_comments.py # 输入歌曲ID(从网页URL获取) ``` ### 注意事项 1. 遵守网站robots.txt规定 2. 控制请求频率(建议不超过3页/秒) 3. 可能需要处理加密参数(如果API更新)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值