做网站时的兼容问题,有了域名如何建网站,互联网保险的定义与特点,wordpress get_the_content【Python学习笔记】#xff1a;Python爬取音频
背景前摇#xff08;省流可以不看#xff09;#xff1a; 人工智能公司实习#xff0c;好奇技术老师训练语音模型的过程#xff0c;遂请教#xff0c;得知训练数据集来源于爬取某网页的音频。 很久以前看B站同济子豪兄的《…【Python学习笔记】Python爬取音频
背景前摇省流可以不看 人工智能公司实习好奇技术老师训练语音模型的过程遂请教得知训练数据集来源于爬取某网页的音频。 很久以前看B站同济子豪兄的《两天搞定图像识别毕业设计》系列见识到了祖传代码爬虫爬取大量图片制作训练数据集的能力然后我就想到我之前学的BeautifulSoup和Scrapy都是爬网页文本的我还从来没有写代码成功且专门爬过视频和图片的经验那正好学一下以后没准也可以拿来做自己的数据集这次就先搞定音频的爬取吧。 原理讲解这部分我认为下面这个视频无懈可击——言简意赅简明扼要时长感人堪称吾辈楷模 【python】几分钟教你如何用python爬取音频数据 https://www.bilibili.com/video/BV1mL4y1N7eV/?spm_id_from333.1007.top_right_bar_window_custom_collection.content.clickvd_sourcecdfd0a0810bcc0bcdbcf373dafdf6a82 传送门 网址后缀只有mp3 ———————————————————————————————— 原理明白了下面进入实操细节我承认我选这个教程的很大原因是被“突破网站反爬”几个字吸引了。 突破网站反爬-制作简易的音乐播放器【Python】https://www.bilibili.com/list/watchlater?oid1556173520bvidBV1e1421b73kspm_id_from333.1007.top_right_bar_window_view_later.content.click 传送门 老师这个清晰的板书风格爱了。 意外收获找个歌曲的宝藏网站一枚歌曲宝能在线听也能下载 说真的感觉有这网站在都不用劳动爬虫大驾笑死 https://www.gequbao.com/ 传送门———————————————————————————————— 思路梳理 ———————————————————————————————— 第一部分单首歌曲采集 F12/右键——检查选择”网络“模块然后点击页面上的刷新按钮让网页数据重新加载出来。 右边示范的这个链接还是歌曲本身 下面这个play_url就是我们需要的歌曲播放链接了 这个有点难点到先点play_url下面的数据内容然后再选Headers。 然后就可以看到数据的标头了——可以得知请求网站请求方法和请求参数等等都可看到。 数据包地址Request URL: https://www.gequbao.com/api/play_url?id402856json1 ———————————————————————————————— 思路分析清楚后就该到代码实践步骤了 主要使用的是请求标头里面的参数比如这个User-Agent user-agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36 插入代码后要注意写成字典形式
# 模拟浏览器
headers {#User-Agent 用户代理表示浏览器基本身份信息User-Agent :Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36
}# 请求网址
url https://www.gequbao.com/api/play_url?id402856json1———————————————————————————————— 经过以上步骤可以成功获取一个格式类似json的结果
#导入数据请求模块
import requests发送请求
# 模拟浏览器
headers {#User-Agent 用户代理表示浏览器基本身份信息User-Agent : Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36
}
# 请求网址
url https://www.gequbao.com/api/play_url?id402856json1
# 发送请求
response requests.get(urlurl, headersheaders)获取数据
#获取响应json数据——字典数据
json_data response.json()
print(json_data)输出
{code: 1, data: {url: https://sy-sycdn.kuwo.cn/edde772eaab20af3f141ec9f2561df44/66912c2a/resource/n2/70/55/756351052.mp3?bitrate$128fromvip}, msg: 操作成功}通过键值对取值的方式一层一层获得歌曲的播放链接
获取数据
#获取响应json数据——字典数据
json_data response.json()
解析数据
#提取歌曲链接键值对取值
play_url json_data[data][url]
print(json_data)
print(play_url)———————————————————————————————— 下一步是保存数据现在我们拿到的只是一个链接地址要想保存到本地要向这个链接发出请求获取音频内容。 写入数据这部分要用到os这个包并且写之前要判断是否存在目标路径如果没有的话会报错。 UP老师为了直观省事毕竟这个程序很简单直接指定文件夹的名字并且把存在与否的逻辑判断放在了最开头但我见的更多的写法是和文件操作放在一起写比如执行读写操作之前判断一下有无此目录如果没有的话再建立。
#导入数据请求模块
import requests
#导入文件操作模块
import os自动创建保存音频的文件夹
file music
#判断文件夹是否存在
if not os.path.exists(file):#创建文件夹os.mkdir(file)发送请求
# 模拟浏览器
headers {#User-Agent 用户代理表示浏览器基本身份信息musicUser-Agent : Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36
}
# 请求网址
url https://www.gequbao.com/api/play_url?id402856json1
# 发送请求
response requests.get(urlurl, headersheaders)获取数据
#获取响应json数据——字典数据
json_data response.json()
解析数据
#提取歌曲链接键值对取值
play_url json_data[data][url]
print(json_data ,json_data)
print(play_url ,play_url)
保存数据
#对于音频链接发送请求获取音频内容
music_content requests.get(url play_url, headers headers).content
#数据保存
with open(music\\晴天.mp3, mode wb) as f:#写入数据f.write(music_content)
执行完这一步以后打开本地文件夹可以看到《晴天》这首歌已经顺利存到本地了并且点击可以电脑上播放 到这里单首歌曲的采集就结束了可以说是给了我很大信心但我还不够满意因为要做人工智能音频数据集的话需要大量爬取音频数据之前问过做分布式Python的技术老师用的是Scrapy但我一下子没找到用Scrapy或者其他框架大规模深度爬取数据的好例子先把手上这个学完吧。 截至第一步的完整代码内容
#导入数据请求模块
import requests
#导入文件操作模块
import os自动创建保存音频的文件夹
file music
#判断文件夹是否存在
if not os.path.exists(file):#创建文件夹os.mkdir(file)发送请求
# 模拟浏览器
headers {#User-Agent 用户代理表示浏览器基本身份信息musicUser-Agent : Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36
}
# 请求网址
url https://www.gequbao.com/api/play_url?id402856json1
# 发送请求
response requests.get(urlurl, headersheaders)获取数据
#获取响应json数据——字典数据
json_data response.json()
解析数据
#提取歌曲链接键值对取值
play_url json_data[data][url]
print(json_data ,json_data)
print(play_url ,play_url)
保存数据
#对于音频链接发送请求获取音频内容
music_content requests.get(url play_url, headers headers).content
#数据保存
with open(music\\晴天.mp3, mode wb) as f:#写入数据f.write(music_content)
———————————————————————————————— 第二部分搜索下载 老师讲到这部分已经有点批量采集的意思了要分析链接的变化规律要说这个我可就不困了。 选择另一首歌曲《稻香》如法炮制播放歌曲刷新检查界面的Network下属Media栏一样的办法找到url。如果发现没有歌曲的链接出现的话应该是没有播放歌曲 正好老师的视频也在讲这个播放一下出链接的解决办法甚至还让不出来就拉进度条哈哈 再故技重施找链接 通过对比发现不同的歌曲主要是id不同。只要能把所有的歌曲ID都拿到那就可以采集全部的歌曲。好耶音频训练数据集不是梦 ———————————————————————————————— 那么关键的id该怎么找呢老师告诉我们和浏览器上方网址导航栏里面是一样的 而导航栏这个链接是搜索出的集合页面“下载”按钮点进来的 在搜索页面搜一下单首歌曲的id 发现这一页歌名作者id都有 那么要抓取的请求网址自然也是这个页面的Request URL了 Request URL: https://www.gequbao.com/s/%E5%91%A8%E6%9D%B0%E4%BC%A6 ———————————————————————————————— 老师的总结三种获取内容的方式 前面我们根据链接直接下载歌曲文件的时候就用的content方法直接获取歌曲的二进制文件并保存。 最开始获取歌曲链接的时候就是返回的json格式
json_data {code: 1, data: {url: https://sy-sycdn.kuwo.cn/6dafd418ad3ba5d48a41948554b060df/669147fa/resource/n2/70/55/756351052.mp3?bitrate$128fromvip}, msg: 操作成功另外提一句我实习做内容安全方向的AI训练数据标注师的时候每天审核的文本训练集就是json文件所有数据都有整齐划一的格式主题、回答什么的排得清清楚楚甚至还是放在VSCode里打开删改。然后根据技术老师的答疑这些训练数据很多也是爬虫得到的所以response.json()在文本数据集制作应该会很常用但如果是训练语音模型、图像识别模型的话应该response.content会更吃香。 ———————————————————————————————— 具体选择用哪种方法呢要根据获取的目标网页内容决定 1.这种网页前端HTML的格式就用获取文本response.text 2.这种花括号包起来的用response.json() 3.二进制音频/视频/图片/文件链接用response.content 保存代码不是固定的要看保存成什么样子。 ———————————————————————————————— 切到元素分栏鼠标选择找到CSS标签 看一下查到的84条row标签发现首尾几条代表的并不是我们想要的歌曲所以要对返回的列表做切片。 ———————————————————————————————— 找到a标签并且提取歌名文字内容以后发现歌名的后面还跟着很多空格 使用**strip()**方法去掉歌名左右两边的空格。 ———————————————————————————————— 提取歌曲id要注意id并不是文字内容而是标签里面的属性要用 attr(属性名称) 来获取。
这块是有一点绕一会是文字一会是属性的对HTML比较熟的看起来要容易一些或者对着老师的教程多看几遍自己多尝试不懂的问问Kimi。 歌手也如法炮制——找到标签提取文本信息 将之前请求网址的格式更换为通用匹配id的形式 保存的格式也换成歌名和歌手通用的形式 ———————————————————————————————— 批量采集的思路捋一捋先通过单首歌曲的链接和浏览器网址对比发现每首歌曲有id作为唯一辨识符那么只要知道所有id就可以爬取所有歌曲。 我想如果对网页很熟了知道要找歌曲id来下载应该可以直接进行批量爬取不需要再拿单首歌曲测试 于是就去搜索页面这种有大量id的网页通过检查HTML代码的方法找到了要薅羊毛的这个大集合目标网址的HTML代码然后写爬虫获取网页源代码通过CSS解析出当中隐藏的一大堆歌名、id等信息最后再拿这一大堆id组合成完整歌曲链接去爬想要的一大堆歌曲并且保存到本地。 ———————————————————————————————— 不知道为什么我下着下着就报了一个bug看原网页这也不是当前目录的最后一首歌而且似乎也不是按顺序下载的。 仔细看老师的下载列表跟我一样也是到这首歌就停了。 询问了一下Kimi我感觉可能是有的歌曲解析失败无法提供播放链接造成的之前在这个网站试着搜了一些想听的歌结果有好几首无法播放说《解析失败》。 加上Kimi提供的这段代码以后确实程序容错性变高了下载到本地的歌曲明显多了也不会因为中间出问题而中断。 而且我们还能看到出bug的是这首《霍元甲》 这首歌到网站里面点开发现是能正常播放的那就不是音源找不到的问题我们把错误给Kimi看一下——原来是歌曲名太刁钻了。 按照Kimi的提示改一下 但我试过以后还是报这个刁钻古怪的问题……看网页源代码也看不出bug 那看来是不得不使用Kimi建议的另一个方法——清理一下文件名了 这次奏效了成功把《霍元甲》这首歌爬下来了而且爬取效果比我想得要好甚至电影题目都还在 这段代码成功顺利跑完了爬取流程再没有报错起立欢呼
#导入数据请求模块
import requests
#导入文件操作模块
import os
#导入数据解析模块
import parsel
import re
def clean_filename(filename):# 替换文件名中的特殊字符为下划线return re.sub(r[:/\\|?*\r\n], _, filename)自动创建保存音频的文件夹
file music
#判断文件夹是否存在
if not os.path.exists(file):#创建文件夹os.mkdir(file)发送请求
# 模拟浏览器
headers {#User-Agent 用户代理表示浏览器基本身份信息musicUser-Agent : Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36
}
#搜索网址
link https://www.gequbao.com/s/%E5%91%A8%E6%9D%B0%E4%BC%A6
# 发送请求
link_response requests.get(urllink, headersheaders)
#获取响应文本数据
html link_response.text
解析数据
#把html字符串数据转换为可解析对象
selector parsel.Selector(html)
#第一次提取提取所有歌曲信息所在div标签类名row
rows selector.css(.row)[2:-1]
#for循环遍历提取列表里面元素
for row in rows:提取每一条歌曲具体信息#提取歌名SongName clean_filename(row.css(a.text-primary::text).get().strip())#提取idSongId row.css(a.text-primary::attr(href)).get().split(/)[-1]#提取歌手singer row.css(.text-success::text).get().strip()print(SongName, SongId, singer)# 请求网址url fhttps://www.gequbao.com/api/play_url?id{SongId}json1# 发送请求response requests.get(urlurl, headersheaders)# 检查响应状态码if response.status_code 200:try: 获取数据# 尝试获取响应json数据json_data response.json()print(json_data , json_data)except ValueError:# 如果解析JSON失败打印原始响应文本print(Failed to parse JSON from response text:)print(response.text)else:print(Failed to retrieve data, status code:, response.status_code)解析数据#提取歌曲链接键值对取值play_url json_data[data][url]print(json_data ,json_data)print(play_url ,play_url)保存数据#对于音频链接发送请求获取音频内容music_content requests.get(url play_url, headers headers).content#数据保存# 使用原始字符串来避免转义字符问题with open(fmusic\\{SongName}-{singer}.mp3, modewb) as f:#写入数据f.write(music_content)
———————————————————————————————————————————— 接下来就进入第三部分搜索歌曲 老师使用了一个比较陌生的新库prettytable这会打印出很整齐的表格 操作过程比较零碎要多看慢慢跟 这个prettytable我在命令行里装了好几回明明都requirements satisfied了一跑还是报没有这个module在jupyter里面单独又装了一次这回正常了。 老师给的建议是最好把这块代码重构写成函数不然很麻烦。 能实现输入汉字找到对应歌曲的原因我猜测应该是和这个网页链接有关能匹配上歌曲的搜索界面网页关键词然后获取这个网页的HTML代码有了歌曲id就能指哪打哪 这次我们就可以随心所欲输入关键字和目标序号随心所欲下载自己喜欢的歌曲啦 搜索部分完整代码
#导入数据请求模块
import requests
#导入文件操作模块
import os
#导入数据解析模块
import parsel
#导入制表模块
from prettytable import PrettyTable
import re
def clean_filename(filename):# 替换文件名中的特殊字符为下划线return re.sub(r[:/\\|?*\r\n], _, filename)自动创建保存音频的文件夹
file music
#判断文件夹是否存在
if not os.path.exists(file):#创建文件夹os.mkdir(file)发送请求
# 模拟浏览器
headers {#User-Agent 用户代理表示浏览器基本身份信息musicUser-Agent : Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36
}
#输入搜索内容
key input(请输入搜索内容)
#搜索网址
link fhttps://www.gequbao.com/s/{key}
# 发送请求
link_response requests.get(urllink, headersheaders)
#获取响应文本数据
html link_response.text
解析数据
#把html字符串数据转换为可解析对象
selector parsel.Selector(html)
#第一次提取提取所有歌曲信息所在div标签类名row
rows selector.css(.row)[2:-1]#实例化对象
tb PrettyTable()
#添加字段名
tb.field_names [序号, 歌名, 歌手]
#自定义变量
page 0
#创建空列表
info_list []#for循环遍历提取列表里面元素
for row in rows:提取每一条歌曲具体信息#提取歌名SongName clean_filename(row.css(a.text-primary::text).get().strip())#提取idSongId row.css(a.text-primary::attr(href)).get().split(/)[-1]#提取歌手singer row.css(.text-success::text).get().strip()#print(SongName, SongId, singer)#添加数据存在字典中dit {歌名:SongName,歌手:singer,ID:SongId,}#给info_list添加元素info_list.append(dit)#添加内容tb.add_row([page, SongName, singer])page 1print(tb)
num input(请输入你要下载的歌曲序号)
#获取歌曲ID
music_id info_list[int(num)][ID]# 请求网址
url fhttps://www.gequbao.com/api/play_url?id{music_id}json1
# 发送请求
response requests.get(urlurl, headersheaders)# 检查响应状态码
if response.status_code 200:try: 获取数据# 尝试获取响应json数据json_data response.json()print(json_data , json_data)except ValueError:# 如果解析JSON失败打印原始响应文本print(Failed to parse JSON from response text:)print(response.text)
else:print(Failed to retrieve data, status code:, response.status_code)解析数据
#提取歌曲链接键值对取值
play_url json_data[data][url]
print(json_data ,json_data)
print(play_url ,play_url)
保存数据
#对于音频链接发送请求获取音频内容
music_content requests.get(url play_url, headers headers).content
#数据保存
# 使用原始字符串来避免转义字符问题
with open(fmusic\\{info_list[int(num)][歌名]}-{info_list[int(num)][歌手]}.mp3, modewb) as f:#写入数据f.write(music_content)效果如图所示 ———————————————————————————————————————————— 然后我想试着爬取一个某知名的有声书网站但发现很难搜到搜索界面的Request URL。 为了解决这个问题我也查了一些教程 Python爬虫实战案例之爬取喜马拉雅音频数据详解https://www.jb51.net/article/201564.htm 传送门 在观看老师的操作和我自己的操作结果对比发现现在的网址跟以前有些不一样了。 老师的视频是23年上传的看下面截图他找到的播放链接和上面歌曲宝一样只有id不同。 但等我真正自己今天是2024年7月15日去找的时候发现现在链接大不一样了 Request URL: https://a.xmcdn.com/download/1.0.0/group30/M02/3F/2A/wKgJXlmBkw2zg0LjAKntzSZLubI803-aacv2-48K.m4a?sign132430e114a56804799c6cc645b6d251buy_keywww2_e039a2bf-161311236timestamp1721007591951000token8248duration1377 现在的链接看起来要复杂的多变化也更多不仅仅是一个简单的id替换就能搞定的。 然后问了一下Kimi发现可能用到了动态生成 目前我还只知道怎么爬简单的换id的网址这种动态的问题对我来说有点太复杂了不过可以作为以后一个进阶的学习方向。 本次我跟着视频教程写的代码也会发到CSDN资源库上有需要的读者可以下载 ———————————————————————————————————————————— 一些搜索过程中遇到的其他好帖子也发在这里一起分享出来 解析Python爬虫常见异常及处理方法https://zhuanlan.zhihu.com/p/650309507 添加链接描述 Python常见问题-如何爬取动态网页内容https://www.bilibili.com/video/BV1of4y15736/?spm_id_from333.337.search-card.all.clickvd_sourcecdfd0a0810bcc0bcdbcf373dafdf6a82 添加链接描述 这个视频主要教授的是动态网页的爬取和之前找的Media栏目不同这次主要找的是JS和Fetch/XHR目录下的内容。
有个弹幕说的好找数据在那个包里不难 难的是找出数据包链接的规律从而一次爬多页的数据