朴树歌词分析--python爬虫

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_26025363/article/details/79145607

朴树的歌到底都在唱些什么?

前言

朴树去年新出了一张专辑《猎户星座》,其中出了几首个人非常欣赏的曲子。朴树这个人很奇怪,不走寻常路。对他的个人不做过多评价,就想看看能不能通过他的音乐来了解一下它。旋律什么的都不是很懂,我只决定好听就行了。那么,剩下的只能分析歌词了。所以我爬取了朴树的所有歌曲的歌词。以下就爬取过程和爬下来的结果进行一波分析。

结果分析

总共爬取了80首歌,总共14张专辑的歌。然后对所有的歌词进行分词,根据分词后的结果进行了统计。由于分词后的结果占比最多的肯定是一个字的,但是一个字的东西给的信息太少,所以我挑选了所有结果的前200个的二字词语和三字词语。这时候就可以看出很多的信息了。

二个字的词语分析

下面是出现次数的最多的前200词语中的二字词语:

'什么', 87)('my', 87)('我们', 74)('曾经', 70)('朴树', 68)('一切', 67)('就让', 53)('那么', 49)('这么', 47)('不能', 44)('放在', 42)('on', 39)('所有', 36)('归来', 36)('天真', 36)('人生', 36)('世界', 36)('坠入', 33)('那个', 33)('时光', 30)('永远', 30)('年少', 30)('放开', 29)('黑夜', 29)('没有', 29)('咿呀', 29)('只有', 27)('明天', 27)('路过', 27)('no', 26)('那些', 26)('他们', 26)('交给', 25)('一样', 25)('沉入', 25)('故事', 25)('不知', 24)('快乐', 24)('天空', 24)('黑暗', 24)('自然', 23)('亚东', 23)('一天', 21)('植物', 21)('离开', 21)('真得', 20)('动物', 20)('in', 20)('还是', 19)('今天', 19)('两手', 19)('拥有', 19)('野草', 19)('就算', 19)('风吹', 19)('自己', 18)('今日', 18)('从此', 18)('再见', 18)('天涯', 18)('知道', 17)('骄傲', 17)('命运', 16)('夕阳', 16)('暗中', 16)('才能', 16)('平凡', 16)('向前', 16)('up', 16)('is', 16)('永不', 15)('这样', 15)('熄灭', 15)('再次', 15)('真正', 15)('过人', 15)('阳光', 14)('昨天', 14)('沉默', 14)('不再', 14)('陌生', 14)('彻底', 14)('不敢', 14)('反顾', 14)

括号中分别是他们的出现的频率。仔细分析一下,还是能看出,整个辞藻还是很多大气的,朴树的人还是很理想的。好吧,其实我也看不出到底主要是什么感情色彩的,或者展现了朴树的什么性格。是否有现成的一些识别词语的褒义还是贬义或者是积极还是消极的词的库,把上面的所有高频词进行一波判断,然后在得出结果,应该就能看出朴树的歌词的积极和消极了吧(我猜的QAQ)。这个其实歌曲还是很主观的,每个人的理解不同,还是不能这么理性的分析。

三个词的分析

前200个单词中出现3个字的词语就只有这些个词。

('now', 70)
('and', 25)
('为什么', 23)
('bad', 20)
('the', 20)
('can', 20)
('way', 19)
('向前走', 16)

如果只看第一眼,还是能看出朴树的歌曲还是很积极的,但是中文是很博大精深的,很多东西是要根据语境来判断的,这只能说用词还是蛮积极向上的。

四个词的词语

四个词的词语就如下这些了:

('that', 39)
('open', 35)
('yeah', 19)
('灰飞烟灭', 15)
('good', 14)
('义无反顾', 14)

其实我也分析不出来什么,就大概这么个意思吧。每个人心中都有一个莎士比亚还是哈姆雷特来着,大概就是这个意思。


爬取思路

前奏

第一目标本来是打算爬取网易云的朴树的所有歌曲的歌词的,但是,实践告诉我不行,网易云的html是动态加载的,访问的html都是渲染前的,根本加载不出所有的链接或者信息。是需要浏览器的运行环境,才能动态加载。但是我写的脚本是直接发的HTTP请求,请求该html页面,并没有浏览器的环境。
第二目标又转战腾讯,想爬qq音乐的歌曲,但是呢,qq音乐的歌曲的链接信息也是动态操作才能加载的。是通过鼠标的onmouseover和mouseout事件控制信息的显示。对于HTTP请求静态资源,我并不能模拟用户的鼠标操作,也没有浏览器的运行环境。所以爬QQ音乐卒。
结果就找了阿里家的虾米音乐,可能用户量不大吧,所有的资源一如既往的好爬。

具体过程

  1. 首先,爬取朴树的所有歌曲,是需要数据筛选的,不能是他唱的歌曲都爬一下,可能有些歌曲是跟别人合唱的,但是都是一首歌,被收录了很多次。这样的话,直接爬所有歌会出现大量的重复,从而对爬取结果有影响。所以我选择根据专辑进行爬取,每一张专辑都是唯一的,不会出现重复。这样的数据的可靠性有所保障。

  2. 接着,就是找到朴树的所有专辑的页面了,发现qq音乐不需要登陆也可能去点击响应的专辑或者歌。然后具体的歌的话页面上会有对应的歌词。这就非常人性了,不需要模拟登陆这个部分了。所以按照常规思路,只要先请求朴树的所有专辑页面,然后对该页面上的所有专辑信息进行提取,保存专辑的名字和专辑的链接,存到本地的数组里面。然后根据数组里面的专辑url,分别在请求对应的html页面,根据请求的html,进行解析,找到所有对应的歌曲。这里虾米音乐的歌曲有的不是朴树的链接,这时候就需要一次过滤。然后对每首歌的页面分别请求,提取歌词的信息。存到内存中。后续就是对应的数据处理和分析。对所有的额数据进行操作了。

拓展

  1. 对于性能问题,因为朴树的歌也比较少,如果用框架scrapy框架的话,有点大材小用了。不需要那么大的武器来做这件事。其次,内存完全够存储,总共也就2000多个词。如果需要保存的话,可以连接数据库,进行数据库的插入操作,也不是很麻烦,只是对于这个没啥必要,我把它写入到文件中去了。
  2. 对于上述的思路,由于虾米音乐的html都是相似的,如果爬取其他歌手的专辑,应该也是很容易修改的,只要稍加修改,可能是一些CSS选择器的改变吧,可扩展行还行。
  3. 对于上述爬取网易云和腾讯的音乐失败问题,网易云的链接还有锚点这种操作,一定要注意好。http://music.163.com/#/search/m/?s=%E6%9C%B4%E6%A0%91&type=100,比如这个链接,中间有个#,这是锚点,如果直接发这个http请求的话,会得不到正确的html。
    所以对于上述的问题,大概有以下几种解决思路吧:(个人没尝试过,希望有人能指出问题)
    1. python有一个包,是解析动态网页加载的,名字是selenium.可以去官方文档上看这个.
    2. 通过分析浏览器发出的Ajax请求,根据Ajax请求的参数,直接模拟浏览器发出的Ajax请求,然后解析返回的数据。

总结

其实朴树的歌我也听不懂,只是觉得很好听,但是能不能理解他,我看还是差点火候。这个歌词分析,明显看不出来。
下面是所有的python脚本代码,也可以去我的GitHub上fork。

import requests
from bs4 import BeautifulSoup 
import jieba

pushu_url='http://www.xiami.com/artist/album-IOd0c43?spm=a1z1s.6659509.6856549.3.p4Tsid';
host='http://www.xiami.com'

headers={
         'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36",
         'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8'}


def get_html(url):
    '''获取指定url的页面,返回经过处理后的html页面'''
    s=requests.session()
    response=s.get(url,headers=headers);
    bs_html=BeautifulSoup(response.text,'lxml')
    return bs_html

def get_album(url):
    '''获取所有的专辑url,传入页面的参数'''
    bsHtml=get_html(url)
    albumUrl=bsHtml.select('div.detail p.name a')
    Albums=[]
    for item in albumUrl:
        album={}
        album['href']=host+item['href']
        album['title']=item['title']
        Albums.append(album)
    return Albums

def is_song(a):
    '''判断是否是歌的链接'''
    return not a.has_attr('class')

def get_song(url):
    ''' 获取某专辑所有的歌的url,传入的是专辑的url'''
    albumHtml=get_html(url)
    songs=albumHtml.select('td.song_name a')
    songs=filter(is_song,songs)
    song=[]
    for i in songs:
        item={}
        item['href']=host+i['href']
        item['text']=i.text
        song.append(item)    
    return song

def get_song_lyric(url):
    '''获取歌的歌词,传入的是歌的url'''
    lyric_html=get_html(url)
    AllLyric=lyric_html.select('div.lrc_main')
    try:
        return AllLyric[0].text
    except IndexError:
        return ''

def tokenize(str):
    ''' 结巴分词,对输入参数str进行分词,返回分词后的结果'''
    seg_list=jieba.cut(str,cut_all=True)
    for word in seg_list:
        if(words.__contains__(word)):
            words[word]=words[word]+1
        else:
            words[word]=1

words={}

if __name__=='__main__':
    '''不作为模块名的时候运行'''
    count=0                                # 记录总的歌曲数
    albumUrls=get_album(pushu_url)
    for i in albumUrls:  
        Allsongs=get_song(i['href'])
        for j in Allsongs:
            lyric=get_song_lyric(j['href'])
            tokenize(lyric)
            count+=1            
    order_words=sorted(words.items(),key=lambda x:x[1],reverse=True)

    # 将前200个2个字的词输出
    for i in order_words[0:200]:
        if(len(i[0])==2):
            print(i)

    for i in order_words[0:200]:
        if(len(i[0])==3):
            print(i)

    for i in order_words[0:200]:
        if(len(i[0])==4):
            print(i)

    # 将所有分词的结果输出到文件
    fs=open('pushu_word.txt','w')
    for i in order_words:
        fs.writelines(str(i)) 
    fs.close

猜你喜欢

转载自blog.csdn.net/qq_26025363/article/details/79145607