用Python实现一个面向主题的网络爬虫程序,并完成以下内容:
(注:每人一题,主题内容自选,所有设计内容与源代码需提交到博客园平台)
一、主题式网络爬虫设计方案(15分)
1.主题式网络爬虫名称
名称:爬取视频网站中的视频属性评分等信息
2.主题式网络爬虫爬取的内容与数据特征分析
本次爬虫主要爬取哔哩哔哩视频(Bilibili)网站中的视频属性评分等信息
3.主题式网络爬虫设计方案概述(包括实现思路与技术难点)
本次设计方案主要依靠request库对目标页面进行信息的爬取采集,再用matplotlib.pyplot对数据进行清洗,最后将结果打印出来。
技术难点主要包括获取数据的接口、对数据的清洗以及对打印结果的排版。
二、主题页面的结构特征分析(15分)
1.主题页面的结构特征
B站采用Jquery技术对相关标签进行绑定,视频属性信息的显示采用Ajax访问restful-API接口的方式,动态渲染显示,故采用常规的查看网页源代码的方式无法直接获取到所需要的数据。
2.restful-API接口分析
通过在浏览器中用鼠标右键点击查看“查看元素”选项或者按“F12”打开网页源代码。
在DevTool中切换到Network下,我们可以看到当前页面加载的所有文件和数据流。
通过分析相应标签的绑定事件和数据流中的XHR访问(Ajax访问接口)我们可以得到其接口:https://api.bilibili.com/x/web-interface/archive/stat?aid=X
接口返回Json结构体的数据。
至此,我们可以用requests.get(url) 命令向服务器提交请求,然后将响应的数据存储到sqlite3数据库中。
三、网络爬虫程序设计(60分)
爬虫程序主体要包括以下各部分,要附源代码及较详细注释,并在每部分程序后面提供输出结果的截图。
import requests import time import sqlite3 import threading from concurrent import futures headers = { \'X-Requested-With\': \'XMLHttpRequest\', \'User-Agent\': \'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36\' \'(KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36\' } total = 1 result = [] lock = threading.Lock() flag = None conn = None def create(): # 创建数据库 global conn conn = sqlite3.connect(\'data.db\') conn.execute("""create table if not exists data (id int prinmary key autocrement, aid int, view int, danmaku int, reply int, favorite int, coin int, share int)""") conn.execute("""insert into data (id,aid,view,danmaku,reply,favorite,coin,share) values(0,0,0,0,0,0,0,0)""") def save(): # 将数据保存至本地 global result, conn, flag, total command = "insert into data \ values(?,?,?,?,?,?,?,?);" for row in result: try: conn.execute(command, row) except: conn.rollback() flag = "error has occurred when total is "+str(total) print(flag) pass conn.commit() result = [] def run(url): global total req = requests.get(url, headers=headers, timeout=6).json() time.sleep(0.4) try: data = req[\'data\'] video = ( total, data[\'aid\'], # 视频编号 data[\'view\'], # 播放量 data[\'danmaku\'], # 弹幕数 data[\'reply\'], # 评论数 data[\'favorite\'], # 收藏数 data[\'coin\'], # 硬币数 data[\'share\'] # 分享数 ) with lock: result.append(video) if total % 250 == 0: global time0 time1 = time.time() print("爬取{0}个网页,花费时间:{1:.2f}s".format( total, time1-time0)) total += 1 except: pass if __name__ == "__main__": create() time0 = time.time() for i in range(0, 1981): begin = 10000*i print(begin) urls = ["http://api.bilibili.com/archive_stat/stat?aid={}".format(j) for j in range(begin, begin+10000)] with futures.ThreadPoolExecutor(32) as executor: executor.map(run, urls) save() if flag != None: print(flag) conn.close()
运行结果:
1.数据爬取与采集
使用request库进行爬取数据
def run(url): global total req = requests.get(url, headers=headers, timeout=6).json() time.sleep(0.4) try: data = req[\'data\'] video = ( total, data[\'aid\'], # 视频编号 data[\'view\'], # 播放量 data[\'danmaku\'], # 弹幕数 data[\'reply\'], # 评论数 data[\'favorite\'], # 收藏数 data[\'coin\'], # 硬币数 data[\'share\'] # 分享数 ) with lock: result.append(video) if total % 250 == 0: global time0 time1 = time.time() print("爬取{0}个网页,花费时间:{1:.2f}s".format( total, time1-time0)) total += 1 except: Pass
2.数据清洗分析与可视化
(例如:数据柱形图、直方图、散点图、盒图、分布图、数据回归分析等)
import matplotlib.pyplot as plt import sqlite3 conn=sqlite3.connect(r"C:\Users\peter\Desktop\bilibili\bilibili-spider\data.db") favorite=conn.execute("select favorite from data order by id;").fetchall() coin=conn.execute("select coin from data order by id;").fetchall() plt.title("收藏数与硬币数关系图",fontproperties=\'SimHei\',fontsize=25) plt.xlabel("收藏数",fontproperties=\'SimHei\',fontsize=15) plt.ylabel("硬币数",fontproperties=\'SimHei\',fontsize=15) plt.plot(favorite,coin,\'o\') conn.close()
【收藏数与硬币数关系 散点图】
import matplotlib.pyplot as plt import sqlite3 conn=sqlite3.connect(r"C:\Users\peter\Desktop\bilibili\bilibili-spider\data.db") aid=conn.execute("select aid from data order by id;").fetchall() view=conn.execute("select view from data order by id;").fetchall() danmakeu=conn.execute("select danmaku from data order by id;").fetchall() reply=conn.execute("select reply from data order by id;").fetchall() plt.title("aid号与播放量关系图",fontproperties=\'SimHei\',fontsize=25) plt.xlabel("aid号",fontproperties=\'SimHei\',fontsize=15) plt.ylabel("播放量",fontproperties=\'SimHei\',fontsize=15) plt.plot(aid,view) conn.close()
【aid与播放量的分析 柱状图】
3.数据持久化
def create(): # 创建数据库 global conn conn = sqlite3.connect(\'data.db\') conn.execute("""create table if not exists data (id int prinmary key autocrement, aid int, view int, danmaku int, reply int, favorite int, coin int, share int)""") conn.execute("""insert into data (id,aid,view,danmaku,reply,favorite,coin,share) values(0,0,0,0,0,0,0,0)""") def save(): # 将数据保存至本地 global result, conn, flag, total command = "insert into data \ values(?,?,?,?,?,?,?,?);" for row in result: try: conn.execute(command, row) except: conn.rollback() flag = "error has occurred when total is "+str(total) print(flag) pass conn.commit() result = []
四、结论(10分)
1.经过对主题数据的分析与可视化,可以得到哪些结论?
通过对主题数据的分析与可视化,可以得到视频评分属性信息,更好的对相关信息进行数据挖掘和分析。
2.对本次程序设计任务完成的情况做一个简单的小结。
通过这次任务,基本实现把想要的数据爬取下来,以及对其进行数据清洗及分析,并生成散点图、柱状图等,更直观的体现了数据价值。
同时,这次实验同样存在不足之处,爬取下来的数据效率还有待提高,应该尽可能的使用多线程操作,但也要注意网站对于爬虫的防御和限制。