1、任務(wù)目標(biāo)
① 爬五月天正規(guī)專輯的所有歌曲的歌詞
② 按照年份進(jìn)行情感分析堂污,并制作詞云
2、方法
在qq音樂上用Python進(jìn)行爬蟲龄砰,總共499首歌曲盟猖,其中包括演唱會(huì)和電影原聲帶等,需要進(jìn)行數(shù)據(jù)清洗换棚。
3式镐、情感語義分析
彎路部分:
原本是想用Beautiful Soup 來抓歌詞,Beautiful Soup是python的一個(gè)庫固蚤,最主要的功能是從網(wǎng)頁抓取數(shù)據(jù)娘汞,但是后來發(fā)現(xiàn)此路不通。
其一夕玩,因?yàn)閝q音樂里的url是固定不變的你弦,并不是每一頁是一個(gè)單獨(dú)的url惊豺。點(diǎn)擊下一頁,這個(gè)url永遠(yuǎn)在那里不變禽作,摔J痢!
打開之后跳轉(zhuǎn)到的是歌手的首頁旷偿,并不是我們要的單曲頁烹俗。
因?yàn)槲沂峭耆珱]有學(xué)過php,后來搜索了一圈才知道萍程,好像這個(gè)翻頁是用js寫的(還是什么ajax幢妄?),就是實(shí)際上看不到的……反正我是找了好久也沒找到那個(gè)對(duì)應(yīng)499首歌曲的對(duì)應(yīng)頁面的url茫负。
其二蕉鸳,因?yàn)锽eautiful Soup要依賴標(biāo)簽定位,而可以看到有的歌曲有mv注釋朽褪,有的歌曲有熱門注釋置吓,所以源碼里標(biāo)簽并不是非常一致。
因?yàn)槭切“椎拊@個(gè)地方也摸索了半天衍锚,后來才發(fā)現(xiàn)怎么也提取不到《我不愿 讓你一個(gè)人》的歌名,才知道是標(biāo)簽xx.[1]這種寫法有問題嗤堰,其他歌曲都是通過xx.[1]就可以定位戴质,而這首歌由于沒有mv,所以要提取歌名的話踢匣,對(duì)應(yīng)標(biāo)簽是xx.[0]告匠,寫半天卻發(fā)現(xiàn)此路不通。
綜上离唬,后來分析了一下后专,就是由于自己對(duì)php太小白,啥也不懂输莺,所以才浪費(fèi)了這么久戚哎。還有就是,其實(shí)剛開始上手某種語言時(shí)嫂用,都會(huì)經(jīng)歷這種比較爬坡繞路的時(shí)期型凳,不要怕,堅(jiān)持一下嘱函,多搜索下前人經(jīng)驗(yàn)甘畅,總會(huì)有辦法的。還好我沒放棄~~~
好吧,那我們開始尋找另一條路疏唾。
然后我不甘心蓄氧,把所有能打開的url都打開了一遍,看看都是些什么鬼荸实。
最后讓我找到了這個(gè)網(wǎng)址:
https://c.y.qq.com/v8/fcg-bin/fcg_v8_singer_track_cp.fcg?g_tk=5381&jsonpCallback=MusicJsonCallbacksinger_track&loginUin=0&hostUin=0&format=jsonp&inCharset=utf8&outCharset=utf-8?ice=0&platform=yqq&needNewCode=0&singermid=000Sp0Bz4JXH0o&order=listen&begin=0&num=30&songstatus=1
打開是醬紫的:
小小興奮一下匀们,仔細(xì)看里面有專輯名、歌名准给、歌手名泄朴,甚至還有歌詞的id。
到這里就有思路了露氮,可以用正則表達(dá)式把歌名祖灰、專輯名、歌詞鏈接等關(guān)鍵字都篩選出來就好了呀~
突然有種柳暗花明的感覺呢畔规!
但是這僅僅是499首單曲里第一頁的內(nèi)容局扶,其他頁呢?
通過觀察發(fā)現(xiàn)叁扫,在url里這里很不一樣!
https://c.y.qq.com/v8/fcg-bin/fcg_v8_singer_track_cp.fcg?g_tk=5381&jsonpCallback=MusicJsonCallbacksinger_track&loginUin=0&hostUin=0&format=jsonp&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq&needNewCode=0&singermid=000Sp0Bz4JXH0o&order=listen&begin=0&num=30&songstatus=1
begin=0&num=30決定了每頁第一首歌曲的序號(hào)及歌曲數(shù)目三妈。
只要做個(gè)循環(huán)就可以翻頁了都爬下來了嘛~
代碼走起,先來看看最基本的莫绣,爬了第一頁的歌曲:
import re
import pandas as pd
import requests
response = requests.get("https://c.y.qq.com/v8/fcg-bin/fcg_v8_singer_track_cp.fcg?g_tk=5381&jsonpCallback=MusicJsonCallbacksinger_track&loginUin=0&hostUin=0&format=jsonp&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq&needNewCode=0&singermid=000Sp0Bz4JXH0o&order=listen&begin=0&num=30&songstatus=1")
response = response.text
print(response)
songname = '"songname":"(.?)","songorig"'
res1 = re.findall(songname,response)
for i in res1:
print(i)
同理畴蒲,爬了專輯名、歌詞還有一個(gè)musicid后面會(huì)用到对室。
然后只要將每一頁的歌曲都抓出來就好了模燥,用一個(gè)循環(huán)增加頁碼即可。
import re
import requests
for i in range(0,481,30):
response = requests.get("https://c.y.qq.com/v8/fcg-bin/fcg_v8_singer_track_cp.fcg?g_tk=5381&jsonpCallback=MusicJsonCallbacksinger_track&loginUin=0&hostUin=0&format=jsonp&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq&needNewCode=0&singermid=000Sp0Bz4JXH0o&order=listen&begin="+str(i)+"&num=30&songstatus=1")
response = response.text
#print(response)
songname = '"songname":"(.?)","songorig"'
album = '"albumname":"(.?)","alertid"'
strMedia = '"strMediaMid":"(.?)","stream"'
musicid = '"songid":(.*?),"songmid"'
res1 = re.findall(songname,response)
res2 = re.findall(album,response)
res3 = re.findall(strMedia,response)
res4 = re.findall(musicid,response)
for i in range(0,len(res1)):
if res2 == '' or res3 == '' or res4 == '' :
continue
print (str(i),'\t',res1[i],'\t',res2[i],'\t',"http://y.qq.com/n/yqq/song/"+res3[i]+".html",'\t',res4[i])
這里最開始print的for循環(huán)寫的是:
for i in range(0,30)
拉到最后報(bào)錯(cuò)說list index out of range
但代碼改成for i in range(0,len(res1))之后還是有問題掩宜,實(shí)際抓取出來只有409首歌蔫骂,剩下的3頁90首歌因?yàn)橛械膶]嬅麨榭眨瑫?huì)同樣出現(xiàn)list index out of range的問題牺汤,只是不報(bào)錯(cuò)辽旋,而是直接跳過去繼續(xù)打印下一頁的內(nèi)容了。
后來加上if語句檐迟,將為空的元素跳過繼續(xù)執(zhí)行循環(huán)就好了戴已。
關(guān)于數(shù)組有時(shí)候很容易懵b。但還是那句話锅减,剛開始學(xué),在還沒有那么扎實(shí)的理論功底時(shí)伐坏,這樣邊試錯(cuò)怔匣、邊實(shí)戰(zhàn)是對(duì)代碼理解最深刻、學(xué)得最快的方式。然后在實(shí)操之后每瞒,可以再反過來金闽,重新看一下基礎(chǔ)的理論知識(shí),鞏固一下基本功剿骨,此時(shí)自己的理解力肯定跟兩眼一抹黑代芜,從頭學(xué)的時(shí)候不一樣了,理解會(huì)更深刻的浓利。
接下來是導(dǎo)出到excel中挤庇,然后根據(jù)歌詞的鏈接,再去抓取歌詞贷掖。最后就可以對(duì)歌詞進(jìn)行分析了~
我是直接把print出來的內(nèi)容copy到txt文檔中嫡秕,再copy到excel即可,怎么快怎么來苹威。
按照專輯分類昆咽,將演唱會(huì)、日語專輯等刪除牙甫,按照年份對(duì)原始先做一次清理掷酗。
最后整理完一共是124首歌。
然后找到歌詞頁窟哺,繼續(xù)解析網(wǎng)頁源碼泻轰,結(jié)果發(fā)現(xiàn)源碼里并沒有直接給出歌詞,shit!
完全陷入困境脏答,不知從何下手糕殉。
然后搜了好多大神的方法,讓我找到了一位大神的github:
(https://github.com/lhtlht/qqmusic)
潛心研究了快一天爸掣妗阿蝶!
最后稍微看明白一些,原來能夠有效區(qū)分不同歌曲的key有兩個(gè)黄绩,一個(gè)是在url中的歌曲號(hào)musicid(之前沒注意羡洁,沒有爬下來,后來加上的)爽丹,一個(gè)是在referer里用到的歌詞號(hào)songmid(也就是我們之前抓到的strMedia)
然后對(duì)大神的代碼做了調(diào)整筑煮,改了好久啊,才跑成功粤蝎,更改如下:
(簡(jiǎn)書的編輯器會(huì)吞空格……看我公眾號(hào)的原版吧真仲,無奈)
#抓取歌詞函數(shù)
import requests
import json
import pandas as pd
import re
def getLyric(musicid,songmid):
url = 'https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric.fcg?nobase64=1&musicid='+musicid+'&callback=jsonp1&g_tk=5381&jsonpCallback=jsonp1&loginUin=0&hostUin=0&format=jsonp&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq&needNewCode=0'
header = {
'user-agent':'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36',
'referer':'https://y.qq.com/n/yqq/song/{}.html'.format(songmid)
}
paramters = {
'nobase64':'1',
'callback':'jsonp1',
'g_tk':'5381',
'jsonpCallback':'jsonp1',
'loginUin':'0',
'hostUin':'0',
'format':'jsonp',
'inCharset':'utf8',
'outCharset':'utf-8',
'notice':'0',
'platform':'yqq',
'needNewCode':'0'
}
html = requests.get(url=url,params=paramters,headers=header)
res = json.loads(html.text.lstrip('jsonp1(').rstrip(')'))
#由于一部分歌曲是沒有上傳歌詞,因此沒有默認(rèn)為空
lyric = json.loads(html.text.lstrip('jsonp1(').rstrip(')'))['lyric']
#對(duì)歌詞內(nèi)容做稍微清洗
dr1 = re.compile(r'&#\d.;',re.S)
dr2 = re.compile(r'[\d+]',re.S)
dd = dr1.sub(r'',lyric)
dd = dr2.sub(r'\n',dd).replace('\n\n','\n')
return dd
帶入一首《志明與春嬌》的musicid和 songmid試試看:
lyric = getLyric('4830147','001Sh6UI3dh9mE')
print (lyric)
寫到這里初澎,快哭了好嗎=沼Α!!
然后把大神對(duì)于歌詞格式的更改稍微改了一下软啼,便于導(dǎo)出桑谍。
從excel中導(dǎo)入musicid 和 songmid。
#抓取歌詞函數(shù) getLyric 及從excel傳參
import requests
import json
import pandas as pd
import re
import openpyxl
wb = openpyxl.load_workbook(r'D:\lyric.xlsx') #打開excel文件
#print(wb.get_sheet_names()) #獲取工作簿所有工作表名
sheet = wb.get_sheet_by_name('清洗') #獲取工作表
#print(sheet.title) #獲取sheet頁的名稱
def getLyric(musicid,songmid):
url = 'https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric.fcg?nobase64=1&musicid='+musicid+'&callback=jsonp1&g_tk=5381&jsonpCallback=jsonp1&loginUin=0&hostUin=0&format=jsonp&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq&needNewCode=0'
header = {
'user-agent':'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36',
'referer':'https://y.qq.com/n/yqq/song/{}.html'.format(songmid)
}
paramters = {
'nobase64':'1',
'callback':'jsonp1',
'g_tk':'5381',
'jsonpCallback':'jsonp1',
'loginUin':'0',
'hostUin':'0',
'format':'jsonp',
'inCharset':'utf8',
'outCharset':'utf-8',
'notice':'0',
'platform':'yqq',
'needNewCode':'0'
}
html = requests.get(url=url,params=paramters,headers=header)
res = json.loads(html.text.lstrip('jsonp1(').rstrip(')'))
#由于一部分歌曲是沒有上傳歌詞祸挪,因此沒有默認(rèn)為空
lyric = json.loads(html.text.lstrip('jsonp1(').rstrip(')'))['lyric']
#對(duì)歌詞內(nèi)容做稍微清洗
dr1 = re.compile(r'&#\d.;',re.S)
dr2 = re.compile(r'[\d+]',re.S)
dd = dr1.sub(r'',lyric)
dd = dr2.sub(r'\n',dd).replace('\n',',')
return dd
lyric_list = []
for i in range(2,126,1):
lyric_list = getLyric(str(sheet.cell(row=i,column=5).value),str(sheet.cell(row=i,column=4).value))
print (lyric_list,'\n')
同上锣披,copy到txt再直接粘貼到excel就好了,至此贿条,歌詞爬蟲總算搞定了~
撒花~~~
這篇是比較理論的部分雹仿,下一篇會(huì)進(jìn)行歌詞的分析,結(jié)合年份看看我們主唱大人這幾年的心-路-歷-程闪唆,畢竟小伙子也變成發(fā)福中年大叔了嘛~哈哈
謝謝大家盅粪!
然后本人再次強(qiáng)調(diào),小白Python選手悄蕾,記性不好票顾,單純?yōu)閭€(gè)人記錄之用。
本文可分享帆调,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載奠骄!
整理后的excel文檔如果有人想用來分析,請(qǐng)?jiān)诠娞?hào)(fancyfanyc)后臺(tái)回復(fù)mayday即可獲得下載鏈接番刊。
請(qǐng)大神們多多指教含鳞,輕拍,喵~
江湖之大芹务,后會(huì)有期蝉绷,咱們下篇見~