接觸python也有一段時間了,一提到python,可能大部分pythoner都會想到爬蟲,沒錯,今天咱們的話題就是爬蟲!做爲一個小學生,關於爬蟲其實本人也只是略懂,懷着」Done is better than perfect」的態度硬着頭皮開始了這篇文章的撰寫!好了,廢話很少說!python
先說一下今天咱們的目的,做爲一個音癡但不影響我對於音樂的執着,因此今天咱們爬取的是網易雲音樂,咱們將會經過代碼爬取歌詞並寫入到本地。web
做爲新手,我很本能就打開頁面複製了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!幾經波折,找到了這樣一個URLjson
'http://music.163.com/api/song/lyric?' + 'id=' + str(191232) + '&lv=1&kv=1&tv=-1'
打印出來的效果是這樣的:
這纔像那麼回事了,可是發現裏面還多了一些不須要的東西。api
第二步,篩選出咱們須要的元素,這裏咱們將用到正則表達式和json,切記用以前先導入這兩個模塊。加入幾行代碼,帥選後的結果爲:app
到這裏咱們已經基本上完成了咱們的工做。最後一步,寫入文本就很少說了,這樣咱們再加上幾行代碼就搞定了!這裏咱們先貼上以前的代碼scrapy
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,ide
'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)
至此,第一篇學習筆記就要完結了!因爲本人才疏學淺,加上又是第一次寫博,文章中會出現一些錯誤或者不規範的地方,但願你們諒解!也歡迎各位大佬指出不足,謝謝你們!!