接触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)
至此,第一篇学习笔记就要完结了!因为本人才疏学浅,加上又是第一次写博,文章中会出现一些错误或者不规范的地方,但愿你们谅解!也欢迎各位大佬指出不足,谢谢你们!!