本次作业要求来自于:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/3159
爬虫综合大作业
- 选择一个热点或者你感兴趣的主题。
- 选择爬取的对象与范围。
- 了解爬取对象的限制与约束。
- 爬取相应内容。
- 做数据分析与文本分析。
- 形成一篇文章,有说明、技术要点、有数据、有数据分析图形化展示与说明、文本分析图形化展示与说明。
- 文章公开发布。
于2009年6月26日创建,被粉丝们亲切的称为“B站”的哔哩哔哩(bilibili),现在可以说是无人不晓。但你们是否知道哔哩哔哩这名称的来历。曾经的一部动画《某科学的超电磁炮》(疯狂安利),女主
名为御坂美琴,粉丝们中的姐姐大人,发动超能力放超电磁炮的时候,电流所发出的声音被调侃为“bilibili”,为了致敬这部动画,所以就有了现在的哔哩哔哩(B站的会员等级lv0 -> lv6也是对应动画中的等级)。所以便选了与这部动画有关的视频,爬取这个视频部分弹幕(全日站排行第1的视频,有着110万的弹幕总数)
通过检查元素-->netword,去寻找有关弹幕的链接,会发现到一个与众不同的东西,名为list.so?oid=XXX的目标。查看preview的内容,会发现这就是我们要找的弹幕资源。
B站视频弹幕文件都有相对应的cid
# 获取视频弹幕的cid def get_cid(url): response = requests.get(url, headers=headers) if response.status_code == 200: cid = json.loads(response.content.decode())["data"]["cid"] return cid
将弹幕内容保存到MySQL数据库中
# 将弹幕内容保存到MySQL数据库中 def save_to_sql(cid,barrage): conInfo = "mysql+pymysql://root:123456@localhost:3306/bilibili?charset=utf8" engine = create_engine(conInfo,encoding='utf-8') df = pd.DataFrame(barrage) df.to_sql(name=str(cid),con=engine,if_exists='append',index=False)
最后生成词云
# 生成词云 def make_wordCould(barrage): barrage = ''.join(barrage) ciyun = WordCloud(background_color='white',width=1000,height=600).generate(barrage) plt.imshow(ciyun) plt.axis('off') plt.show()
全部代码如下:
import requests import json import os from lxml import etree import pandas as pd from sqlalchemy import create_engine from wordcloud import WordCloud import matplotlib.pyplot as plt headers = { "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36", } # 获取视频番号 def get_url(): av = input("请输入想要爬取弹幕的B站视频av号(例如810872):") url = "https://api.bilibili.com/x/web-interface/view?aid={}".format(av) # url = "https://api.bilibili.com/x/player/pagelist?aid={}&jsonp=jsonp".format(av) return url # 获取视频弹幕的cid def get_cid(url): response = requests.get(url, headers=headers) if response.status_code == 200: cid = json.loads(response.content.decode())["data"]["cid"] return cid def get_title(url): response = requests.get(url, headers=headers) if response.status_code == 200: title = json.loads(response.content.decode())["data"]["title"] return title # 解析弹幕的xml,并把爬取的弹幕保存为本地txt文件 def get_barrage(cid): cid_url = "https://api.bilibili.com/x/v1/dm/list.so?oid={}".format(cid) # cid_url = "https://comment.bilibili.com/{}.xml".format(cid) result = requests.get(cid_url, headers=headers) comment_element = etree.HTML(result.content) barrage_list = comment_element.xpath("//d") txt = str(cid)+".txt" if os.path.exists(txt): os.remove(txt) with open(txt, 'w', encoding='utf-8') as file: for d in barrage_list: file.write(d.xpath('./text()')[0]) file.write(" ") # 打开弹幕文件内容 def get_text(cid): txt = str(cid) + ".txt" with open(txt, 'r', encoding='utf-8') as file: fp = file.read() barrage = fp.split(' ') return barrage # 将弹幕内容保存到MySQL数据库中 def save_to_sql(cid,barrage): conInfo = "mysql+pymysql://root:123456@localhost:3306/bilibili?charset=utf8" engine = create_engine(conInfo,encoding='utf-8') df = pd.DataFrame(barrage) df.to_sql(name=str(cid),con=engine,if_exists='append',index=False) # 统计弹幕出现次数,并保存为本地csv文件 def barrage_count(barrage,cid): barrage_dict = {} barrage_set = set(barrage) for br in barrage_set: barrage_dict[br] = barrage.count(br) barrage_sort = sorted(barrage_dict.items(),key=lambda x:x[1],reverse=True) for i in range(20): print(barrage_sort[i]) file_name = str(cid)+'.csv' pd.DataFrame(data=barrage_sort).to_csv(file_name,encoding='utf-8') # 生成词云 def make_wordCould(barrage): barrage = ''.join(barrage) ciyun = WordCloud(background_color='white',width=1000,height=600).generate(barrage) plt.imshow(ciyun) plt.axis('off') plt.show() if __name__ == '__main__': url = get_url() cid = get_cid(url) get_barrage(cid) barrage = get_text(cid) save_to_sql(cid,barrage) barrage_count(barrage,cid) make_wordCould(barrage)