前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【一起学Python】爬取网易云歌词

【一起学Python】爬取网易云歌词

作者头像
不二小段
发布2018-04-08 11:42:29
1.3K0
发布2018-04-08 11:42:29
举报
文章被收录于专栏:不二小段不二小段不二小段

说在前面:这是公众号第一篇来自小伙伴的投稿。我之前挖过一个坑,说想抓取歌词以后做文本分析,后面不了了之了。刚好Ricky作为爬虫的初学者,需要小项目练手,他就把这件事接了过去,帮我填坑。作为初学者,做项目和做笔记是很重要的。Ricky把文章发给我后让我帮他改,我觉得其实每个人写文章风格不一样,有的人逗比,有的人严谨,只要能把事情讲清楚就好了。至于代码,只要能实现需求,我其实不在乎是Pythonic还是ugly。这也是一系列文章的第一篇,希望大家也能多多指点。

▲ ▲ ▲

接触python也有一段时间了,一提到python,可能大部分pythoner都会想到爬虫,没错,今天我们的话题就是爬虫!作为一个小学生,关于爬虫其实本人也只是略懂,怀着”Done is better than perfect”的态度硬着头皮开始了这篇文章的撰写!好了,废话不多说!

  先说一下今天我们的目的,作为一个音痴但不影响我对于音乐的执着,所以今天我们爬取的是网易云音乐,我们将会通过代码爬取歌词并写入到本地。

  作为新手,我很本能就打开页面复制了url,然后用Beautifulsoup解析了网页并打印出来,然后去查找歌词所在的标签,心想这不是so easy吗!写下了以下代码

# -*- coding:utf-8 -*-
import requests
from bs4 import BeautifulSoup
lrc_url = "http://music.163.com/#/song?id=191232"

lyric = requests.get(lrc_url)
soup = BeautifulSoup(lyric.text,'lxml')
print(soup)

卧擦嘞,打印出来了一些什么鬼啊!居然没有找到歌词!怎么办!怎么办!沉思了良久后我觉得我掉进了一个巨坑,事情绝对没有那么简单!.....(心情无比悲痛,此处省略一万字)作为平常屡试不爽的招数今天居然装逼失败!痛定思痛,我觉得肯定是URL的问题,经过一番思索发现原来我找了一个假的URL!几经波折,找到了这样一个URL

'http://music.163.com/api/song/lyric?' + 'id=' + str(191232) + '&lv=1&kv=1&tv=-1'

打印出来的效果是这样的:

这才像那么回事了,但是发现里面还多了一些不需要的东西。

第二步,筛选出我们需要的元素,这里我们将用到正则表达式和json,切记用之前先导入这两个模块。加入几行代码,筛选后的结果为:

到这里我们已经基本上完成了我们的工作。最后一步,写入文本就不多说了,这样我们再加上几行代码就搞定了!这里我们先贴上之前的代码

# -*- coding:utf-8 -*-
import requests
import json
import re
lrc_url = 'http://music.163.com/api/song/lyric?' + 'id=' + str(191232) + '&lv=1&kv=1&tv=-1'

lyric = requests.get(lrc_url)
json_obj = lyric.text
j = json.loads(json_obj)
lrc = j['lrc']['lyric']
pat = re.compile(r'\[.*\]')
lrc = re.sub(pat, "", lrc)
lrc = lrc.strip()
print(lrc)

由于本人对歌神的崇拜犹如滔滔江水之连绵不绝,几乎他的每一首歌都很喜欢,所以我想多下几首歌的歌词,热心的吃瓜群众可能会这样提醒我换一首歌,把URL复制进去替换一下不就OK了吗,但是作为一个连吃饭都舍不得下床的极度懒惰者我怎么可能会做这样繁琐的事呢!诶换了一首歌也只是歌曲的ID发生了变化。找到规律了!我们可以定义一个这样的函数根据歌曲的ID去自动下载歌曲的歌词,我们想要下载哪首歌曲的歌词需要输入歌曲的ID就可以了!我们可以看到张学友的主页有50首最热门的单曲,我们姑且就先定一个小目标,下他个50首歌!根据我们刚刚的思路我们只需要从这个页面筛选出这50首歌曲的ID就可以了!这时候我们又遇到了和刚刚一样的问题,print一个居然找不到我们需要的元素。历经千辛万苦终于get到了一个争气的URL,

'http://music.163.com/artist?id=' + str(6460)

同样,经过一番筛我们找到了自己需要的东西,那就是一大串的music_id!说了这么多上代码

# -*- coding:utf-8 -*-
import requests
import json
import re
from bs4 import BeautifulSoup
singer_url = 'http://music.163.com/artist?id=' + str(6460)
web_data = requests.get(singer_url)
soup = BeautifulSoup(web_data.text, 'lxml')
singer_name = soup.select("#artist-name")
r = soup.find('ul', {'class': 'f-hide'}).find_all('a')
r = (list(r))
music_id_set=[]
for each in r:
    song_name = each.text  # print(each.text)
    song_id = each.attrs["href"]
    music_id_set.append(song_id[9:])
print(music_id_set)

再来一张效果图

有了这些我们就可以根据一个歌手的ID爬取这个歌手的50首热门歌曲的歌词,定义一个函数即可,这里就不贴代码了。就这样我成功的爬取了歌神的50首热门歌曲的所有歌词!讲到这里可能有的朋友说自己的偶像不是学友哥啊,我想爬取其他歌手的歌词,比如说我们的华仔啊,周董啊,天后王菲啊.....于是我就又折腾了一下,找到这样一个页面“华语乐坛歌手历史地位排行top50”(注:歌手排列顺序为网上搬运,不代表单主看法,排行榜出处网址: http://m.icaijing.com)索性我就我把这五十个歌手的50首热门歌曲都爬取下来吧!不料又出了一个问题!下载到某位歌手的一首歌时报错了!

思考了一会,觉得代码没有问题啊!于是做了一个标记,可以让我看到是下载到哪个歌手的哪个歌手的哪一首歌时出了错误,机智的我终于找到了问题所在,原来是该歌曲没有提供歌词!于是又添了几行代码引入了异常机制!终于完美了!下面附上源代码及效果图

# -*- coding:utf-8 -*-
import requests
from bs4 import BeautifulSoup
import json
import re
top50_singer_url='http://music.163.com/playlist?id=119712779'

web_data=requests.get(top50_singer_url)
soup=BeautifulSoup(web_data.text,'lxml')

R=soup.textarea.text#找到歌手ID所在的标签json_obj=json.loads(R)
top50_singer_ID_set=[]
for each in json_obj:
    singer_ID=each['artists'][0]['id']
    top50_singer_ID_set.append(singer_ID)#将排名前50的歌手的id存进一个列表def func(singer_ID1):#定义一个函数,通过一个歌手的id下载其最火的五十首歌的全部歌词
    singer_url  = 'http://music.163.com/artist?id=' + str(singer_ID1)
    web_data=requests.get(singer_url)
    soup=BeautifulSoup(web_data.text,'lxml')
    singer_name=soup.select("#artist-name")
    singer_name=singer_name[0].get('title')
    r=soup.find('ul',{'class':'f-hide'}).find_all('a')
    r=(list(r))
    music_id_set=[]
    music_name_set=[]    
      for each in r:
        song_name=each.text#print(each.text)
        music_name_set.append(song_name)
        song_id=each.attrs["href"]
        music_id_set.append(song_id[9:])
    dic=dict(map(lambda x,y:[x,y],music_name_set,music_id_set))#将音乐名字和音乐id组成一个字典

    def get_lyric_by_music_id(music_id):#定义一个函数,通过音乐的id得到歌词
        lrc_url = 'http://music.163.com/api/song/lyric?' + 'id=' + str(music_id) + '&lv=1&kv=1&tv=-1'
        lyric=requests.get(lrc_url)
        json_obj=lyric.text        #print(json_obj)
        j=json.loads(json_obj)        #print(type(j))#打印出来j的类型是字典
        try:#部分歌曲没有歌词,这里引入一个异常
            lrc=j['lrc']['lyric']
            pat=re.compile(r'\[.*\]')
            lrc=re.sub(pat,"",lrc)
            lrc=lrc.strip()            
                  return lrc        
            except KeyError as e:
            pass
    x=0
    for i in music_id_set:
        x=x+1

        print(x)
        top_50_lyric=get_lyric_by_music_id(i)

        f=open("F:/projects/scrapy/%s.txt" % singer_name,"ab")#单个文件存储一个歌手的50首热门歌曲的歌词并以歌手的名字命名
        try:#引入异常
            f.write(top_50_lyric.encode('utf-8'))
            f.close()        
        except AttributeError as e2:
            pass

for singer_ID in top50_singer_ID_set:#依次将列表中的id代表的歌手的歌词下载下来
    singer_ID1=singer_ID
    func(singer_ID1)

至此,第一篇学习笔记就要完结了!由于本人才疏学浅,加上又是第一次写博,文章中会出现一些错误或者不规范的地方,希望大家谅解!也欢迎各位大佬指出不足,谢谢大家!!

▲ ▲ ▲

最后插播软广。关于爬取歌词我之前录过一小节视频。其实很多时候感觉视频比文章更能把事情讲清楚。感兴趣的小伙伴可以看一下。

http://v.youku.com/v_show/id_XMjcwOTU4MzU4NA==

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-04-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 不二小段 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档