数据分析:当回音哥唱music时,他在唱些什么~~~

2 篇文章 0 订阅
1 篇文章 0 订阅

思路来源于此,注明出处:

https://mp.weixin.qq.com/s/gx04XBv0qRuQB75ccPCi3g

尊重原创

——————————————————————————————

简单来说,我们想分析某一位歌手所唱的所有歌曲(主流网站上可以找出来的),主要出现的词汇是什么(更能反映歌手的偏好)。下面开始动手做:

第一个,爬数据

爬数据这里我用的是scrapy + selenium,二话不说,先上代码:

# scrapy中置于 spider 下的 爬虫.py

from scrapy import Spider,Request
from selenium import webdriver
from .. import process_text_format
from .. import items


class HuiyingeSpider(Spider):
    name = 'huiyinge'
    allowed_domains=['https://y.qq.com']

    def __init__(self):
        self.browser = webdriver.Chrome()
        self.browser.set_page_load_timeout(30)

    def closed(self,spider):
        print("spider closed")
        self.browser.close()

    def start_requests(self):
        start_urls = ['https://y.qq.com/portal/search.html#page={}&searchid=1&remoteplace=txt.yqq.top&t=lyric&w=%E5%9B%9E%E9%9F%B3%E5%93%A5'.format(str(i)) for i in range(1,11,1)]
        for url in start_urls:
            yield self.make_requests_from_url(url=url)

    def parse(self, response):
        titles = response.xpath('//*[@id="lyric_box"]/div[1]/ul/li/h3/a[1]/text()').extract()
        lrcs = response.xpath('//*[@id="lyric_box"]/div[1]/ul/li/div[2]/p').extract()

        for title, lrc in zip(titles, lrcs):
            item = items.HuiyingeItem()
            item['title'] = title
            item['lrc'] = process_text_format.prcessTextFormat(lrc)
            yield item

这里我们选择的是*q音乐,嗯,回音哥的音乐在这个网站上比较全

这里由于后边我们对数据的保存需要(我们是保存到文件txt中的,而不是存入数据库),我们把歌名当做txt文件名,歌词存入其中充当内容,所以分成title和lrc两个字段,但是lrc里有很多html标签,例如<p><span>之类的,我们要取出较为正常的歌词,对此我们做一个格式化处理,就是上面的prcessTextFormat函数

#scrapy 下 自己创建的py文件 process_text_format.py

def prcessTextFormat(text):

    flagOfIsHaveHtml = text.find('<')

    while flagOfIsHaveHtml != -1:
        indexStart = flagOfIsHaveHtml
        indexEnd = text.find('>')
        text = text.replace(text[indexStart:indexEnd + 1], '\n', 1)
        flagOfIsHaveHtml = text.find('<')

    return text.strip()

if __name__ == '__main__':
    text = '''<p>天后 - <span class="c_tx_highlight">回音哥</span> (Echo)<br> 词:彭学斌<br> 曲:彭学斌<br> 终于找到借口趁着醉意上心头<br> 表达我所有感受<br> 寂寞渐浓沉默留在舞池角落<br> 你说的太少或太多<br> 都会让人更惶恐<br> 谁任由谁放纵谁会先让出自由<br> 最后一定总是我<br> 双脚悬空在你冷酷热情间游走<br> 被侵占所有还要笑着接受<br> 我嫉妒你的爱气势如虹<br> 像个人气高居不下的天后<br> 你要的不是我而是一种虚荣<br> 有人疼才显得多么出众<br> 我陷入盲目狂恋的宽容<br> 成全了你万众宠爱的天后<br> 若爱只剩诱惑只剩彼此忍受<br> 别再互相折磨<br> 因为我们都有错<br> 推开苍白的手推开苍白的厮守<br> 管你有多么失措<br> 别再叫我心软是最致命的脆弱<br> 我明明都懂却仍拼死效忠<br> 我嫉妒你的爱气势如虹<br> 像个人气高居不下的天后<br> 你要的不是我而是一种虚荣<br> 有人疼才显得多么出众<br> 我陷入盲目狂恋的宽容<br> 成全了你万众宠爱的天后<br> 若爱只剩诱惑只剩彼此忍受<br> 别再互相折磨<br> 因为我们都有错<br> 如果有一天爱不再迷惑<br> 足够去看清所有是非对错<br> 直到那个时候<br> 你在我的心中<br> 将不再被歌颂<br> 把你当作天后<br> 不会再是我</p>'''
    print(prcessTextFormat(text))

由于我们选择是selenium来去加载页面(这样就不用害怕js或者之类的加载东东导致我们不能爬到数据了),所以我们需要修改中间键

#scrapy 下的 middlewares.py

from scrapy.http import HtmlResponse
from selenium.common.exceptions import TimeoutException
import time

class SeleniumMiddleware(object):
    def process_request(self, request, spider):
        if spider.name == 'huiyinge':
            try:
                spider.browser.get(request.url)
                # elem = spider.browser.find_element_by_class_name('next js_pageindex')
            except TimeoutException as e:
                print('超时')
                spider.browser.execute_script('window.stop()')
            time.sleep(2)
            return HtmlResponse(url=spider.browser.current_url, body=spider.browser.page_source,
                                encoding="utf-8", request=request)

同样贴出items.py和pipelines.py,感觉没什么好说的,pipelines我选择的处理方式是直接把数据保存成文件而不是存入数据库

# scrapy 下的 items.py

import scrapy


class HuiyingeItem(scrapy.Item):
    # define the fields for your item here like:
    title = scrapy.Field()
    lrc = scrapy.Field()
# scrapy 下的 pipelines.py

class ScrapySeleniumPipeline(object):

    def process_item(self, item, spider):

        fileName = item['title']

        with open('file/{}.txt'.format(fileName), 'w') as f:
            f.write(item['lrc'])

为了在运行过程中便于调试,我们加一个脚本

# scrapy 下 新建的便于pycharm运行和调试的脚本py begin.py

from scrapy import cmdline
cmdline.execute("scrapy crawl huiyinge".split())

然后把这个在 运行/调试设置 里面设置一下就好了(更详细的过程百度也有,这里就不再赘述了)

展示一个爬到的歌曲吧,也是目前比较喜欢的一首歌:

然后问题来了,lrc里有很多冗余字段,比如重复出现歌手,监制,编曲之类的人名,这些可能会对我们后边筛选关键词造成影响,所以我们做一个简单的预处理,剔除其中的一些字段(正式歌词之前的段落)

 

# pretreatment_huiyin.py  预处理歌词py

import os

def remove_sundry(line):
    indexOfColon = line.find(':')
    if (indexOfColon != -1):
        if line.__len__() == (indexOfColon + 1):
            return 2
        return 1
    return 0

flagOfIsSkip = False

if __name__ == '__main__':
    list = os.listdir('file')
    for fileName in list:
        if(fileName.find('.txt') != -1):
            with open('file/{}'.format(fileName),'r') as f:
                 # print(fileName)
                index = 1
                newFile = '';
                for line in f.readlines():
                    # print(line)
                    if (index > 3):

                        if flagOfIsSkip:
                            flagOfIsSkip = False
                            continue

                        flagOfIdAdd = remove_sundry(line)

                        if flagOfIdAdd == 0:
                            newFile += line
                        if flagOfIdAdd == 2:
                            flagOfIsSkip = True

                    else:
                        index = index + 1

            with open('file/{}'.format(fileName), 'w') as f:
                f.write(newFile)

这里处理的效果并不是很理想,首先把前三行除掉,因为前三行都是歌名,歌手名,还有他的英文名,然后我们队后边的段落检查是否这一行有冒号(:)有的话,说明这一行是类似于监制,编曲之类的冗余信息,我们就把他去掉,然而还是有漏网之鱼,有的冒号之后没有内容,而是直接换行显示对应的音乐人,我们加一个检查就是如果冒号后换行的话,就删掉下一行,然而即使这样,还是又一部分有漏网之鱼(唉,只能抱怨一句网站还是不够规范吧)。剩下的自己稍微改一下吧。(格式太千奇百怪的话,也就只能人为干预了,哼!)

修改好后,我们就开始正式的分析数据了,上代码

# 分析数据的py analyze_huiyin.py

import jieba.posseg as psg
import os
from collections import Counter

def check_word_characteristic(word_flag):
    if(word_flag.find('r') != -1 or word_flag.find('p') != -1 or word_flag.find('c') != -1 or word_flag.find('u') != -1):
        return False
    return True

if __name__ == '__main__':

    files = os.listdir('file')
    print(files.__len__())
    items = []
    for fileName in files:
        if(fileName.find('.txt') != -1):
            with open('file/{}'.format(fileName),'r') as f:
                item = []
                itemSet = set()
                for line in f.readlines():
                    for word, flag in psg.cut(line.strip()):
                        if(check_word_characteristic(flag)):
                            temp = word + "_" + flag;
                            item.append(temp)
            itemSet.update(item)
            items.append(itemSet)
    counter_items = Counter()
    for item in items:
        counter_items.update(item)
    print(counter_items)

这里主要的思想前面的微信公众号已经说了,主要是就读取数据 -> 对单个歌曲做分词,set去重 -> 统计所有的歌曲,累加起来 -> collections.counter来进行统计。这里我们加上了词性的过滤,过滤掉一些助词,代词,介词,连词之类的虚词

最后的统计结构展示一下(人为过滤了一下常见的动词)

 

'没有_v': 21

'不会_v': 18

'不要_df': 16

'知道_v': 15

'幸福_a': 15

'寂寞_a': 14

'不能_v': 14

'梦_n': 13

'眼泪_n': 12

'永远_d': 12

 

emmmm。。。。,好吧,回音哥确实比较伤感吧。(笑哭表情)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值