[Python+requests+BeautifulSoup/lxml+jieba+pyecharts]B站弹幕的爬取及其词云分析——书记带把的嘛?

一、BeautifulSoup与lxml库的区别与比较

    简单地概括二者的区别,在于操作的灵活性,本质上都是在解析html文档。

    lxml是使用C语言完成XML处理的第三方库,因为C语言的特性,可以及其高速的运行。但是,同时操作起来非常灵活,也许不适用于初学者。

    BeautifulSoup,相反地,尽管操作没有lxml那么灵活,但是操作简单易懂。内部有4个解析器(常用为lxml解析器),可以根据使用目的进行替换。

二、XML是什么,以及B站弹幕的位置

    XML,可扩展标记语言,是对超文本标记语言的补充。

    它和超文本标记语言为不同的目的而设计:

            1,它被设计用来传输和存储数据,其焦点是数据的内容。

            2,超文本标记语言被设计用来显示数据,其焦点是数据的外观。

    超文本标记语言旨在显示信息,而它旨在传输信息。

    对它最好的描述是:它是独立于软件和硬件的信息传输工具。

    因此弹幕作为实时数据,必然会存储在XML文件中。自然地,B站视频上的弹幕都有一个对应的XML文件,于是我们可以通过解析XML文件获取到B站视频的弹幕。

    那么它在哪里呢?

     打开heartbeat这个文件,在这里能够看到aid即为视频号(能在url找到它),cid即是存储弹幕的编号。 

     在访问时,按照这个进行访问就ok了。

http://comment.bilibili.com/(cid).xml

     那么在这里就是http://comment.bilibili.com/77853722.xml

三、利用Beautifulsoup或者lxml库进行弹幕信息的爬取,并通过pandas存储为csv文件

   以上是访问xml文件的结果,发现了弹幕都是在标签上的。因此只要能够访问所有的d标签并进行文本的抽取,即可完成弹幕的爬取。 

Beautifulsoup的做法:

import requests
from bs4 import BeautifulSoup

url = 'https://comment.bilibili.com/69082679.xml'
response = requests.get(url)
html = response.content
html_doc = str(html, 'utf-8')

soup = BeautifulSoup(html_doc, 'lxml')
results = soup.find_all('d')
contents = [ x.text for x in results ]

lxml的做法:

import requests
import lxml.html

url = 'https://comment.bilibili.com/77853722.xml'
response = requests.get(url)
html = lxml.html.fromstring(response.content)
print(type(html))           #在这里返回

h1 = html.cssselect('d')
print(type(h1))             #在这里返回 
contents = [x.text for x in h1]

再利用pandas的Dataframe进行csv文件的输出:

import pandas as pd

table_dict = {"contents":contents}
df = pd.DataFrame(table_dict)
df.to_csv("bibi.csv", encoding = 'utf-8')

结果大致为:

[Python+requests+BeautifulSoup/lxml+jieba+pyecharts]B站弹幕的爬取及其词云分析——书记带把的嘛?_第1张图片

四、使用jieba、pyecharts进行词云分析

 首先利用jieba库进行单词的获取

import jieba

def get_word(file, stop_words):
    df = pd.read_csv(file, encoding = 'utf-8')
    df.head()                   #确认数据有没有进来
    df.dropna(inplace = True)   #清除缺失值
    content = df.contents.values.tolist()   #将contents一列转换为list列表
    segment = list()
    #jieba分词
    for line in content:
        try:
            segs = jieba.cut_for_search(line)
            segs = [v for v in segs if not str(v).isdigit()]
            for seg in segs:
                if len(seg) > 1 and seg != '\r\n':
                    segment.append(seg)
        except:
            print(line)
            continue

    words_df = pd.DataFrame({'segment': segment})
    print(words_df)
    stopwords = pd.read_csv(stop_words, index_col=False, quoting=3, sep="\t", names=['stopword'], encoding='utf-8')
    # 安装关键字groupby分组统计词频,并按照计数降序排序
    words_stat = words_df.groupby(by=['segment'])['segment'].agg({"count": np.size})
    words_stat = words_stat.reset_index().sort_values(by=["count"], ascending=False)
    # 分组之后去掉停用词
    words_stat = words_stat[~words_stat.segment.isin(stopwords.stopword)]
    print(words_stat)
    return words_stat

这段代码完全引用了这位大神的代码https://github.com/sujeek/comment_bilibili,其中包含停用词的txt文件。希望大神多多包涵。

再利用pyecharts中Wordcloud库 

from pyecharts import WordCloud

wordcloud = WordCloud(width = 1300, height = 620)
wordcloud.add("", words_stat['segment'], words_stat["count"],word_size_range=[20,100])
wordcloud.render('nidaibalema.html')

五、输出结果

      使用pyecharts库输出的词云具有动态效果,非常赞。

     但是从图中也可以看出项“哈哈哈”和“哈哈哈哈”并没有归为统一的词。算法还有待改进,今后考虑出一篇专门的jieba学习帖。

     从图中可以得到,这集确实高能,awsl最近真的好火啊。。

你可能感兴趣的:(爬虫,pandas,lxml,BeautifulSoup)