适合小白的爬虫练习Day1-音乐下载器
一、前言
环境使用
- Python 3.10
- Pycharm
模块使用
- requests
- parsel
- prettytable
- pyinstaller
二、爬虫基本实现流程
1. 数据来源分析
(1). 明确需求
明确采集的网站以及数据内容
- 单首歌曲采集
- 网址:https://www.gequbao.com/music/112019
- 数据:歌曲链接(播放地址)
(2). 抓包分析
通过开发者工具,进行分析对应的数据位置
2. 代码实现步骤
(1). 发送请求
模拟浏览器对 url 地址发送请求
模拟浏览器
可以直接复制开发者工具中 --> 标头 --> 请求标头 --> UA --> 复制到代码中(构建headers的键值对)
# 导入数据请求模块
import requests # 需要 pip install requests
def get_response(url):
"""
def python关键字 用于定义函数
get_response 函数名 (自定义变量)
url 形式参数 (调用get_response函数需要传入一个url链接参数进来)
模拟浏览器对 url 地址发送请求
:param url: url链接地址
:return: url的响应体对象
"""
# 模拟浏览器
headers = {
# User-Agent 用户代理 表示浏览器基本身份信息 (一种简单反反爬方法)
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'
}
# 发送请求:调用 requests 里面 get 请求方法 ( GET 请求方法是根据开发者工具所显示的方法)
response = requests.get(url=url, headers=headers)
# 返回内容
return response
(2). 获取数据
获取服务器返回的响应数据
- response.text
- 获取响应文本数据
- response.json()
- 获取响应json数据
- response.content
- 获取响应的二进制数据
(3). 解析数据
def get_music():
"""获取音频链接"""
# 音频数据包地址
link = 'https://www.gequbao.com/api/play_url?id=112019&json=1'
# 发送请求 ( 调用定义好的函数即可 )
response = get_response(url=link)
# 获取数据
json_data = response.json()
# 解析数据, 提取音频链接
music_url = json_data['data']['url']
# 返回音频链接
return music_url
(4). 保存数据
def save_music(title, url):
"""
保存音频数据的函数
:param title: 歌名
:param url: 音频链接
:return:
"""
# 自动创建文件夹:
# 判断如果在和当前的 py文件同级里面没有 music文件夹 则自动创建
if not os.path.exists('./music'):
# 自动创建 music文件夹
os.mkdir('./music')
# 获取音频数据内容
music_content = get_response(url=url).content
# 保存数据
with open('./music/' + title + '.mp3', mode='wb') as f:
f.write(music_content)
3. 完整代码
import os
# 导入数据请求模块
import requests # 需要 pip install requests
def get_response(url):
"""
- def python关键字 用于定义函数
- get_response 函数名 (自定义变量)
- url 形式参数 (调用get_response函数需要传入一个url链接参数进来)
模拟浏览器对 url 地址发送请求
:param url: url链接地址
:return: url的响应体对象
"""
# 模拟浏览器
headers = {
# User-Agent 用户代理 表示浏览器基本身份信息 (一种简单反反爬方法)
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'
}
# 发送请求:调用 requests 里面 get 请求方法 ( GET 请求方法是根据开发者工具所显示的方法)
response = requests.get(url=url, headers=headers)
# 返回内容
return response
def get_music():
"""获取音频链接"""
# 音频数据包地址
link = 'https://www.gequbao.com/api/play_url?id=112019&json=1'
# 发送请求 ( 调用定义好的函数即可 )
response = get_response(url=link)
# 获取数据
json_data = response.json()
# 解析数据, 提取音频链接
music_url = json_data['data']['url']
# 返回音频链接
return music_url
def save_music(title, url):
"""
保存音频数据的函数
:param title: 歌名
:param url: 音频链接
:return:
"""
# 自动创建文件夹:
# 判断如果在和当前的 py文件同级里面没有 music文件夹 则自动创建
if not os.path.exists('./music'):
# 自动创建 music文件夹
os.mkdir('./music')
# 获取音频数据内容
music_content = get_response(url=url).content
# 保存数据
with open('./music/' + title + '.mp3', mode='wb') as f:
f.write(music_content)
# 函数入口:当你的代码被当做模块进行调用时, 下面的代码不会被执行
if __name__ == '__main__':
# 调用获取音频链接的函数
music_url = get_music()
# 调用保存音频数据的函数
save_music(title='稻香', url=music_url)
三、搜索下载功能
对于不同歌曲,请求链接变化规律
稻香:https://www.gequbao.com/api/play_url?id=112019&json=1
晴天:https://www.gequbao.com/api/play_url?id=402856&json=1
如果爱忘了:https://www.gequbao.com/api/play_url?id=19734&json=1
主要改变的参数:id=xxx(歌曲id)
1. 数据来源分析
(1). 明确需求
- 网址:https://www.gequbao.com/s/%E7%A8%BB%E9%A6%99
- 数据:歌曲ID 歌曲名字
(2). 抓包分析
- 开发者工具
- 刷新网页
- 关键字搜索 关键字:歌曲ID
2. 代码实现步骤
(1). 搜索歌曲信息
def search_music(word):
"""搜索歌曲信息"""
# 请求网址:搜索链接
search_url = f'https://www.gequbao.com/s/{word}'
# 发送请求
html_data = get_response(url=search_url).text
# 创建空列表
info = []
tb = PrettyTable()
tb.field_names = ['序号', '歌名', '歌手']
page = 0
# 把获取到的html字符串数据, 转成可解析的对象
selector = parsel.Selector(html_data)
# CSS选择器: 根据标签的属性提取数据
rows = selector.css('.row')[1:-1]
# for循环遍历, 提取列表里面的元素
for row in rows:
music_name = row.css('.text-primary::text').get().strip() # 歌名
music_id = row.css('.text-primary::attr(href)').get().split('/')[-1] # 歌曲链接
author = row.css('.text-success::text').get().strip() # 歌手
dit = {
'歌名': music_name,
'ID': music_id
}
tb.add_row([page, music_name, author])
info.append(dit)
page += 1
print(tb)
return info
(2). 主函数
def main():
"""主函数"""
while True:
msg = """**************************************************
欢迎使用【音乐下载系统】V1.0
请选择你想要进行的操作
1. 单首歌曲下载
2. 批量下载全部
q. 退出系统
**************************************************"""
print(msg)
# 输入关键词进行搜索
key = input('请选择你想要进行的操作: ')
if key == 'q':
exit()
elif key == '1':
word = input('请输入你想要下载的歌曲/歌手: ')
# 调用搜索 返回的 info列表 ——> 字典
info = search_music(word)
# 输入要下载的歌曲的序号
num = input('请输入你要下载的歌曲的序号: ')
# 提取音乐ID
song_id = info[int(num)]['ID']
# 提取歌名
song_title = info[int(num)]['歌名']
# 获取音频链接
music_url = get_music(id=song_id)
# 保存数据
save_music(song_title, music_url)
print()
# for循环遍历, 提取列表里面的元素
elif key == '2':
word = input('请输入你想要下载的歌曲/歌手: ')
# 调用搜索 返回的 info列表 ——> 字典
info = search_music(word)
for item in info:
song_id = item['ID'] # 音乐ID
song_title = item['歌名'] # 歌名
# 获取音频链接
music_url = get_music(id=song_id)
# 保存数据
save_music(song_title, music_url)
print()
else:
print('输入有误!!!')
print()
四、打包
采用 pyinstaller (需要安装 pip install pyinstaller)
命令 pyinstaller -F 文件名(py文件).py
pyinstaller -F 歌曲.py
四、完整代码
"""
案例分为三个部分
1. 采集单首歌曲内容
2. 实现搜索下载功能 (选择 单首/多首 下载)
3. 把python程序打包成exe软件
"""
# 导入文件操作模块 (内置模块 不用安装)
import os
# 导入数据请求模块
import requests # (需要安装 pip install requests)
# 导入数据解析模块
import parsel # (需要安装 pip install parsel)
# 导入制表模块
from prettytable import PrettyTable
def get_response(url):
"""
- def python关键字 用于定义函数
- get_response 函数名 (自定义变量)
- url 形式参数 (调用get_response函数需要传入一个url链接参数进来)
模拟浏览器对 url 地址发送请求
:param url: url链接地址
:return: url的响应体对象
"""
# 模拟浏览器
headers = {
# User-Agent 用户代理 表示浏览器基本身份信息 (一种简单反反爬方法)
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'
}
# 发送请求:调用 requests 里面 get 请求方法 ( GET 请求方法是根据开发者工具所显示的方法)
response = requests.get(url=url, headers=headers)
# 返回内容
return response
def get_music(id):
"""获取音频链接"""
# 音频数据包地址
link = f'https://www.gequbao.com/api/play_url?id={id}&json=1'
# 发送请求 ( 调用定义好的函数即可 )
response = get_response(url=link)
# 获取数据
json_data = response.json()
# 解析数据, 提取音频链接
music_url = json_data['data']['url']
# 返回音频链接
return music_url
def save_music(title, url):
"""
保存音频数据的函数
:param title: 歌名
:param url: 音频链接
:return:
"""
# 自动创建文件夹:
# 判断如果在和当前的 py文件同级里面没有 music文件夹 则自动创建
if not os.path.exists('./music'):
# 自动创建 music文件夹
os.mkdir('./music')
# 获取音频数据内容
music_content = get_response(url=url).content
# 保存数据
with open('./music/' + title + '.mp3', mode='wb') as f:
f.write(music_content)
print('-' * 30, f'{title}下载完毕', '-' * 30)
def search_music(word):
"""搜索歌曲信息"""
# 请求网址:搜索链接
search_url = f'https://www.gequbao.com/s/{word}'
# 发送请求
html_data = get_response(url=search_url).text
# 创建空列表
info = []
tb = PrettyTable()
tb.field_names = ['序号', '歌名', '歌手']
page = 0
# 把获取到的html字符串数据, 转成可解析的对象
selector = parsel.Selector(html_data)
# CSS选择器: 根据标签的属性提取数据
rows = selector.css('.row')[1:-1]
# for循环遍历, 提取列表里面的元素
for row in rows:
music_name = row.css('.text-primary::text').get().strip() # 歌名
music_id = row.css('.text-primary::attr(href)').get().split('/')[-1] # 歌曲链接
author = row.css('.text-success::text').get().strip() # 歌手
dit = {
'歌名': music_name,
'ID': music_id
}
tb.add_row([page, music_name, author])
info.append(dit)
page += 1
print(tb)
return info
def main():
"""主函数"""
while True:
msg = """**************************************************
欢迎使用【音乐下载系统】V1.0
请选择你想要进行的操作
1. 单首歌曲下载
2. 批量下载全部
q. 退出系统
**************************************************"""
print(msg)
# 输入关键词进行搜索
key = input('请选择你想要进行的操作: ')
if key == 'q':
exit()
elif key == '1':
word = input('请输入你想要下载的歌曲/歌手: ')
# 调用搜索 返回的 info列表 ——> 字典
info = search_music(word)
# 输入要下载的歌曲的序号
num = input('请输入你要下载的歌曲的序号: ')
# 提取音乐ID
song_id = info[int(num)]['ID']
# 提取歌名
song_title = info[int(num)]['歌名']
# 获取音频链接
music_url = get_music(id=song_id)
# 保存数据
save_music(song_title, music_url)
print()
# for循环遍历, 提取列表里面的元素
elif key == '2':
word = input('请输入你想要下载的歌曲/歌手: ')
# 调用搜索 返回的 info列表 ——> 字典
info = search_music(word)
for item in info:
song_id = item['ID'] # 音乐ID
song_title = item['歌名'] # 歌名
# 获取音频链接
music_url = get_music(id=song_id)
# 保存数据
save_music(song_title, music_url)
print()
else:
print('输入有误!!!')
print()
# 函数入口:当你的代码被当做模块进行调用时, 下面的代码不会被执行
if __name__ == '__main__':
# 调用主函数
main()