网易云音乐热度分析
import requests import json import pandas as pd import time from fake_useragent import UserAgent import random # -------------------------- 配置项 -------------------------- # 网易云音乐榜单ID2025热歌榜/年度榜可替换此ID # 热歌榜3778678 | 年度榜19723756 | 飙升榜19723756 BOARD_ID 3778678 # 请求间隔防反爬 REQUEST_DELAY 1.5 # 导出Excel文件名 OUTPUT_FILE 2025网易云音乐热度分析.xlsx # -------------------------- 核心爬虫函数 -------------------------- class NeteaseMusicSpider: def __init__(self): # 随机User-Agent模拟浏览器 self.ua UserAgent() self.headers { User-Agent: self.ua.random, Referer: https://music.163.com/, Cookie: appver8.9.0; ospc; # 可替换成自己的Cookie可选 } # 存储最终数据 self.music_data [] def get_board_songs(self, board_id): 爬取指定榜单的歌曲列表 # 榜单接口URL url fhttps://music.163.com/api/playlist/detail?id{board_id} try: # 发送请求添加随机延迟防封 time.sleep(random.uniform(REQUEST_DELAY, REQUEST_DELAY 1)) response requests.get(url, headersself.headers, timeout10) response.raise_for_status() # 抛出HTTP错误 # 解析JSON数据 data json.loads(response.text) songs data[result][tracks] # 遍历提取核心信息 for song in songs: # 基础信息 song_info { 排名: len(self.music_data) 1, 歌曲名: song[name], 歌手: /.join([artist[name] for artist in song[artists]]), 专辑: song[album][name], 时长: self.format_duration(song[duration]), 播放量: self.get_play_count(song[id]), # 单独获取播放量 热度值: song.get(popularity, 0), # 热度指数 收藏数: song.get(likedCount, 0), 评论数: self.get_comment_count(song[id]) # 单独获取评论数 } self.music_data.append(song_info) print(f已爬取{song_info[排名]}. {song_info[歌曲名]} - {song_info[歌手]}) except Exception as e: print(f爬取榜单失败{e}) def get_play_count(self, song_id): 获取歌曲播放量补充接口 try: url fhttps://music.163.com/api/song/detail/?id{song_id}ids[{song_id}] response requests.get(url, headersself.headers, timeout5) data json.loads(response.text) # 部分歌曲播放量字段不同做兼容 play_count data[songs][0].get(playCount, 0) return self.format_number(play_count) except: return 未知 def get_comment_count(self, song_id): 获取歌曲评论数 try: url fhttps://music.163.com/api/v1/resource/comments/R_SO_4_{song_id}/?limit1 response requests.get(url, headersself.headers, timeout5) data json.loads(response.text) comment_count data.get(total, 0) return self.format_number(comment_count) except: return 未知 staticmethod def format_duration(duration): 格式化时长毫秒→分:秒 minutes duration // 60000 seconds (duration % 60000) // 1000 return f{minutes}:{seconds:02d} staticmethod def format_number(num): 格式化数字万/亿单位 if num 1e8: return f{num / 1e8:.2f}亿 elif num 1e4: return f{num / 1e4:.2f}万 else: return str(num) def save_to_excel(self): 将数据导出为Excel try: df pd.DataFrame(self.music_data) # 按热度值降序排序 df df.sort_values(by热度值, ascendingFalse) # 保存Excel忽略索引 df.to_excel(OUTPUT_FILE, indexFalse, engineopenpyxl) print(f\n✅ 数据已成功导出至{OUTPUT_FILE}) print(f 共爬取 {len(self.music_data)} 首歌曲) except Exception as e: print(f保存Excel失败{e}) # -------------------------- 运行爬虫 -------------------------- if __name__ __main__: print( 2025网易云音乐热度爬虫开始运行 ) spider NeteaseMusicSpider() # 1. 爬取榜单数据 spider.get_board_songs(BOARD_ID) # 2. 数据清洗去重 df_temp pd.DataFrame(spider.music_data) df_temp df_temp.drop_duplicates(subset[歌曲名, 歌手], keepfirst) spider.music_data df_temp.to_dict(records) # 3. 导出Excel spider.save_to_excel() print( 爬虫运行结束 )