上一篇传送门:初学Python爬虫:爬取B站某个详情页的所有标题
经过了一个星期的学习,本学渣又来啦。
这次的准备:
urllib、time、random、xlwt、gzip、io、json模块!
如果掌握好了前面的东西,似乎B站可以翻个底朝天了?
既然如此…让我来康♂康♂
咦?扒不出来?明明我是按照之前的方法来爬视频的啊?
urllib.error.HTTPError: HTTP Error 403: Forbidden
给了我这么一个错误,让我百度一下…找到了!
【爬虫 | 报错】urllib.error.HTTPError: HTTP Error 403: Forbidden
找视频可不是白找的,网站需要验证你是个人,不能非法访问!
如果有恶意爬虫爬过来,一下子几十万条数据扒下去,网站都要崩溃啦!
所以这就是所谓的反爬虫措施,目前通过查找资料,我明白了两个:
1、没有合适的契约(缺失用户信息),拒绝。
2、太贪吃(访问速度过快),拒绝。
第二点似乎说会所ip,因为后面加了应对措施,所以不太清楚,也不敢去试啊。
博主温馨提醒:爬虫千万个,安全第一个;爬取不规范,亲人两行泪。
解决第一个问题就是按链接中的方法,在F12开发者界面中,找到对应位置的信息,补充进去,我的是这样子的:
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}
req = urllib.request.Request(url=url0, headers=headers)
page=urllib.request.urlopen(req).read()
然后困扰很久的就是乱码问题了:你会发现,这样的确能把代码扒下来,但它是乱码状态,而且伴随编码越界的错误。起初我以为是解码问题,用的不是utf-8…
但不是的,查看网页编码方式的通用方法介绍了怎么查看。
哦,utf-8,没错…
终于找到了!
爬虫初学报错:UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0x8b in position 1: i
加入gzip将代码解压…
ok,你就得到了需要的代码。
那么上面第二点怎么办呢?引入休眠,据说加随机或许会好一点?
time.sleep(3 + random.random())
还有还有!一些视频被删除了,怎么办?
通过对网页代码的观察,会发现删掉的视频会出现error-body的字段,直接查找就可以辨别啦!
数据总算是扒下来了…什么?!硬币数和播放数呢?
这是json的魔法了。json可以用于展示变化的数据,在网页文件中是不储存的。
解铃还须系铃人,B站视频,上!
Python爬虫,网页抓json数据包详细教程,爬虫必备技能
成功了!运用json的loads()直接转成字典!
全代码如下:
import urllib.request
import time
import random
import xlwt
import gzip
from io import BytesIO
import json
#目标:爬取B站av1-1110视频时间、弹幕数、投币数,形成表格
#初始化并创建一个工作簿
book = xlwt.Workbook()
#创建一个名为sheetname的表单
sheet = book.add_sheet('结果')
str0 = 'l-con'
str1 = 'r-con'
strerr='error-body'
sheet.write(0,0,"视频时间")
sheet.write(0,1,"弹幕数")
sheet.write(0,2,"投币数")
#url0="https://www.bilibili.com/video/av1"
#headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}
#req = urllib.request.Request(url=url0, headers=headers)
#page=urllib.request.urlopen(req).read()
#time.sleep(3+random.random())
jjj = 1
for urlll in range(1,1111):
url0 = "https://www.bilibili.com/video/av" + str(urlll)
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}
req = urllib.request.Request(url=url0, headers=headers)
page=urllib.request.urlopen(req).read()
buff = BytesIO(page)
f = gzip.GzipFile(fileobj=buff)
getHtml = f.read().decode('utf-8')
time.sleep(3 + random.random())
if strerr in getHtml:
continue
content = getHtml.partition(str0)[2]
content = content.partition(str1)[0]
title_list = []
num1 = content.index('<time>', 0)+6
num2 = content.index('</time>', num1)
title_list.append(content[num1:num2])
#这里统计时间
url1="https://api.bilibili.com/x/web-interface/archive/stat?aid=" + str(urlll)
req1 = urllib.request.Request(url=url1, headers=headers)
page1 = urllib.request.urlopen(req1).read()
resu = json.loads(page1)
inresu=resu['data']
title_list.append(inresu['danmaku'])
#这里统计弹幕数
title_list.append(inresu['coin'])
#这里统计投币数
kkk = 0
for i in title_list:
sheet.write(jjj, kkk, i)
kkk = kkk + 1
jjj=jjj+1
#将工作簿以bookname命名并保存
book.save('wewantto2.xls')
注意,这个程序要跑很久,请自行修改for的range值…
现在的这个直接复制粘贴的话,要跑大约一个小时…吧?
得出结果如下:
时间上,前面1110个视频从2009-06-26 15:11:36到2012-10-15 23:57:11,横跨三年(当然你会发现前面的视频很多的时间是错乱的)
最高播放量292263(截止到爬取时间),其中播放量少于100的有275个,挖远古巨坟的人请加油!
而在投币量方面:
over,收工!