小记:音频格式转化ByPython(下)

上文中我们已经大致明白了pydub库的使用方法,今天的目标是写个爬虫爬取歌曲信息。

关于网络爬虫,Python的标准库里是有相应的包的,可以直接打开:https://docs.python.org/zh-cn/ 去看Python相应版本的的官方中文文档(这个网站很有用,推荐学Python的小伙伴收藏),当然官方文档一般比较晦涩,可以再搜一些教程配合食用最佳。

通过学习了解到关于python网络爬虫可以使用传统的urllib库或者更高级的 Requests库,这里暂时选用urllib。其中urllib.request模块用于打开url,用法如下:

urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)

观察网页,又出现了一个新问题,那就是七里香存在多义,而默认转到的是周杰伦专辑《七里香》,而不是周杰伦歌曲,七里香。分别打开烟花易冷和七里香搜索结果的源代码,观察:

▪周杰伦演唱歌曲

▪2004年周杰伦发行的音乐专辑

可以发现他们这一行代码是不同的,另外在后一行代码附近,有如下代码:

▪2004年周杰伦发行的音乐专辑
▪席慕容诗集
▪2007年泰国电视剧
▪陈淑桦演唱歌曲
▪中药
▪旅游景点
▪2005年中央编译出版社出版的图书
▪小说《七里香》
▪芸香科九里香属植物
▪台湾2004年周杰伦演唱歌曲
▪中国台湾地区小吃
▪席慕容创作新诗
▪暗夜文学网小说
全部展开
收起

发现这里有个”台湾2004年周杰伦演唱歌曲”选项,与前者相通的地方是有共同关键字”周杰伦演唱歌曲”。接下来继续寻找,我们需要的信息在这样一段文字中:


所以,谱曲、编曲和作曲有什么区别吗?百度一下:

1、概念区别:作曲一般是指给歌词谱写旋律;编曲一般是指给歌曲作伴奏;谱曲是把已经有的曲子记下来,写成简谱,五线谱等。
2、顺序区别:先有作曲,再有编曲和谱曲。

好吧,长见识了。到这里,准备工作大致就差不多了。
这是歌曲标签信息在不同平台与ffmpeg库对照的的一个统计表:

Windows iTunes(Info tab) id3v2.3 ffmpeg key ffmpeg 示例 Title Title TIT2 title -metadata title=”海阔天空” Subtitle Description(Video tab) TIT3 TIT3 -metadata TIT3=”beyond 20周年纪念版” Rating n/a n/a n/a n/a Comments Comments COMM n/a n/a Contributing artists Artist TPE1 artist -metadata artist=”黄家驹” Album artist Album artist TPE2 album_artist -metadata album_artist=”Josh Groban” Album Album TALB album -metadata album=”Closer” Year Year TYER date -metadata date=”2009″ # Track Number TRCK track -metadata track=”3/12″(12首歌中的第3个) Genre Genre TCON genre -metadata genre=”Vocal” Publisher n/a TPUB publisher -metadata publisher=”Heaven Church” Encoded by n/a TENC encoded_by -metadata encoded_by=”Joshua” Aythor URL n/a WOAR n/a n/a CopyRight(不可编辑) n/a TCOP copyright -metadata copyright=”℗ lqsoft” Composers n/a TCOM composer -metadata composer=”Joshua” Conductors n/a TPE3 performer -metadata performer=”Joshua” Group description Grouping TIT1 TIT1 -metadata TIT1=”The Classics” Mood n/a n/a n/a n/a Part of set Disc Number TPOS disc -metadata disc=”1/2″ Initial key n/a TKEY TKEY -metadata TKEY=”G” Beats-per-minute BOM TBPM TBPM -metadata TBPM=”120″ Part of a compilation Part of a compilation TCMP n/a n/a n/a n/a TLAN language -metadata language=”eng” n/a n/a TSSE encoder -metadata encoder=”iTunes v10″ 我们主要会用到title:标题即歌曲名、artist:艺术家即歌手、album:专辑、date:发布时间、composer:作曲。然后呢,发现并没有给可怜的文山兄弟留下一个作词的位置。回头再看,似乎作词、作曲一般是在歌词文件中出现,音乐文件的标签似乎一般有个歌名和歌手就行了。

由于店家的资源文件名中带有数字编号:

01.牛仔很忙.wav
01.说了再见.wav

所以先写个脚本重命名一下,顺带导出歌曲名单:

import os
import re

pattern=[r"^[0-9]+\.",r"\.wav"]
dir='E:\\BaiduNetdiskDownload\\周杰伦'
os.chdir(dir)
raw_dir_list=os.listdir(dir)
dir_list=list()

for file in raw_dir_list:
    tmp=re.sub(pattern[0],"",file)
    str=re.sub(pattern[1],"",tmp)
    dir_list.append(str)
    os.rename(file,tmp)

with open("song_list.txt","w") as p:
    for file in dir_list:
        p.write(file+"\n")

名单效果如下(文件名则是带有”.wav”后缀):

七里香
世界末日
东风破
乔克叔叔

接下来是爬虫脚本:

from urllib import request
from urllib import parse
import re
import os

def getlist(file):
    with open(file,"r") as p:
        list=p.read().split("\n")
    while '' in list:
        list.remove('')
    return list

def crawtext(url):
    res=request.urlopen(url)
    text=res.read().decode(encoding='utf-8', errors='strict')
    return text

def isurl(patternlist,text):
    if re.search(patternlist[0],text):
        a=re.search(patternlist[1],text)
        if a:
            flag=0
        else :
            flag=2
    else :
        flag=1
    return flag

def gettext(pattern,raw_text):
    a=re.search(pattern,raw_text)
    if a:
        text=raw_text[a.span()[0]:a.span()[1]]
    else :
        text=False
    return text

def geturl(pattern,patternlist,raw_text):
    a=re.search(pattern,raw_text)
    if a:
        text=raw_text[a.span()[0]:a.span()[1]]
        tmp=re.sub(patternlist[0],"",text)
        url=re.sub(patternlist[1],"",tmp)
    else :
        url=False
    return url

baseurl=r"https://baike.baidu.com/item/"
pattern1=['▪','▪.*周杰伦.*歌曲.*']
pattern2=''
pattern3='▪.*"]
dir="E:\\BaiduNetdiskDownload\\周杰伦"
os.chdir(dir)

song_list=getlist("song_list.txt")
text_list=list()
for file in song_list:
    name=re.sub(".wav","",file)
    url=baseurl+parse.quote(name)
    text=crawtext(url)
    flag=isurl(pattern1,text)
    if  flag==0:
        text_list.append(gettext(pattern2,text))
    elif flag==1:
        text=gettext(pattern2,text)
        if text:
            text_list.append(text)
        else:
            text_list.append(name+" error 1 ")
    else :
        key=geturl(pattern3,pattern4,text)
        if key:
            url=baseurl+key
            text=crawtext(url)
            text_list.append(gettext(pattern2,text))
        else :
            text_list.append(name+" error 2 ")

with open("text.txt","w") as p:
    for str in text_list:
        p.write(str+"\n")

还是出了一些问题,比如3个”error:2″:

菊花台 error 2
说好的幸福 error 2
轨迹 error 2

打开浏览器搜索,发现周杰伦的歌曲叫”说好的幸福呢”,而不是”说好的幸福”,而对于”菊花台”和”轨迹”:

周杰伦演唱电影《满城尽带黄金甲》片尾曲
周杰伦演唱电影《寻找周杰伦》主题曲

无语,副标题里面没有”歌曲”关键字。除此之外, 还有几个数据错误是因为词条没有自动跳转、演唱者不是周杰伦(献世是周杰伦给陈小春写的歌)。
看起来脚本还可以优化下,好麻烦,反正就几个,手动添加吧,顺带修改一下错误的歌曲名。原始数据下载成功,效果如下:

接下来进行数据清理:

import os
import re

def getlist(file):
    with open(file,"r") as p:
        list=p.read().split("\n")
    while '' in list:
        list.remove('')
    return list

class SONG:
    title=""
    artist=""
    album=""
    date=""
    composer=""
    def __init__(self,title) :
        self.title=title

def cuthead(pattern,text):
    a=re.search(pattern,text)
    if a:
        tmp=text[a.span()[1]:-1]+text[-1]
        str=cuthead(pattern,tmp)
    else :
        str=text
    return str

def search1(pattern,text):
    a=re.search(pattern[0]+".*?"+pattern[1],text)
    if a:
        tmp1=text[a.span()[0]:a.span()[1]]
        tmp2=re.sub(pattern[1],"",tmp1)
        str=cuthead(pattern[0],tmp2)
    else:
        str=False
    return str

def search2(pattern,text):
    a=re.search(pattern,text)
    if a:
        str=text[a.span()[0]:a.span()[1]]
    else :
        str=False
    return str

def search3(pattern,text):
    pass

dir="E:\\BaiduNetdiskDownload\\周杰伦"
os.chdir(dir)
pattern1=["《","》"]
pattern2=["是","演唱"]
pattern3=["歌曲,.",",收录"]
pattern4=["收录.*?[0-9]+年[0-9]+月[0-9]+日","[0-9]+年[0-9]+月[0-9]+日"]
pattern5=["专辑《","》"]

textlist=getlist("text.txt")
li=[]
for  text in textlist:
    title=search1(pattern1,text)
    song=SONG(title)
    song.artist=search1(pattern2,text)
    song.album=search1(pattern5,text)
    song.date=search2(pattern4[1],str(search2(pattern4[0],text)))
    song.composer=search1(pattern3,text)
    li.append(song)

with open("list.txt","w") as p:
    for song in li:
        p.write(str(song.title)+"\t")
        p.write(str(song.artist)+"\t")
        p.write(str(song.album)+"\t")
        p.write(str(song.date)+"\t")
        p.write(str(song.composer)+"\n")

数据不规范,清理两行泪。程序运行完还是手动检查修改了几个不规范数据。清理效果如下:

七里香 周杰伦 七里香 2004年8月3日 方文山作词,周杰伦谱曲,钟兴民编曲
世界末日 周杰伦 范特西PLUS 2001年12月28日 周杰伦作词、作曲
东风破 周杰伦 叶惠美 2003年7月31日 周杰伦谱曲,方文山填词,林迈可编曲

接下来最后一步,格式转化,标签添加:

import os
import pydub

def getlist(file):
    with open(file,"r") as p:
        list=p.read().split("\n")
    while '' in list:
        list.remove('')
    return list

class SONG:
    title=""
    artist=""
    album=""
    date=""
    composer=""
    def __init__(self,title) :
        self.title=title

dir="E:\\BaiduNetdiskDownload\\周杰伦"
os.chdir(dir)
os.mkdir("test")
lines=getlist("list.txt")
list=[]
for line in lines:
    tmp=line.split("\t")
    song=pydub.AudioSegment.from_wav(tmp[0]+".wav")
    dic={"title":tmp[0],"artist":tmp[1],"album":tmp[2],"date":tmp[3],"composer":tmp[4]}
    song.export("test\\"+tmp[0]+".flac",format="flac",tags=dic)
    song.export()

通篇下来,发现格式转化反倒是最简单的了。

Original: https://www.cnblogs.com/hs3434/p/15962611.html
Author: hs3434
Title: 小记:音频格式转化ByPython(下)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/585989/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 微服务架构项目搭建过程中的Mysql安装和相关问题

    搭建微服务架构的过程中需要使用Mysql数据库,Mysql数据库搭建着实不是一个容易的事情,会碰到各种各样的问题,如果没有一个安装数据库的思路真的很难把数据库安装好,并且掉入到安装…

    Linux 2023年6月14日
    0106
  • JuiceFS 在 Elasticsearch/ClickHouse 温冷数据存储中的实践

    企业数据越存越多,存储容量与查询性能、以及存储成本之间的矛盾对于技术团队来说是个普遍难题。这个难题在 Elasticsearch 与 ClickHouse 这两个场景中尤为突出,为…

    Linux 2023年6月14日
    0113
  • powershell 编写的tui界面脚本《电壳别名宝》

    中文名: 《电壳别名宝》 English name: 《Power Alias》 powershell 编写的tui界面脚本。 用途:保存容易记住的别名(支持中文),保存linux…

    Linux 2023年5月27日
    0132
  • MySQL双主同步的实现

    双主复制: 在两个节点上都可以写入数据,互为主从节点。 解决单点失败的问题:一个主节点失败,所有节点都会失败。 双主配置: (1) 各节点使用一个惟一server_id (2) 都…

    Linux 2023年6月7日
    087
  • 课间游戏志:斗荧光笔与扒撸咔嚓

    课间游戏志:斗荧光笔与扒撸咔嚓 写这篇博客,主要是想记录两个课间游戏,一个是我于小学四年级时发明的斗荧光笔,一个是初中时班上几个变态发明的扒撸咔嚓,自从这两个游戏被发明以后,我们班…

    Linux 2023年6月6日
    092
  • 【证券从业】金融基础知识-第二章 中国金融体系与多层次资本市场02

    注1:后续学习并整理到第八章,全书完结后再合并成一个笔记进行源文件分享 注2:本章内容巨多,大约分为两篇文章记录消化 posted @2022-05-31 22:14 陈景中 阅读…

    Linux 2023年6月13日
    081
  • redis cli命令

    redis安装后,在src和/usr/local/bin下有几个以redis开头的可执行文件,称为redis shell,这些可执行文件可做很多事情。 可执行文件 作用 redis…

    Linux 2023年5月28日
    069
  • GCC常见命令

    rwx 对于目录和文件的区别 文件 目录 r 文件的内容可以被查看。支持cat、more、head…vim 目录的内容可以被查看。ls、tree w 文件的内容可以被添…

    Linux 2023年6月6日
    0111
  • 【Leetcode】53. 最大子数组和

    给你一个整数数组 nums,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 子数组是数组中的一个连续部分。 示例 1: 输&am…

    Linux 2023年6月6日
    089
  • Linux远程连接管理(命令)

    1.ftp服务器的搭建 ftp的作用:文件的上传和下载,不允许操作目录,如果想操作目录只能用tar打包。 (1)服务器端: ①.输入”sudo apt-get inst…

    Linux 2023年6月8日
    0107
  • 接口压测提示redis获取不到连接数,出现timeout waiting for idle object异常问题定位

    博客园 :当前访问的博文已被密码保护 请输入阅读密码: Original: https://www.cnblogs.com/qmfsun/p/11583355.htmlAuthor…

    Linux 2023年5月28日
    086
  • 对象缓存服务的思考和实现

    写在前面 目前在很多业务中,存储都大量的依赖了云存储,比如阿里云的 oss、华为云的 obs 等。但是如果有大量的上传/下载任务,云存储上的网络 I/0 就变成了一个很大的瓶颈。 …

    Linux 2023年6月14日
    090
  • 深入理解java泛型

    什么是Java泛型 泛型的使用 泛型类 泛型接口 泛型方法 泛型的底层实现机制 ArrayList源码解析 什么是泛型擦除 泛型的边界 ?:无界通配符 extends 上边界通配符…

    Linux 2023年6月6日
    0123
  • CodeSmith无法获取MySQL表及列Description说明处理

    实体类生成模板下载: 链接:https://pan.baidu.com/s/1tLxW5m5ECwVV2feWSVtQIA提取码:qezw 反编译工具下载: 链接:https://…

    Linux 2023年6月13日
    0111
  • 一劳永逸,解决.NET发布云服务器的时区问题

    国内大多数开发者使用的电脑,都是使用的北京时间,日常开发的过程中其实并没有什么不便;不过,等遇到了阿里云等云服务器,系统默认使用的时间大多为 UTC时间,这个时候,时区和时间的问题…

    Linux 2023年6月6日
    090
  • OSPF之Default-router-advertise 解析

    1、关于default-route-advertise命令 Ospf是可以通过import-route命令引入外部路由的,但很少有人会注意到,在默认情况下,ospf是不会引入来自外…

    Linux 2023年6月14日
    094
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球