前言
“酒香不怕巷子深“,这样的想法在这个时代已经算是非常地消极和落伍的一个思想了。
就像是一部电影,如战狼、哪吒这样,优秀的宣发能够带来远超电影本身质量的收益;而反过来,如闪光少女这样的电影,质量足以称为上乘,但是票房确差强人意,这就是典型的忽视了市场规则的下场。
访问量、点赞、收藏、投币等要素共同决定了一个视频的热度。但是,除了前者之外,都需要一个确切的 B 站账户,笔者目前还没有能力来维持一个基数庞大的 B 站账号池,所以就只能在第一个要素,点击量 上下文章咯。
正文
首先,先上一个 CSDN 的访问量爬虫。
import requests
headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36"}
url = "https://blog.csdn.net/Acher_zxj/article/details/104276531"
count = 0
while True:
res = requests.get(url,headers=headers)
print("now in loop {}".format(count))
访问量爬虫的工作原理非常地简单,就是单纯的向服务器发出一个请求,核心的行为与浏览器访问相类,每一次访问就算是一个点击量。
不过这里有一个问题,如何让远程服务器承认你的这次访问有效呢?
爬虫本身可以想象为<柯南>中那个小黑人,任谁(服务器)看到这幅打扮的人都会心神警惕吧。而 headers 的作用就是给这个小黑人”变装”,让它看上去更加地像一个”好人”。
这就是笔者上文所说的 与浏览器访问相类 ,具体的体现就是 headers 这一行。
这一行规定了爬虫的请求头,这是笔者从自己的浏览器中摘出来的浏览器请求头,声明了使用的是什么样的浏览器及其内核版本。
当然,get 还有proxies这样一个参数,这就相当于是直接给爬虫这个小黑人”换了一个身份”,对于这个有兴趣的可以参看构建 proxy pool 一文,这里就不多做赘述了。
之所以先上 CSDN 的访问量爬虫,是因为这个爬虫的实现机制简单,可以作为一个很好的引入案例。
那么,现在开始正餐~
关于 B 站视频的访问量爬虫,有两个很重要的问题需要我们解决。
- B 站的视频访问是需要登录的,不登录的访问似乎是不计数的(还是只记一次来着)?
- B 站视频并不是你进入页面时就算是一个访问的,而是你点击了这个视频,即开始观看之后,才算是一个视频访问量。
由于上述的两个问题,那么很显然我们无法像 CSDN 访问量爬虫 那样简单地实现了。
关于第一个问题,我们的解决方法很简单。
在浏览器中找到你的 cookie,然后将其添加到 headers 中即可。
在解决第二个问题的时候,笔者发现,网络上的主流方法是使用Selenium进行自动化的网页访问,模拟点击事件。
这种方法并无不可,但是 Selenium 自动化是真实地启动了 Chrome 内核的,也就是说,它的内存消耗相对很大,进而会拖慢计算机的执行效率,这一点我在以前写 Pixiv 图片爬虫的时候深有体会。
于是,我开始尝试寻找新的方法。2019 年下半年的网站开发工作,让我对API这个概念有了更深一层的体会,在每次点击开始播放之后,对应的 API 又是什么呢?
1. 开始分析网页的 API 结构
以【德拉科 Draco】个人向踩点混剪(一点都不骚)这个视频为例。
在点击开始之后,一瞬间跳出了一大片的网络请求信息。(难怪 Safari 总是提示 B 站耗能高 (笑))
2. 开始寻找”嫌疑人”
主要就是看交互的参数和响应。
既然要计算点击量,那么在请求中肯定包含了视频的 av 号和 cid这些特征信息吧,于是完成第一轮排查。
依然剩下很多,第二轮排查的主要着力点在 API 的名字,优秀的 API 的命名不可能是很随意的,这里我选择相信 B 站程序员的职业素养,于是我赌对了。在挑了两个之后,果然被我命中了。
可以看到,这个名字是 h5 的小家伙携带了很不得了的信息呢。
3. 测试 API
将表单的信息复制下来,我们使用 post 命令来模拟一下,看看是什么结果。
headers = {
'Host':'api.bilibili.com',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Accept-Encoding': 'gzip, deflate, br',
'Origin': 'https://www.bilibili.com',
'Connection': 'keep-alive',
'Referer': 'https://www.bilibili.com/video/av88113854',
'Cookie':"你的cookie"
}
data = {
'aid':'88113854',
'cid':'150536365',
'part':'1',
'mid':'your mid',
'lv':'5',
# 'ftime':'1581244587',
# 'stime':'1581419884',
'jsonp':'jsonp',
'type':'3',
'sub_type':'0'
}
req = requests.post('https://api.bilibili.com/x/click-interface/click/web/h5',data=data,headers=headers,proxies=proxy)
当然,不要忘记先”变装”,不然直接就可以进 Bad End 了。
说明:
ftime 和 stime 这两个参数一直在变动,但是熟悉 Linux 的小伙伴应该知道这是什么意思,所以笔者尝试将这两个参数去掉,果然,没有影响~~
mid 和 cookie 是根据每个人的账号信息生成的
在执行了一遍这个代码之后,发现视频的访问量 +1 ~
4. 完成爬虫
import requests
import time
headers = {
'Host':'api.bilibili.com',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Accept-Encoding': 'gzip, deflate, br',
'Origin': 'https://www.bilibili.com',
'Connection': 'keep-alive',
'Referer': 'https://www.bilibili.com/video/av88113854',
'Cookie':"你的cookie"
}
data_bk1 = {
'aid':'88113854',
'cid':'150536365',
'part':'1',
'mid':'your mid',
'lv':'5',
# 'ftime':'1581244587',
# 'stime':'1581419346',
'jsonp':'jsonp',
'type':'3',
'sub_type':'0'
}
count = 0
while True:
try:
req = requests.post('https://api.bilibili.com/x/click-interface/click/web/h5',data=data,headers=headers)
count += 1
print("now in loop {}".format(count))
print(req.text)
time.sleep(100)
except Exception as e:
print(proxy_raw)
print(e)
time.sleep(100)
print('over')
必要说明:
经过测试,在不更换 ip 和账号的情况下,B 站对每个 ip 的访问频率记数是 400s 左右,所以就以这个时间为睡眠间隔。
同时也是为了防止过度频繁的访问触发反爬虫机制,导致自己的 ip 被封,影响正常使用。
但是,可以同时刷多个视频的播放量
当然,如果使用代理的话,就可以放心大胆地浪了。