news 2026/6/9 20:36:07

Python 爬虫项目 音乐平台歌单与曲目信息采集

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python 爬虫项目 音乐平台歌单与曲目信息采集

前言

网络音乐平台汇聚了海量歌单、单曲、歌手、专辑等音频相关数据,这类结构化与半结构化数据在音乐推荐系统、舆情分析、音乐行业数据统计、个性化歌单生成等场景中具备极高的应用价值。传统人工整理音乐数据效率低下、数据覆盖范围有限,而依托 Python 爬虫技术能够自动化、规模化地完成歌单列表、曲目名称、演唱者、播放量、收藏量、发行时间、歌词等多维度信息的采集工作。

本次实战选取主流音乐平台作为目标站点,围绕公开歌单与曲目核心信息开展合规数据爬取,全程基于通用爬虫技术栈实现,兼顾代码通用性、运行稳定性与数据完整性。文章会从环境依赖、站点接口分析、请求伪装、数据解析、数据存储、异常处理、反爬规避、代码优化等多个维度展开讲解,搭配完整可运行代码、原理剖析、参数说明与实战踩坑总结。

为方便读者快速搭建运行环境、下载对应依赖库与工具,现将本文用到的所有第三方库官方地址、安装源链接统一整理如下:

  1. requests(网络请求库):https://pypi.org/project/requests/
  2. beautifulsoup4(网页解析库):https://pypi.org/project/beautifulsoup4/
  3. lxml(解析引擎,配合 BeautifulSoup 使用):https://pypi.org/project/lxml/
  4. json(Python 内置 JSON 解析库,Python 标准库无需额外安装):https://docs.python.org/3/library/json.html
  5. re(Python 内置正则表达式库,Python 标准库无需额外安装):https://docs.python.org/3/library/re.html
  6. csv(Python 内置 CSV 文件存储库,Python 标准库无需额外安装):https://docs.python.org/3/library/csv.html
  7. time(Python 内置时间处理库,用于请求延时):https://docs.python.org/3/library/time.html
  8. random(Python 内置随机数库,用于随机延时规避反爬):https://docs.python.org/3/library/random.html
  9. fake-useragent(随机请求头生成库):https://pypi.org/project/fake-useragent/

本文所有代码基于 Python 3.8 及以上版本开发测试,适配 Windows、Linux、macOS 全平台,读者按照链接指引完成依赖安装后即可复现全部功能。同时需要着重强调,本次爬虫仅针对平台公开展示的非版权涉密数据进行采集,所有操作需严格遵守目标网站《用户协议》与《robots 协议》,禁止大规模高频爬取、禁止盗用版权音频文件、禁止将采集数据用于商业侵权行为,技术学习与研究需在合法合规的框架内开展。

一、项目整体规划与需求分析

1.1 项目核心采集目标

结合音乐平台页面结构与公开数据维度,本次爬虫确定两大核心采集模块:歌单基础信息采集、歌单内曲目明细采集,细分采集字段如下表所示。

表格

数据分类采集字段字段说明数据类型
歌单基础信息歌单 ID平台唯一标识编号,用于关联曲目字符串 / 整型
歌单基础信息歌单名称用户创建 / 官方推荐歌单标题字符串
歌单基础信息创建者昵称歌单发布用户名称字符串
歌单基础信息创建者 ID创作者平台账号编号字符串 / 整型
歌单基础信息播放总量歌单累计播放次数整型
歌单基础信息收藏数量歌单被用户收藏次数整型
歌单基础信息分享数量歌单对外分享次数整型
歌单基础信息歌单标签风格、语种、场景等分类标签列表 / 字符串
歌单基础信息歌单简介创作者填写的歌单描述内容字符串
曲目明细信息曲目 ID单曲唯一标识编号字符串 / 整型
曲目明细信息曲目名称歌曲完整名称字符串
曲目明细信息歌手名称歌曲演唱艺人,多歌手以分隔符区分字符串
曲目明细信息专辑名称歌曲所属专辑名称字符串
曲目明细信息曲目时长歌曲播放时长,格式为分:秒字符串
曲目明细信息歌曲播放次数单首歌曲累计播放量整型

1.2 技术选型说明

本项目采用请求 + 解析 + 存储经典爬虫架构,结合目标站点特征选择对应技术组件,各组件分工明确且相互解耦:

  1. 网络请求层:使用requests库发送 HTTP/HTTPS 请求,替代 Python 原生 urllib 库,其语法简洁、支持会话保持、Cookie 携带、代理配置,能够高效模拟浏览器请求行为;搭配fake-useragent动态生成随机 UA 请求头,降低被服务器识别为爬虫程序的概率。
  2. 数据解析层:目标站点同时存在 HTML 静态页面数据与接口返回的 JSON 格式数据,因此组合使用两套解析方案。静态网页内容采用BeautifulSoup4搭配lxml解析引擎完成 DOM 节点定位与数据提取;接口返回的结构化数据直接使用 Python 内置json库解析;对于混杂在 HTML 标签内的不规则文本,使用内置re正则表达式库完成匹配提取。
  3. 防反爬层:依托timerandom库实现随机请求延时,模拟人类浏览行为的时间间隔,避免短时间内高频请求触发站点 IP 封禁、验证码拦截等反爬策略。
  4. 数据存储层:优先使用 Python 内置csv库将采集数据写入 CSV 格式文件,该格式通用性极强,可直接用 Excel、WPS、数据库工具打开查看与二次处理,无需额外部署数据库环境,适合中小型数据量采集场景。

1.3 项目执行流程

整个爬虫项目按照线性流程分步执行,逻辑清晰且便于模块拆分与故障排查,完整流程如下:

  1. 环境准备:安装所有依赖第三方库,确认 Python 运行环境正常;
  2. 站点分析:通过浏览器开发者工具抓包,分析歌单列表页、歌单详情页的 URL 规则、请求方式、请求参数、数据返回格式;
  3. 请求封装:编写通用请求函数,统一配置请求头、超时时间、异常捕获逻辑;
  4. 歌单列表爬取:遍历分类歌单页面,批量采集所有歌单的基础信息与唯一 ID;
  5. 曲目详情爬取:利用歌单 ID 拼接详情页 URL,进入对应页面提取每一首曲目的明细数据;
  6. 数据清洗:对采集到的空值、特殊符号、换行符、多余空格等脏数据进行统一清洗;
  7. 数据持久化:将清洗后的结构化数据按分类写入 CSV 文件,完成本地存储;
  8. 异常处理与日志:捕获网络超时、页面 404、数据缺失等异常,保证程序持续运行;
  9. 程序优化:针对爬取速度、反爬规避、代码复用性进行迭代优化。

二、开发环境搭建与依赖安装

2.1 Python 环境要求

本项目代码兼容Python 3.8 ~ Python 3.12全系列版本,不支持 Python 2.x 版本。建议使用官方原生 Python 环境,也可搭配 Anaconda 虚拟环境管理工具,实现多项目环境隔离,避免库版本冲突。

2.2 第三方库安装命令

结合前文给出的库链接,读者可通过 Python 包管理工具pip完成一键安装,区分常规安装与国内镜像源安装(国内网络环境推荐使用镜像源,提升下载速度)。

2.2.1 常规 pip 安装命令

打开系统命令行(CMD、PowerShell、终端),依次执行以下命令:

bash

运行

pip install requests pip install beautifulsoup4 pip install lxml pip install fake-useragent
2.2.2 国内清华镜像源安装命令(推荐)

国内访问 PyPI 官方源速度较慢,使用清华大学开源软件镜像站可大幅提升安装效率,命令如下:

bash

运行

pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple pip install beautifulsoup4 lxml -i https://pypi.tuna.tsinghua.edu.cn/simple pip install fake-useragent -i https://pypi.tuna.tsinghua.edu.cn/simple

2.3 环境校验方法

安装完成后,在命令行输入python进入 Python 交互式环境,执行导入语句验证库是否安装成功,若无报错则代表环境搭建完成:

python

运行

import requests from bs4 import BeautifulSoup from fake_useragent import UserAgent

若提示ModuleNotFoundError,说明对应库未安装成功,需重新执行安装命令。

三、目标站点抓包与接口分析

爬虫开发的核心前提是分析目标站点的数据传输逻辑,本章节使用 Chrome 浏览器开发者工具完成抓包分析,区分静态页面渲染与异步接口加载两种数据形式。

3.1 浏览器抓包基础操作

  1. 打开浏览器进入音乐平台歌单分类页面,按下F12键唤起开发者工具,切换至 **Network(网络)** 面板;
  2. 勾选Preserve log(保留日志)选项,刷新当前页面,面板内会加载出当前页面所有的请求记录;
  3. 请求记录分为DocXHRJSCSSImg等类型,其中Doc代表 HTML 主页面,XHR/Fetch代表前端异步加载的接口请求,也是动态数据的主要来源;
  4. 点击单条请求,可查看Request URL(请求地址)Request Method(请求方式)Request Headers(请求头)Query String Parameters(请求参数)Response(响应内容)五大核心信息。

3.2 歌单列表页分析

主流音乐平台的歌单列表分为分页展示形式,URL 具备明显的页码参数特征。经过抓包分析得出以下关键结论:

  1. 请求方式:歌单列表页统一为GET请求,无复杂 POST 加密参数,请求门槛较低;
  2. URL 规则:基础 URL + 分页参数,格式示例:https://xxx.com/playlist?cat=全部&page=1,其中page为分页页码,修改该参数即可遍历所有分页歌单;
  3. 数据形式:歌单名称、创建者、播放量等基础信息一部分直接渲染在 HTML 页面中,可通过 BeautifulSoup 解析 DOM 节点提取;部分实时播放数据由 XHR 异步接口返回 JSON 格式数据;
  4. 关键 DOM 节点:所有歌单条目统一嵌套在同一个 class 属性的 div/li 标签内,每一条歌单为独立子节点,歌单 ID 隐藏在标签属性、链接地址当中,是关联曲目数据的核心字段。

3.3 歌单详情页与曲目接口分析

点击任意歌单进入详情页面,继续抓包分析曲目数据加载逻辑:

  1. 歌单详情页 URL 规则:基础详情 URL + 歌单 ID,格式示例:https://xxx.com/playlist?id=123456,通过列表页提取的歌单 ID 即可拼接出所有歌单详情地址;
  2. 曲目数据加载形式:绝大部分平台不会将上百条曲目直接渲染在 HTML 中,而是通过异步 XHR 接口分页加载曲目列表,接口携带歌单 ID、起始位置、每页条数等参数;
  3. 响应格式:曲目数据全部为标准 JSON 格式,字段层级清晰,包含曲目 ID、歌名、歌手、时长、专辑等所有需要采集的字段,解析难度远低于 HTML 页面;
  4. 反爬特征:详情页接口存在基础请求头校验,缺失User-Agent会直接返回 403 拒绝访问,因此请求头伪装是必不可少的环节。

3.4 反爬机制总结

结合抓包与实测,该音乐平台针对普通爬虫设置了基础反爬策略,无高强度加密、验证码、指纹校验等复杂反爬,主要规则如下:

  1. 校验请求头:拒绝无User-Agent的非法请求,识别简易爬虫;
  2. 频率限制:短时间内连续发送大量请求,会触发 IP 临时封禁,表现为页面无法访问、接口返回空数据;
  3. Cookie 校验:部分接口需要携带页面 Cookie 才能正常返回数据,纯裸请求会数据缺失; 基于以上规则,本项目采用随机 UA + 会话保持 + 随机延时的组合方案规避反爬。

四、通用请求模块开发与原理详解

通用请求函数是整个爬虫的基础组件,负责统一处理网络请求、请求头伪装、超时控制、异常捕获、会话保持,后续所有页面与接口请求都会复用该函数,实现代码解耦与复用。

4.1 通用请求函数完整代码

python

运行

# 导入所需依赖库 import requests import time import random from fake_useragent import UserAgent # 初始化随机UA对象 ua = UserAgent() # 创建会话对象,实现Cookie自动携带与会话保持 session = requests.Session() def get_page_response(url, timeout=10): """ 通用网络请求函数,统一处理GET请求、请求头、延时、异常 :param url: 目标请求地址 :param timeout: 请求超时时间,默认10秒 :return: 成功返回响应对象,失败返回None """ # 构建请求头,随机生成浏览器UA headers = { "User-Agent": ua.random, "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.9", "Referer": "https://music.example.com/" } try: # 随机延时1~3秒,模拟人类浏览间隔 sleep_time = random.uniform(1, 3) time.sleep(sleep_time) # 发送GET请求 response = session.get(url=url, headers=headers, timeout=timeout) # 设置响应编码,解决中文乱码问题 response.encoding = response.apparent_encoding # 判断请求状态码,200代表请求成功 if response.status_code == 200: return response else: print(f"请求失败,状态码:{response.status_code},请求地址:{url}") return None except requests.exceptions.Timeout: print(f"请求超时,地址:{url}") return None except requests.exceptions.ConnectionError: print(f"网络连接异常,地址:{url}") return None except Exception as e: print(f"未知异常:{str(e)},请求地址:{url}") return None

4.2 代码模块原理逐行解析

4.2.1 库导入与对象初始化原理
  1. from fake_useragent import UserAgent:该库内置了海量主流浏览器(Chrome、Firefox、Edge、Safari 等)的User-Agent字符串,ua = UserAgent()完成对象实例化后,调用ua.random即可每次生成随机 UA,避免单一 UA 被服务器标记为爬虫。相较于手动编写固定 UA,动态随机 UA 的伪装效果更强。
  2. session = requests.Session()requests库的会话对象,核心作用是会话保持与 Cookie 自动管理。普通requests.get()属于单次独立请求,不会保留上一次请求的 Cookie;而 Session 对象会自动存储、携带站点下发的 Cookie,模拟真实浏览器的会话状态,完美适配需要 Cookie 校验的接口与页面。
4.2.2 请求头构建原理

请求头(Headers)是客户端向服务器传递的身份标识与访问配置,本项目中三个核心请求头作用如下:

  1. User-Agent:告知服务器当前客户端是什么浏览器、操作系统、设备型号,是站点最基础的反爬校验项,缺失该字段会直接拦截请求。
  2. Accept:声明客户端能够接收的数据类型,模拟浏览器正常的资源接收规则。
  3. Referer:标识当前请求的来源页面,部分站点会校验该字段,防止跨站非法请求,填写站点首页地址可进一步提升伪装度。
4.2.3 随机延时原理

random.uniform(1, 3)会生成1 到 3 秒之间的随机浮点数,搭配time.sleep()实现随机等待。固定时长延时容易被行为分析系统识别,而无规律的随机延时高度模拟人工点击页面的行为特征,是规避 IP 频率限制最简单有效的方案。延时区间可根据站点严格程度调整,反爬严格的站点可扩大至 2~5 秒。

4.2.4 异常捕获原理

网络请求属于不稳定 IO 操作,存在超时、断网、服务器宕机、页面 404 等多种异常场景,代码中使用分层异常捕获:

  1. requests.exceptions.Timeout:捕获请求超时异常,当服务器响应速度过慢、网络卡顿,超过设定的 timeout 时间后触发;
  2. requests.exceptions.ConnectionError:捕获连接异常,对应断网、域名无法解析、服务器拒绝连接等场景;
  3. 通用Exception:捕获其余所有未知异常,保证程序不会因为单条请求失败而整体崩溃,实现容错运行
4.2.5 编码处理原理

response.encoding = response.apparent_encoding用于解决网页中文乱码问题。部分站点不会在响应头中声明编码格式,response.encoding默认识别错误,导致中文显示为问号、乱码。apparent_encoding会自动分析网页内容,识别真实编码(UTF-8、GBK、GB2312 等),是 Python 爬虫处理中文乱码的标准解决方案。

五、歌单列表信息采集模块开发与原理

在通用请求函数的基础上,开发歌单列表采集模块,实现分页遍历、HTML 数据解析、歌单基础信息提取、数据清洗功能,同时将采集结果临时存储,为后续曲目爬取提供歌单 ID 数据源。

5.1 歌单列表采集完整代码

python

运行

from bs4 import BeautifulSoup import re # 定义全局列表,存储所有歌单信息 playlist_list = [] def crawl_playlist_list(total_page=5): """ 爬取分页歌单列表信息 :param total_page: 需要爬取的总页数,默认爬取5页 :return: 无返回值,数据存入全局列表 """ # 歌单列表基础URL,page为分页参数 base_url = "https://music.example.com/playlist?cat=全部&page={}" # 正则表达式,用于提取标签内数字(播放量、收藏量) num_pattern = re.compile(r"\d+") for page in range(1, total_page + 1): # 拼接分页URL page_url = base_url.format(page) print(f"正在爬取第 {page} 页歌单,地址:{page_url}") # 调用通用请求函数获取页面响应 response = get_page_response(page_url) if not response: continue # 使用lxml解析引擎实例化BeautifulSoup对象 soup = BeautifulSoup(response.text, "lxml") # 定位所有歌单条目父节点 playlist_items = soup.find_all("li", class_="playlist-item") # 遍历单页所有歌单 for item in playlist_items: # 1. 提取歌单名称 try: playlist_name = item.find("a", class_="playlist-name").get_text(strip=True) except: playlist_name = "未知歌单" # 2. 提取歌单ID(从链接地址中截取) try: playlist_href = item.find("a", class_="playlist-name")["href"] playlist_id = num_pattern.search(playlist_href).group() except: playlist_id = "0" # 3. 提取创建者昵称 try: creator_name = item.find("span", class_="creator").get_text(strip=True) except: creator_name = "未知用户" # 4. 提取播放总量 try: play_count_text = item.find("span", class_="play-count").get_text(strip=True) play_count = num_pattern.findall(play_count_text)[0] except: play_count = "0" # 5. 提取收藏数量 try: collect_text = item.find("span", class_="collect-count").get_text(strip=True) collect_count = num_pattern.findall(collect_text)[0] except: collect_count = "0" # 6. 提取歌单标签 try: tag_list = item.find_all("span", class_="tag") tag_str = ",".join([tag.get_text(strip=True) for tag in tag_list]) except: tag_str = "无标签" # 组装单条歌单数据字典 playlist_info = { "歌单ID": playlist_id, "歌单名称": playlist_name, "创建者": creator_name, "播放量": play_count, "收藏量": collect_count, "歌单标签": tag_str } # 添加至全局列表 playlist_list.append(playlist_info) print(f"歌单列表爬取完成,共采集 {len(playlist_list)} 个歌单")

5.2 歌单列表模块原理详解

5.2.1 分页遍历原理

代码中for page in range(1, total_page + 1)实现分页循环,结合base_url.format(page)动态拼接每一页的 URL。该逻辑基于抓包得到的分页 URL 规则,修改total_page参数即可自由控制爬取页数,灵活性极强。若站点分页存在最大页数限制,可增加页面判断逻辑,到达尾页后自动终止循环。

5.2.2 BeautifulSoup 节点定位原理

BeautifulSoup是 HTML/XML 文档解析工具,核心功能是将不规则的 HTML 字符串转化为结构化的 DOM 树,通过节点标签、class、id、属性实现精准定位:

  1. soup = BeautifulSoup(response.text, "lxml"):将页面 HTML 文本传入解析器,指定lxml作为解析引擎。lxml 基于 C 语言开发,解析速度快、容错性高,是生产环境下的首选引擎。
  2. soup.find_all("li", class_="playlist-item")find_all()方法用于批量查找所有匹配节点,参数含义:第一个参数为 HTML 标签名,class_匹配标签的 class 属性(使用 class_是因为 class 为 Python 保留关键字)。该语句会一次性获取当前页面所有歌单条目节点。
  3. item.find("a", class_="playlist-name")find()方法用于查找单个匹配节点,只返回第一个符合条件的标签,适用于单条数据提取。
  4. get_text(strip=True):提取标签内的纯文本内容,strip=True会自动去除文本首尾的空格、换行符、制表符,完成基础数据清洗,避免多余空白字符影响后续存储与使用。
5.2.3 正则表达式提取原理

部分数据(如歌单 ID、播放量)混杂在 URL 链接、中文文本当中,无法通过 DOM 节点直接提取纯数字,因此使用re正则库处理:

  1. num_pattern = re.compile(r"\d+"):编译正则表达式规则,\d+代表匹配一个及以上数字,编译后的正则对象可重复使用,提升执行效率。
  2. num_pattern.search(playlist_href).group()search()方法从字符串中查找第一个匹配规则的内容,group()提取匹配到的结果,用于从歌单链接中截取纯数字格式的歌单 ID。
  3. num_pattern.findall(play_count_text)findall()方法查找字符串中所有匹配规则的内容,返回列表,适用于从 “播放:123 万” 这类混合文本中提取数字。
5.2.4 容错与空值处理原理

每一个字段提取逻辑都包裹在try...except异常捕获结构中。网页结构可能存在个别条目字段缺失、标签层级变化的情况,若直接提取会触发AttributeError报错。捕获异常后为字段赋予默认值(未知歌单、0、无标签等),保证单条歌单数据异常不会中断整个分页爬取流程,进一步强化程序稳定性。

5.2.5 数据结构化原理

将每一条歌单信息组装为字典格式,字典的键对应数据表字段,值为采集到的内容。字典是 Python 中最常用的结构化数据载体,格式清晰、便于遍历、写入文件或数据库,也是后续数据存储模块的标准输入格式。所有歌单字典统一存入全局列表playlist_list,实现数据批量管理。

六、曲目明细采集模块开发与原理

曲目明细是本项目的核心采集内容,依托上一模块获取的歌单 ID拼接详情接口地址,解析 JSON 格式响应数据,提取每一首曲目的完整信息。该模块分为接口请求、JSON 解析、数据清洗三大核心环节。

6.1 曲目明细采集完整代码

python

运行

import json # 定义全局列表,存储所有曲目信息 track_list = [] def crawl_track_info(): """ 根据歌单ID爬取对应歌单内所有曲目信息 :return: 无返回值,数据存入全局列表 """ # 曲目接口基础URL,参数为歌单ID track_api_url = "https://music.example.com/api/track?playlistId={}" # 遍历所有已采集的歌单 for playlist in playlist_list: playlist_id = playlist.get("歌单ID") playlist_name = playlist.get("歌单名称") print(f"正在爬取歌单【{playlist_name}】曲目,歌单ID:{playlist_id}") # 拼接曲目接口地址 api_url = track_api_url.format(playlist_id) # 调用通用请求函数获取接口响应 response = get_page_response(api_url) if not response: continue try: # 解析JSON格式响应数据 json_data = json.loads(response.text) except json.JSONDecodeError: print(f"歌单{playlist_id}接口返回非JSON数据,跳过该歌单") continue # 从JSON层级中提取曲目数组 track_array = json_data.get("data", {}).get("trackList", []) if not track_array: print(f"歌单{playlist_id}暂无曲目数据") continue # 遍历单首曲目 for track in track_array: # 提取曲目基础字段 track_id = track.get("trackId", "0") track_name = track.get("trackName", "未知曲目") singer = track.get("singerName", "未知歌手") album_name = track.get("albumName", "未知专辑") duration = track.get("duration", "00:00") track_play_count = track.get("playCount", "0") # 组装单条曲目数据字典 track_info = { "所属歌单ID": playlist_id, "所属歌单名称": playlist_name, "曲目ID": track_id, "曲目名称": track_name, "歌手": singer, "专辑": album_name, "曲目时长": duration, "单曲播放量": track_play_count } track_list.append(track_info) print(f"曲目爬取完成,共采集 {len(track_list)} 首曲目数据")

6.2 曲目采集模块原理详解

6.2.1 接口 URL 拼接逻辑

该模块的数据源完全依赖歌单列表模块的结果,通过playlist.get("歌单ID")取出每条歌单的唯一编号,拼接异步接口 URL。这种上下游模块关联的设计是分层爬虫的典型思路:先爬取索引数据,再根据索引爬取明细数据,逻辑分层清晰,便于单独调试每一个模块。

6.2.2 JSON 数据解析原理

目标曲目接口返回标准 JSON 字符串,Python 内置json库是解析此类数据的最优选择:

  1. json.loads(response.text):将接口返回的JSON 格式字符串转换为 Python 字典 / 列表组合的结构化对象,转换后可直接通过键取值,语法简单、执行效率高。
  2. json.JSONDecodeError异常捕获:当接口返回空数据、HTML 错误页面、加密文本时,字符串不符合 JSON 格式,会触发该异常。捕获异常并跳过当前歌单,防止程序终止。
  3. 多层级取值:json_data.get("data", {}).get("trackList", [])安全取值写法。JSON 数据存在多层嵌套,get()方法相较于直接[]取值更加安全:若上一层键不存在,返回默认空字典 / 空列表,不会触发键不存在的报错,极大提升代码容错性。
6.2.3 字段提取与默认值原理

track.get("trackId", "0")同样使用get()方法提取字段,并设置默认值。部分小众曲目、下架曲目会出现字段缺失的情况,设置默认值 “0”“未知曲目” 等,保证每一条曲目数据字段完整性,统一数据格式,为后续存储与数据分析奠定基础。

6.2.4 数据关联设计原理

曲目字典中额外加入所属歌单ID所属歌单名称两个字段,实现曲目与歌单的关联绑定。在后续数据分析、表格筛选时,可通过歌单 ID 反向查询对应的所有曲目,完成多表关联逻辑,模拟简易数据库外键的设计思想,让采集的数据具备业务关联价值。

七、CSV 数据存储模块开发与原理

数据采集完成后,需要将内存中的列表字典数据持久化到本地文件,本项目选用 CSV 格式存储,编写通用 CSV 写入函数,分别存储歌单数据与曲目数据,并讲解文件存储的核心原理。

7.1 CSV 数据存储完整代码

python

运行

import csv def save_to_csv(data_list, file_name, fieldnames): """ 通用CSV文件写入函数 :param data_list: 待写入的字典列表数据 :param file_name: 生成的CSV文件名称 :param fieldnames: CSV表头列表,对应字典键名 """ # 使用utf-8-sig编码,解决Excel打开中文乱码问题 with open(file_name, "w", newline="", encoding="utf-8-sig") as f: # 创建CSV写入器 writer = csv.DictWriter(f, fieldnames=fieldnames) # 写入表头 writer.writeheader() # 批量写入所有数据行 writer.writerows(data_list) print(f"数据已成功保存至文件:{file_name}") # 主执行函数,串联所有爬虫模块 def main(): # 1. 爬取歌单列表(爬取前5页) crawl_playlist_list(total_page=5) # 2. 爬取所有歌单对应的曲目 crawl_track_info() # 定义歌单CSV表头 playlist_header = ["歌单ID", "歌单名称", "创建者", "播放量", "收藏量", "歌单标签"] # 保存歌单数据 save_to_csv(playlist_list, "音乐平台歌单数据.csv", playlist_header) # 定义曲目CSV表头 track_header = ["所属歌单ID", "所属歌单名称", "曲目ID", "曲目名称", "歌手", "专辑", "曲目时长", "单曲播放量"] # 保存曲目数据 save_to_csv(track_list, "音乐平台曲目数据.csv", track_header) # 程序入口 if __name__ == "__main__": main()

7.2 CSV 存储模块原理详解

7.2.1 文件打开编码原理

encoding="utf-8-sig"是 Python 爬虫写入 CSV 文件的标准编码配置。Windows 系统下的 Excel 软件默认使用 GBK 编码解析 CSV 文件,若使用普通utf-8编码,中文会出现大面积乱码。utf-8-sig会在文件头部添加 BOM 标记,兼容 Excel、WPS、记事本等全平台软件,完美解决中文乱码问题。

newline=""用于去除 CSV 文件中多余的空行。Windows 系统下使用csv库写入文件时,默认会产生换行冗余,设置newline=""可屏蔽该问题,保证表格格式整洁。

7.2.2 csv.DictWriter 工作原理

csv.DictWriter是专门针对字典列表设计的写入器,完美适配本项目的数据格式:

  1. 初始化时传入文件对象与fieldnames表头列表,表头顺序、名称必须和字典的键一一对应;
  2. writer.writeheader():单独写入 CSV 第一行表头,用于标识每一列数据含义;
  3. writer.writerows(data_list):批量写入字典列表,每一个字典自动转化为表格中的一行数据,键对应列表头,值对应单元格内容,无需手动循环逐行写入,代码简洁且执行效率高。
7.2.3 模块化串联原理

main()函数作为整个爬虫项目的程序入口,按照业务流程依次调用歌单爬取、曲目爬取、数据存储三大模块,实现功能串联。这种模块化拆分的优势在于:可单独运行某一个模块进行调试、可灵活调整执行顺序、后续新增功能(如数据清洗、数据库存储)可直接在主函数中扩展,符合软件工程的模块化开发思想。

7.2.4 程序入口判断原理

if __name__ == "__main__"是 Python 标准程序入口判断语句:当文件直接作为主程序运行时,该条件成立,执行main()函数;当文件被其他 Python 文件作为模块导入时,条件不成立,不会自动执行爬虫逻辑。该写法让代码既可以独立运行,也可以作为工具库被其他项目调用。

八、数据清洗、异常优化与项目拓展方案

8.1 现有数据脏数据问题与清洗方案

实际爬取过程中会产生各类脏数据,影响数据可用性,结合实战场景整理常见问题与清洗代码:

  1. 数字单位统一:平台播放量会出现 “1.2 万”“10 万 +” 等文本格式,无法直接用于数值统计。可编写转换函数,将中文单位转换为纯数字。
  2. 特殊符号过滤:歌名、歌单名称中存在 emoji、特殊标点、换行符,使用正则表达式匹配并过滤。
  3. 重复数据去重:分页爬取可能出现重复歌单 / 曲目,通过唯一 ID(歌单 ID、曲目 ID)进行去重。

基础数据清洗示例代码:

python

运行

def clean_text(text): """文本清洗函数,过滤特殊符号与空白字符""" # 过滤emoji与特殊符号 emoji_pattern = re.compile("[\U00010000-\U0010ffff]") text = emoji_pattern.sub("", text) # 去除首尾空格 text = text.strip() return text

8.2 反爬策略进阶优化

针对站点加强反爬后的优化方案,在现有代码基础上迭代升级:

  1. 代理 IP 配置:当 IP 被封禁后,引入代理 IP 池,在session.get()中增加proxies参数,切换不同 IP 发起请求,突破 IP 限制。
  2. Cookie 持久化:将会话 Cookie 保存至本地文件,下次运行程序直接加载 Cookie,跳过初始页面校验。
  3. 请求头完整模拟:补充CookieSec-Fetch-*系列请求头,完全复刻浏览器请求特征。
  4. 动态延时梯度:访问详情接口时延长延时,区分列表页与详情页的等待时间。

8.3 项目功能拓展方向

本基础项目可基于现有架构进行多维度功能拓展,适配不同业务需求:

  1. 歌词采集:基于曲目 ID 对接歌词接口,抓取歌曲完整歌词,拓展文本数据维度。
  2. 数据库存储:将 CSV 存储替换为 MySQL、SQLite、MongoDB 数据库,适配海量数据存储与查询场景。
  3. 增量爬取:记录上一次爬取时间与最新歌单 ID,实现增量更新,避免重复爬取历史数据。
  4. 多线程 / 异步爬取:引入threadingaiohttp实现异步并发请求,大幅提升爬取效率(并发爬取需严格控制并发数,避免恶意攻击站点)。
  5. 数据可视化:结合 Matplotlib、Pandas 对采集的播放量、收藏量数据进行统计分析与图表展示。

8.4 合规性与运维注意事项

  1. 严格遵守目标站点robots.txt协议,不爬取协议禁止的路径与数据;
  2. 控制爬取频率与并发数量,不对站点服务器造成压力;
  3. 禁止爬取版权音频、付费内容、用户隐私信息;
  4. 定期监测站点页面结构与接口变化,DOM 节点、URL、参数变更后及时调整代码。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 20:32:17

美国创业做 App,为啥选中国技术团队?

这些年接触很多美国客户,起初他们觉得 “美国公司,就该找本地团队开发 App”。但项目做下来,不少老板改变了想法。 开发 App,可不只看写代码,这些方面同样重要: 产品规划:定方向、设功能&#x…

作者头像 李华
网站建设 2026/6/9 20:30:13

终极指南:如何在Windows上使用JoyCon手柄玩转PC游戏

终极指南:如何在Windows上使用JoyCon手柄玩转PC游戏 【免费下载链接】JoyCon-Driver A vJoy feeder for the Nintendo Switch JoyCons and Pro Controller 项目地址: https://gitcode.com/gh_mirrors/jo/JoyCon-Driver JoyCon-Driver是一款专为Windows平台设…

作者头像 李华
网站建设 2026/6/9 20:29:56

XZ1821B 3A 9-100V 扭扭车 平衡车 太阳能 电动设备 电池充电器

这是一款单片集成可设定输出电流的开关型降压恒压驱动器,可工作在宽输入电压范围具有优良的负载和线性调整度。安全保护机制包括每周期的峰值限流、软启动、过压保护和温度保护,带短路保护。需要非常少的常规外围器件。在%2B12输入,可以连续输…

作者头像 李华
网站建设 2026/6/9 20:29:00

Unity3D网页演示包(含Web Player插件与一键启动页)

本文还有配套的精品资源,点击获取 简介:直接在浏览器里跑的Unity3D小样,不用编译、不用配置,点开WebPlayer.html就能看。里面装好了Windows平台的Unity Web Player安装程序(UnityWebPlayer.exe)&#xf…

作者头像 李华