知道你喜欢的歌手在唱什么吗?

版权声明:原创文章转载请注明来源。 https://blog.csdn.net/samll_snail/article/details/85937945

听了那么多的歌,也喜欢上了好些个歌手,但是你知道他们在唱什么吗?

今天我们把他们唱的歌都翻出来,把歌词都分析一遍,看看你喜欢的歌手唱的是啥。

没错,我们还是用 python 来搞定这个事,先来分析下需要做哪些事情。

1、歌曲数据采集

我们这里将从网易云音乐采集数据。通过歌手名字来搜索出他的歌曲列表,然后再得到每首歌的歌词,对获取到的歌词进行分词和过滤处理,去除一些特殊字符,和一些自定义的停用词。

2、歌词数据分析和可视化

数据经过初步处理后,就可以使用 wordcloud 来实现数据可视化了,wordcloud 可以根据所有歌词中词频来生成词云图,这样一眼就能看出哪些词语是歌词经常出现的,因此也能看出这个歌手主要是在唱什么。

其中词云图的效果是可以自定义的,包括图片大小、字体选择、字体大小、图片背景颜色等,因此大家可以自己去调整参数,生成自己喜欢的词云图。

张学友是我喜欢的歌手之一,从他的热门歌曲来看,歌神唱的歌曲大多数是和 "爱" 相关的,这个 "爱" 包含亲人之间的爱,也包含爱情,主要是和情感相关的。同时从词云图中还可以看到有 "伤心" "乱" "醉" "离开" 等词,应该也可以说明歌神的热门歌曲中多数还是以悲情歌为主的。

当然了,代码中采集的数据并不是歌手的全部歌曲,仅仅是采集的其热门歌曲,所以数据不够全面,仅供参考。

看看你喜欢的歌手又主要都是在唱什么呢?下面是完整的源码,可以直接运行,注意代码中涉及到一些第三方库,如果还有你没有安装的,请务必先自行安装,安装也很简单,建议使用 pip 命令安装。

import requests
from urllib import parse
import json
from bs4 import BeautifulSoup
import re
import numpy as np
import jieba
import matplotlib.pyplot as plt
from wordcloud import WordCloud
from PIL import Image, ImageDraw, ImageFont
import matplotlib
matplotlib.matplotlib_fname()

#定义模拟请求头
header = {
    'Accept': '*/*',
    'Accept-Encoding': 'gzip,deflate,sdch',
    'Accept-Language': 'zh-CN,zh;q=0.8',
    'Connection': 'keep-alive',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Host': 'music.163.com',
    'Referer': 'http://music.163.com/search/',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36'
}

cookie = {'appver': '1.5.3'}
stop_word = [' ','\n','(',')','(',')']

url_singer = "http://music.163.com/api/artist/"
url_song = "http://music.163.com/song?id="
url_lyric = "http://music.163.com/api/song/lyric"
search_api = "http://musicapi.leanapp.cn/search?"

#获取歌手id
def getSingerID(s):
    keyword = {'keywords':s}
    nameencode = parse.urlencode(keyword)
    url = search_api + nameencode    
    r = requests.get(url)
    ID = r.json()['result']['songs'][0]["artists"][0]["id"]    
    return ID

#加载停用词,你可以在stop_word.txt添加新的停用词
def loadStopWord():
    f = open("stop_word.txt","r")
    for line in f.readlines():
        stop_word.append(str(line.strip()))

#根据歌手id获取他的热门歌曲,注意这里并没有获取其全部歌曲
def getSongsList(singer_id):
    url = url_singer + str(singer_id)
    r = requests.get(url, headers = header, cookies = cookie)    
    hotSongs = r.json()['hotSongs']
    songList = []
    for hotSong in hotSongs:
        song = {}
        song['id'] = hotSong['id']
        song['name'] = hotSong['name']
        songList.append(song)
    return songList


#获取歌曲歌词
def getSongLyric(song_id):
    param = {
        'id': song_id,
        'lv': -1,
        'kv': -1,
        'tv': -1
    }
    r = requests.post(url_lyric, params = param,cookies=cookie, headers=header)
    soup = BeautifulSoup(r.text, "lxml")
    dic = r.json()
    l = ""
    if ('lrc' in dic):
        if ('lyric' in dic['lrc']):
            for line in dic['lrc']['lyric'].split('\n'):
                temp = line.strip()
                temp = temp[temp.find(']') + 1:].strip()
                if (temp.find(":") == -1 and temp.find(":") == -1 and len(temp) > 0):
                    l = l + temp
    return l 


#根据歌词内容生成词云图
def createWordCloud(wf,words):
    w = [] 
    f = []
    wordc = []
    for l in wf:
        w.append(l[0])
        f.append(l[1])
        wordc.append((l[0],l[1]))

    #词云的参数可以自行调整
    wc = WordCloud(
        font_path = "C:\Windows\Fonts\simhei.ttf", #文字字体
        background_color = '#000000', #背景颜色
        margin=1, #词语间距
        width=2000, #图片宽度
        height=1000, #图片高度
        max_words = 2000,  #最多显示词语数   
        # max_font_size = 30, #最大字体
        min_font_size = 10, #最小字体
        scale = 1, #图片放大倍数
        relative_scaling = .5,
        prefer_horizontal = 90
    ).fit_words(dict(wordc))


    #显示图片
    plt.figure()
    plt.imshow(wc, interpolation='bilinear')
    plt.axis("off")
    plt.show()


    #图片保存到本地
    wc.to_file('./singer.png')


#程序开始
s = input("请输入你喜欢的歌手.\n>")
singer_id = getSingerID(s)
#loadStopWord()

songList = getSongsList(singer_id)
words = []

for song in songList:
    string = getSongLyric(song['id'])
    seg = jieba.cut(string)
    for word in seg:
        if (word not in stop_word):
            words.append(word)
    print(song['name']," 歌词获取完成.")


wf = {}
for word in words:
    if (word in wf.keys()):
        wf[word] += 1
    else:
        wf[word] = 1

wf = sorted(wf.items(), key = lambda item:item[1],reverse=True)
createWordCloud(wf,"".join(words))

猜你喜欢

转载自blog.csdn.net/samll_snail/article/details/85937945
今日推荐