栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

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

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

小记:音频格式转化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)

看起来很复杂,不过其他的默认可以不填,我们只需给出url参数就行了。打开百度百科搜索烟花易冷,发现网页url是这样的:https://baike.baidu.com/item/%E7%83%9F%E8%8A%B1%E6%98%93%E5%86%B7/211 ,尝试更改url,输入:https://baike.baidu.com/item/七里香 ,转到,成功进入七里香的百度词条界面,不过url自动更新为了:https://baike.baidu.com/item/七里香/2181450 (可以用,nice)。

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

  • ▪周杰伦演唱歌曲
  • ▪2004年周杰伦发行的音乐专辑
  • 可以发现他们这一行代码是不同的,另外在后一行代码附近,有如下代码:

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

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

    
    
    
    

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

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

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

    WindowsiTunes(Info tab)id3v2.3ffmpeg keyffmpeg 示例
    TitleTitleTIT2title-metadata title=”海阔天空”
    SubtitleDescription(Video tab)TIT3TIT3-metadata TIT3=”beyond 20周年纪念版”
    Ratingn/an/an/an/a
    CommentsCommentsCOMMn/an/a
    Contributing artistsArtistTPE1artist-metadata artist=”黄家驹”
    Album artistAlbum artistTPE2album_artist-metadata album_artist=”Josh Groban”
    AlbumAlbumTALBalbum-metadata album=”Closer”
    YearYearTYERdate-metadata date=”2009”
    #Track NumberTRCKtrack-metadata track=”3/12”(12首歌中的第3个)
    GenreGenreTCONgenre-metadata genre=”Vocal”
    Publishern/aTPUBpublisher-metadata publisher=”Heaven Church”
    Encoded byn/aTENCencoded_by-metadata encoded_by=”Joshua”
    Aythor URLn/aWOARn/an/a
    CopyRight(不可编辑)n/aTCOPcopyright-metadata copyright=”℗ lqsoft”
    Composersn/aTCOMcomposer-metadata composer=”Joshua”
    Conductorsn/aTPE3performer-metadata performer=”Joshua”
    Group descriptionGroupingTIT1TIT1-metadata TIT1=”The Classics”
    Moodn/an/an/an/a
    Part of setDisc NumberTPOSdisc-metadata disc=”1/2”
    Initial keyn/aTKEYTKEY-metadata TKEY=”G”
    Beats-per-minuteBOMTBPMTBPM-metadata TBPM=”120”
    Part of a compilationPart of a compilationTCMPn/an/a
    n/an/aTLANlanguage-metadata language=”eng”
    n/an/aTSSEencoder-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='
  • ▪' pattern4=[".*href='/item/","'>.*"] 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()
    

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

    转载请注明:文章转载自 www.mshxw.com
    本文地址:https://www.mshxw.com/it/753723.html
    我们一直用心在做
    关于我们 文章归档 网站地图 联系我们

    版权所有 (c)2021-2022 MSHXW.COM

    ICP备案号:晋ICP备2021003244-6号