1. 泡椒音乐搜索接口爬虫实战
最近在做一个音乐数据分析项目,需要批量获取特定歌手的曲目信息。泡椒音乐(pjmp3.com)的搜索接口恰好能满足这个需求。下面分享一个完整的Python爬虫实现,从搜索关键词到获取歌曲详细信息的一站式解决方案。
这个爬虫的核心逻辑分为三步:模拟搜索请求、解析结果列表、提取单曲详情。整个过程用到了requests发起HTTP请求、lxml解析HTML页面结构、re正则表达式提取关键数据。先来看基础环境准备:
python复制import requests
from lxml import etree
import re
2. 请求头与Cookie配置要点
2.1 浏览器指纹模拟
现代网站都会检测请求头来识别爬虫。泡椒音乐对以下头部字段特别敏感:
python复制headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
"accept-language": "zh-CN,zh;q=0.9",
"sec-ch-ua": "\"Not;A=Brand\";v=\"99\"...",
"sec-ch-ua-platform": "\"Windows\""
}
提示:Sec-CH-UA系列头是Chrome的客户端提示(Client Hints)功能,缺少这些头会被识别为低版本浏览器或自动化工具。
2.2 Cookie管理策略
示例中的Cookie包含会话标识和统计参数:
python复制cookies = {
"sl-session": "3Fl/W554pmgUv0WaqyjrLw==",
"Hm_lvt_jfee1h5kk8a": "1754279868,1755653950"
}
实测发现sl-session是必填项,可以通过以下方式获取:
- 浏览器正常访问网站后从开发者工具复制
- 首次请求时获取Set-Cookie再带入后续请求
3. 搜索接口逆向分析
3.1 关键词参数构造
搜索接口URL为https://pjmp3.com/search.php,使用GET方式传参:
python复制params = {
"keyword": "方大同" # 支持歌手名/歌曲名
}
有趣的是,这个接口对URL编码处理比较宽松,直接传中文也能正常响应。
3.2 结果页解析技巧
返回的HTML中歌曲列表是这样的结构:
html复制<div class="search-result-list-content">
<a href="/song.php?id=12345">...</a>
<!-- 更多歌曲 -->
</div>
使用XPath提取歌曲ID时要注意:
python复制hrefs = html.xpath('//div[@class="search-result-list-content"]/a/@href')
song_ids = [h.split('=')[-1] for h in hrefs] # 提取id部分
4. 歌曲详情抓取实战
4.1 音频地址提取
歌曲页面的关键数据藏在JavaScript代码中,采用正则匹配:
python复制audio_url = re.findall('url\: \'(.*?)\'', response.text)[-1]
song_name = re.findall('name\: \'(.*?)\'', response.text)[-1]
artist = re.findall('artist\: \'(.*?)\'', response.text)[-1]
这里有几个易错点:
- 正则表达式要用非贪婪模式
.*? - 取最后一个匹配项
[-1]是因为页面可能有多个相似片段 - 部分歌曲的artist字段可能为空,需要异常处理
4.2 反爬应对方案
当请求频率过高时,可能会遇到:
- 返回403状态码
- 返回验证码页面
- 限制IP访问
建议的解决方案:
- 在每个请求间添加随机延迟(1-3秒)
- 使用代理IP池轮询
- 定期更新Cookie和User-Agent
5. 完整代码优化版
以下是增强稳定性的实现:
python复制import time
import random
from urllib.parse import quote
def search_songs(keyword):
session = requests.Session()
# 首次请求获取必要Cookie
session.get("https://pjmp3.com", headers=headers)
params = {"keyword": quote(keyword)}
try:
resp = session.get(
"https://pjmp3.com/search.php",
params=params,
headers=headers,
timeout=10
)
html = etree.HTML(resp.text)
song_links = html.xpath('//div[contains(@class,"search-result-list")]//a/@href')
results = []
for link in song_links[:5]: # 限制前5首防止被封
song_id = link.split('=')[-1]
detail = get_song_detail(session, song_id)
if detail:
results.append(detail)
time.sleep(random.uniform(1, 2))
return results
except Exception as e:
print(f"搜索失败: {str(e)}")
return []
def get_song_detail(session, song_id):
try:
resp = session.get(
f"https://pjmp3.com/song.php?id={song_id}",
headers=headers,
timeout=8
)
# 提取音频信息...
except:
return None
6. 数据存储与扩展应用
获取到的数据可以:
- 存入CSV文件方便分析
- 导入数据库建立音乐库
- 结合Flask等框架构建音乐API服务
存储示例:
python复制import csv
def save_to_csv(data, filename):
with open(filename, 'a', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(['name', 'artist', 'url'])
for item in data:
writer.writerow([item['name'], item['artist'], item['url']])
在实际使用中,这个爬虫平均每秒能处理2-3首歌曲信息。对于需要大规模采集的情况,建议使用分布式爬虫框架(如Scrapy)配合代理IP服务。
