本周我们的目标是:B站(哔哩哔哩弹幕网 https://www.bilibili.com )视频评论数据。

我们都知道,B站有很多号称“镇站之宝”的视频,拥有着数量极其恐怖的评论和弹幕。所以这次我们的目标就是,爬取B站视频的评论数据,分析其为何会深受大家喜爱。

首先去调研一下,B站评论数量最多的视频是哪一个。。。好在已经有大佬已经统计过了,我们来看一哈!

【B站大数据可视化】B站评论数最多的视频究竟是?来自 < https://www.bilibili.com/video/av34900167/>

嗯?《全职高手》,有点意思,第一集和最后一集分别占据了评论数量排行榜的第二名和第一名,远超了其他很多很火的番。那好,就拿它下手吧,看看它到底强在哪儿。

废话不多说,先去B站看看这部神剧到底有多好看 https://www.bilibili.com/bangumi/play/ep107656

额,需要开通大会员才能观看。。。

好吧,不看就不看,不过好在虽然视频看不了,评论却是可以看的。

感受到它的恐怖了吗?63w6条的评论!9千多页!果然是不同凡响啊。

接下来,我们就开始编写爬虫,爬取这些数据吧。


使用爬虫爬取网页一般分为四个阶段:分析目标网页,获取网页内容,提取关键信息,输出保存。

1. 分析目标网页

  • 首先观察评论区结构,发现评论区为鼠标点击翻页形式,共 9399 页,每一页有 20 条评论,每条评论中包含 用户名、评论内容、评论楼层、时间日期、点赞数等信息展示。

  • 接着我们按 F12 召唤出开发者工具,切换到Network。然后用鼠标点击评论翻页,观察这个过程有什么变化,并以此来制定我们的爬取策略。

  • 我们不难发现,整个过程中 URL 不变,说明评论区翻页不是通过 URL 控制。而在每翻一页的时候,网页会向服务器发出这样的请求(请看 Request URL)。

  • 点击 Preview 栏,可以切换到预览页面,也就是说,可以看到这个请求返回的结果是什么。下面是该请求返回的 json 文件,包含了在 replies 里包含了本页的评论数据。在这个 json 文件里,我们可以发现,这里面包含了太多的信息,除了网页上展示的信息,还有很多没展示出来的信息也有,简直是挖到宝了。不过,我们这里用不到,通通忽略掉,只挑我们关注的部分就好了。

2. 获取网页内容

网页内容分析完毕,可以正式写代码爬了。

import requestsdef fetchURL(url):'''功能:访问 url 的网页,获取网页内容并返回参数:url :目标网页的 url返回:目标网页的 html 内容'''headers = {'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8','user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',}try:r = requests.get(url,headers=headers)r.raise_for_status()print(r.url)return r.textexcept requests.HTTPError as e:print(e)print("HTTPError")except requests.RequestException as e:print(e)except:print("Unknown Error !")if __name__ == '__main__':url = 'https://api.bilibili.com/x/v2/reply?callback=jQuery172020326544171595695_1541502273311&jsonp=jsonp&pn=2&type=1&oid=11357166&sort=0&_=1541502312050'html = fetchURL(url)print(html)

不过,在运行过后,你会发现,403 错误,服务器拒绝了我们的访问。

运行结果:403 Client Error: Forbidden for url: https://api.bilibili.com/x/v2/reply?callback=jQuery172020326544171595695_1541502273311&jsonp=jsonp&pn=2&type=1&oid=11357166&sort=0&_=1541502312050
HTTPError
None

同样的,这个请求放浏览器地址栏里面直接打开,会变403,什么也访问不到。

这是我们本次爬虫遇到的第一个坑。在浏览器中能正常返回响应,但是直接打开请求链接时,却会被服务器拒绝。(我第一反应是 cookie ,将浏览器中的 cookie 放入爬虫的请求头中,重新访问,发现没用),或许这也算是一个小的反爬虫机制吧。

网上查阅资料之后,我找到了解决的方法(虽然不了解原理),原请求的 URL 参数如下:

callback = jQuery1720913511919053787_1541340948898
jsonp = jsonp
pn = 2
type = 1
oid = 11357166&sort=0
_ = 1541341035236

其中,真正有用的参数只有三个:pn(页数),type(=1)和oid(视频id)。删除其余不必要的参数之后,用新整理出的url去访问,成功获取到评论数据。

https://api.bilibili.com/x/v2/reply?type=1&oid=11357166&pn=2

然后,在主函数中,通过写一个 for 循环,通过改变 pn 的值,获取每一页的评论数据。

if __name__ == '__main__':for page in range(0,9400):url = 'https://api.bilibili.com/x/v2/reply?type=1&oid=11357166&pn=' + str(page)html = fetchURL(url)

3. 提取关键信息

通过 json 库对获取到的响应内容进行解析,然后提取我们需要的内容:楼层,用户名,性别,时间,评价,点赞数,回复数。

import json
import timedef parserHtml(html):'''功能:根据参数 html 给定的内存型 HTML 文件,尝试解析其结构,获取所需内容参数:html:类似文件的内存 HTML 文本对象'''s = json.loads(html)for i in range(20):comment = s['data']['replies'][i]# 楼层,用户名,性别,时间,评价,点赞数,回复数floor = comment['floor']username = comment['member']['uname']sex = comment['member']['sex']ctime = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(comment['ctime']))content = comment['content']['message']likes = comment['like']rcounts = comment['rcount']print('--'+str(floor) + ':' + username + '('+sex+')' + ':'+ctime)print(content)print('like : '+ str(likes) + '      ' + 'replies : ' + str(rcounts))print('  ')
部分运行结果如下:--204187:day可可铃(保密):2018-11-05 18:16:22
太太又出本了,这次真的木钱了(´;ω;`)
like : 1      replies : 0--204186:长夜未央233(女):2018-11-05 16:24:52
12区打卡
like : 2      replies : 0--204185:果然还是人渣一枚(男):2018-11-05 13:48:09
貌似忘来了好几天
like : 1      replies : 1--204183:day可可铃(保密):2018-11-05 13:12:38
要准备去学校了,万恶的期中考试( ´_ゝ`)
like : 2      replies : 0--204182:拾秋以叶(保密):2018-11-05 12:04:19
11月5日打卡( ̄▽ ̄)
like : 1      replies : 0--204181:芝米士哒(女):2018-11-05 07:53:43
这次是真的错过了一个亿[蛆音娘_扶额]
like : 2      replies : 1

4. 保存输出

我们把这些数据以 csv 的格式保存于本地,即完成了本次爬虫的全部任务。下面附上爬虫的全部代码。

import requests
import json
import timedef fetchURL(url):'''功能:访问 url 的网页,获取网页内容并返回参数:url :目标网页的 url返回:目标网页的 html 内容'''headers = {'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8','user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',}try:r = requests.get(url,headers=headers)r.raise_for_status()print(r.url)return r.textexcept requests.HTTPError as e:print(e)print("HTTPError")except requests.RequestException as e:print(e)except:print("Unknown Error !")def parserHtml(html):'''功能:根据参数 html 给定的内存型 HTML 文件,尝试解析其结构,获取所需内容参数:html:类似文件的内存 HTML 文本对象'''try:s = json.loads(html)except:print('error')commentlist = []hlist = []hlist.append("序号")hlist.append("名字")hlist.append("性别")hlist.append("时间")hlist.append("评论")hlist.append("点赞数")hlist.append("回复数")#commentlist.append(hlist)# 楼层,用户名,性别,时间,评价,点赞数,回复数for i in range(20):comment = s['data']['replies'][i]blist = []floor = comment['floor']username = comment['member']['uname']sex = comment['member']['sex']ctime = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(comment['ctime']))content = comment['content']['message']likes = comment['like']rcounts = comment['rcount']blist.append(floor)blist.append(username)blist.append(sex)blist.append(ctime)blist.append(content)blist.append(likes)blist.append(rcounts)commentlist.append(blist)writePage(commentlist)print('---'*20)def writePage(urating):'''Function : To write the content of html into a local filehtml : The response contentfilename : the local filename to be used stored the response'''import pandas as pddataframe = pd.DataFrame(urating)dataframe.to_csv('Bilibili_comment5-1000条.csv', mode='a', index=False, sep=',', header=False)if __name__ == '__main__':for page in range(0,9400):url = 'https://api.bilibili.com/x/v2/reply?type=1&oid=11357166&pn=' + str(page)html = fetchURL(url)parserHtml(html)# 为了降低被封ip的风险,每爬20页便歇5秒。if page%20 == 0:time.sleep(5)

写在最后

在爬取过程中,还是遇到了很多的小坑的。

1. 请求的 url 不能直接用,需要对参数进行筛选整理后才能访问。

2. 爬取过程其实并不顺利,因为如果爬取期间如果有用户发表评论,则请求返回的响应会为空导致程序出错。所以在实际爬取过程中,记录爬取的位置,以便出错之后从该位置继续爬。(并且,挑选深夜一两点这种发帖人数少的时间段,可以极大程度的减少程序出错的机率)

3. 爬取到的数据有多处不一致,其实这个不算是坑,不过这里还是讲一下,免得产生困惑。

a. 就是评论区楼层只到了20多万,但是评论数量却有63万多条,这个不一致主要是由于B站的评论是可以回复的,回复的评论也会计算到总评论数里。我们这里只爬楼层的评论,而评论的回复则忽略,只统计回复数即可。

b. 评论区楼层在20万条左右,但是我们最后爬取下来的数据只有18万条左右,反复检查爬虫程序及原网站后发现,这个属于正常现象,因为有删评论的情况,评论删除之后,后面的楼层并不会重新排序,而是就这样把删掉的那层空下了。导致楼层数和评论数不一致。

Python 网络爬虫实战:爬取 B站《全职高手》20万条评论数据相关推荐

  1. 爬取网易云音乐两万条评论储存在MySQL服务器上

    爬取网易云音乐两万条评论储存在MySQL服务器上 最近在公司实习,无聊时看看别人的博客,发现平时学习写写博客是一个很好的学习方法,报平时一些自己写的代码保存下来,遇到的错误踩到的坑也拿出来分享也可也帮 ...

  2. Python网络爬虫:爬取并下载个性化签名图片 附GUI窗体版

    Hello,大家好,我是wangzirui32,最近我开了个新的系列,是"Python网络爬虫"分类,还请大家多多支持! 今天,我们来学习如何爬取并下载个性化签名图片,开始学习吧! ...

  3. Python网络爬虫实战:《跨越星弧》TapTap玩家评论的抓取及分析

    先说说背景吧: 之前玩了一段时间的<跨越星弧>,后来太忙了就没玩了,最近突然想起来想看看,发现TapTap评分居然掉到7.7分了 其实我觉得这个产品挺好的,玩法.剧情.美术都有可圈可点之处 ...

  4. 【爬虫实战】10应用Python网络爬虫——定向爬取百度百科文字

    python百度百科爬虫 网页源代码分析 编程实现 小结 网页源代码分析 首先找一下需要爬取的正文: 对应的源代码有两个地方: 上图往后翻会发现省略号,所以下面这张图才是我们需要爬取的部分: 编程实现 ...

  5. Python网络爬虫之爬取微博热搜

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理. PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取 python免费学习资 ...

  6. Python网络爬虫:爬取CSDN热搜数据 并保存到本地文件中

    hello,大家好,我是wangzirui32,今天我们来学习如何爬取CSDN热搜数据,并保存到Excel表格中. 开始学习吧! 学习目录 1. 数据包抓取 2. 编写代码 1. 数据包抓取 打开CS ...

  7. CrawlScript语言轻松实现网络爬虫——轻松爬取整站信息

    CrawlScript语言在beta0.3版本中集成了整站爬虫的功能,只需要简单几句,就可以完成对整站的爬取. 首先下载CrawlScript beta 0.3: CrawlScript beta 0 ...

  8. Python网络爬虫:爬取豆瓣上《小王子》书评

    本文为南大<用Python玩转数据>学习笔记 用到的库或模块: 1.Requests第三方库 用于中小型网络爬虫的信息抓取. 基本方法: requests.get() 请求获取指定YRL位 ...

  9. Python网络爬虫5 - 爬取QQ空间相册

    自毕业后,就再也没有用过QQ,QQ空间里记录的是些并不精彩的青葱岁月,但好歹也是份回忆,近日想着学以致用,用Python把QQ空间相册的所有照片爬取下来,以作备份. 分析QQ空间 登录QQ空间 爬取第 ...

最新文章

  1. JavaMail API 概述
  2. 听说做前后端的都是这个体会? | 每日趣闻
  3. pytho作线性拟合、多项式拟合、对数拟合
  4. python 解析url上的xml_如何从python中的URL读取XML文件?
  5. 查询数据库中所有表的行数(sqlserver 2000)
  6. redis 安装错误 jemalloc.h: No such file or directory
  7. 研讨会 | 知识工程与问答技术研讨会 (KEQA2018)
  8. STM32----摸石头过河系列(四)
  9. 《Cisco安全防火墙服务模块(FWSM)解决方案》——2.7 软件架构
  10. oracle查看表空间的几个sql
  11. 爱普生xp245手动清零_仍在Windows XP上吗? 手动更新或感到烦恼
  12. 兄弟dcp9020cdn手册_兄弟Brother DCP-9020CDN 驱动
  13. Cadence Allegro 中skill应用教程:让代码替我们打工
  14. android极光富媒体推送,极光推送如何在android客户端接收富媒体
  15. Unity_回合制战斗系统_01
  16. bilibili外链链接到网页
  17. 199 c 通过函数名字符串调用函数
  18. 贝格尔编排法-java
  19. SQL Server数据库mdf文件中了勒索病毒BUNNY。扩展名变为BUNNY
  20. C语言程序设计——计算梯形面积

热门文章

  1. Linux 零拷贝技术
  2. 【微信小程序】用户隐私协议合规修改
  3. 沃谈小知识| 聊聊不明觉厉的“边缘计算”
  4. 怎么给视频配音?这些要点需注意,赶紧收藏
  5. 如何更改计算机上的网络设置路由器,宽带重新换路由器怎么设置【图】
  6. 微信小程序教程:注册微信小程序的操作步骤
  7. JavaScript--DOM案例(一)
  8. 算法基础课:第一讲——基础算法
  9. 姓“深知”,名“诸葛”,首个企业级深度学习公有云平台养成记
  10. Java 操作Excel POI