python學習之爬蟲(一) ——————爬取網易雲歌詞


     接觸python也有一段時間了,一提到python,可能大部分pythoner都會想到爬蟲,沒錯,今天我們的話題就是爬蟲!作為一個小學生,關於爬蟲其實本人也只是略懂,懷着”Done is better than perfect”的態度硬着頭皮開始了這篇文章的撰寫!好了,廢話不多說!

  先說一下今天我們的目的,作為一個音痴但不影響我對於音樂的執着,所以今天我們爬取的是網易雲音樂,我們將會通過代碼爬取歌詞並寫入到本地。

  作為新手,我很本能就打開頁面復制了url,然后用Beautifulsoup解析了網頁並打印出來,然后去查找歌詞所在的標簽,心想這不是so easy嗎!寫下了以下代碼

1 # -*- coding:utf-8 -*-
2 import requests
3 import json
4 import re
5 from bs4 import BeautifulSoup
6 lrc_url = "http://music.163.com/#/song?id=191232"
7 lyric = requests.get(lrc_url)
8 soup = BeautifulSoup(lyric.text,'lxml')
9 print(soup)

卧擦嘞,打印出來了一些什么鬼啊!居然沒有找到歌詞!怎么辦!怎么辦!沉思了良久后我覺得我掉進了一個巨坑,事情絕對沒有那么簡單!.....(心情無比悲痛,此處省略一萬字)作為平常屢試不爽的招數今天居然裝逼失敗!痛定思痛,我覺得肯定是URL的問題,經過一番思索發現原來我找了一個假的URL!幾經波折,找到了這樣一個URL

'http://music.163.com/api/song/lyric?' + 'id=' + str(191232) + '&lv=1&kv=1&tv=-1'
打印出來的效果是這樣的:

這才像那么回事了,但是發現里面還多了一些不需要的東西。

第二步,篩選出我們需要的元素,這里我們將用到正則表達式和json,切記用之前先導入這兩個模塊。加入幾行代碼,帥選后的結果為:

到這里我們已經基本上完成了我們的工作。最后一步,寫入文本就不多說了,這樣我們再加上幾行代碼就搞定了!這里我們先貼上之前的代碼

 

 1 # -*- coding:utf-8 -*-
 2 import requests
 3 import json
 4 import re
 5 lrc_url = 'http://music.163.com/api/song/lyric?' + 'id=' + str(191232) + '&lv=1&kv=1&tv=-1'
 6 lyric = requests.get(lrc_url)
 7 json_obj = lyric.text
 8 j = json.loads(json_obj)
 9 lrc = j['lrc']['lyric']
10 pat = re.compile(r'\[.*\]')
11 lrc = re.sub(pat, "", lrc)
12 lrc = lrc.strip()
13 print(lrc)

 

由於本人對歌神的崇拜猶如滔滔江水之連綿不絕,幾乎他的每一首歌都很喜歡,所以我想多下幾首歌的歌詞,熱心的吃瓜群眾可能會這樣提醒我換一首歌,把URL復制進去替換一下不就OK了嗎,但是作為一個連吃飯都舍不得下床的極度懶惰者我怎么可能會做這樣繁瑣的事呢!誒換了一首歌也只是歌曲的ID發生了變化。找到規律了!我們可以定義一個這樣的函數根據歌曲的ID去自動下載歌曲的歌詞,我們想要下載哪首歌曲的歌詞需要輸入歌曲的ID就可以了!我們可以看到張學友的主頁有50首最熱門的單曲,我們姑且就先定一個小目標,下他個50首歌!根據我們剛剛的思路我們只需要從這個頁面篩選出這50首歌曲的ID就可以了!這時候我們又遇到了和剛剛一樣的問題,print一個居然找不到我們需要的元素。歷經千辛萬苦終於get到了一個爭氣的URL,

'http://music.163.com/artist?id=' + str(6460)
同樣,經過一番篩我們找到了自己需要的東西,那就是一大串的music_id!說了這么多上代碼
 1 # -*- coding:utf-8 -*-
 2 import requests
 3 import json
 4 import re
 5 from bs4 import BeautifulSoup
 6 singer_url = 'http://music.163.com/artist?id=' + str(6460)
 7 web_data = requests.get(singer_url)
 8 soup = BeautifulSoup(web_data.text, 'lxml')
 9 singer_name = soup.select("#artist-name")
10 r = soup.find('ul', {'class': 'f-hide'}).find_all('a')
11 r = (list(r))
12 music_id_set=[]
13 for each in r:
14     song_name = each.text  # print(each.text)
15     song_id = each.attrs["href"]
16     music_id_set.append(song_id[9:])
17 print(music_id_set)

再來一張效果圖

 有了這些我們就可以根據一個歌手的ID爬取這個歌手的50首熱門歌曲的歌詞,定義一個函數即可,這里就不貼代碼了。就這樣我成功的爬取了歌神的50首熱門歌曲的所有歌詞!講到這里可能有的朋友說自己的偶像不是學友哥啊,我想爬取其他歌手的歌詞,比如說我們的華仔啊,周董啊,天后王菲啊.....於是我就又折騰了一下,找到這樣一個頁面“華語樂壇歌手歷史地位排行top50”(注:歌手排列順序為網上搬運,不代表單主看法,排行榜出處網址: http://m.icaijing.com)索性我就我把這五十個歌手的50首熱門歌曲都爬取下來吧!不料又出了一個問題!下載到某位歌手的一首歌時報錯了!

思考了一會,覺得代碼沒有問題啊!於是做了一個標記,可以讓我看到是下載到哪個歌手的哪個歌手的哪一首歌時出了錯誤,機智的我終於找到了問題所在,原來是該歌曲沒有提供歌詞!於是又添了幾行代碼引入了異常機制!終於完美了!下面附上源代碼及效果圖

 1 # -*- coding:utf-8 -*-
 2 import requests
 3 from bs4 import BeautifulSoup
 4 import json
 5 import re
 6 top50_singer_url='http://music.163.com/playlist?id=119712779'
 7 web_data=requests.get(top50_singer_url)
 8 soup=BeautifulSoup(web_data.text,'lxml')
 9 
10 R=soup.textarea.text#找到歌手ID所在的標簽
11 
12 json_obj=json.loads(R)
13 top50_singer_ID_set=[]
14 for each in json_obj:
15     singer_ID=each['artists'][0]['id']
16     top50_singer_ID_set.append(singer_ID)#將排名前50的歌手的id存進一個列表
17 
18 
19 def func(singer_ID1):#定義一個函數,通過一個歌手的id下載其最火的五十首歌的全部歌詞
20 
21 
22     from bs4 import BeautifulSoup
23     singer_url  = 'http://music.163.com/artist?id=' + str(singer_ID1)
24     web_data=requests.get(singer_url)
25     soup=BeautifulSoup(web_data.text,'lxml')
26     singer_name=soup.select("#artist-name")
27 
28     singer_name=singer_name[0].get('title')
29 
30     r=soup.find('ul',{'class':'f-hide'}).find_all('a')
31     r=(list(r))
32     music_id_set=[]
33     music_name_set=[]
34     for each in r:
35         song_name=each.text#print(each.text)
36         music_name_set.append(song_name)
37 
38         song_id=each.attrs["href"]
39         music_id_set.append(song_id[9:])
40 
41 
42 
43     dic=dict(map(lambda x,y:[x,y],music_name_set,music_id_set))#將音樂名字和音樂id組成一個字典
44 
45 
46     from bs4 import BeautifulSoup
47     def get_lyric_by_music_id(music_id):#定義一個函數,通過音樂的id得到歌詞
48         lrc_url = 'http://music.163.com/api/song/lyric?' + 'id=' + str(music_id) + '&lv=1&kv=1&tv=-1'
49 
50         lyric=requests.get(lrc_url)
51         json_obj=lyric.text
52         #print(json_obj)
53         j=json.loads(json_obj)
54         #print(type(j))#打印出來j的類型是字典
55         try:#部分歌曲沒有歌詞,這里引入一個異常
56             lrc=j['lrc']['lyric']
57             pat=re.compile(r'\[.*\]')
58             lrc=re.sub(pat,"",lrc)
59             lrc=lrc.strip()
60             return lrc
61         except KeyError as e:
62             pass
63     x=0
64     for i in music_id_set:
65         x=x+1
66 
67 
68         print(x)
69         top_50_lyric=get_lyric_by_music_id(i)
70 
71         f=open("F:/projects/scrapy/%s.txt" % singer_name,"ab")#單個文件存儲一個歌手的50首熱門歌曲的歌詞並以歌手的名字命名
72         try:#引入異常
73             f.write(top_50_lyric.encode('utf-8'))
74 
75             f.close()
76         except AttributeError as e2:
77             pass
78 for singer_ID in top50_singer_ID_set:#依次將列表中的id代表的歌手的歌詞下載下來
79     singer_ID1=singer_ID
80     func(singer_ID1)

至此,第一篇學習筆記就要完結了!由於本人才疏學淺,加上又是第一次寫博,文章中會出現一些錯誤或者不規范的地方,希望大家諒解!也歡迎各位大佬指出不足,謝謝大家!!

 

 

 

 

 

 

 

 
        
 
        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM