在哔哩哔哩首页头部如下位置有一个 Gif,每次刷新都不同。
通过检查发现他是异步加载的。
访问 api 后得到一个 json 数据。
然后使用 Python 进行爬取。
1import requests
2from pymongo import MongoClient
3import os
4import time
5import random
6
7total = 0
8
9
10def main():
11    api = 'http://api.bilibili.com/x/web-interface/index/icon'
12    global total
13    r = requests.session()
14    headers = {
15        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'
16    }
17    db = MongoClient('127.0.0.1', 27017).gif
18    gif = db.gif
19    s = set()
20
21    try:
22        os.mkdir('gifs')
23    except:
24        pass
25
26    for i in range(10000):
27        c = r.get(api).json()
28        time.sleep(random.randint(10, 30) / 100)
29        if c['data']['id'] in s:
30            continue
31        else:
32            s.add(c['data']['id'])
33        dic = {
34            'url': 'https:' + c['data']['icon'],
35            'id': c['data']['id'],
36            'title': c['data']['title']
37        }
38        print('当前正在处理:', dic['id'], '\t', dic['title'])
39        gif.insert_one(dic)
40        with open('gifs/' + str(dic['id']) + '.' + dic['title'] + '.gif', 'wb+') as f:
41            content = r.get(dic['url'], headers=headers).content
42            f.write(content)
43            total = total + 1
44
45
46if __name__ == '__main__':
47    main()
48    print(total)
Copy
发起大量请求后发现,仅仅有 18 张是有效的,不重复。于是想可能是后端做了限制,缓存之内,防止在同一时间内造成过多插表命令,导致服务器压力过大。
透过前段时间泄露的 B 站后端源码分析,该 JSON 数据模型并没有发生改变。
再次查找发现 Dao 层存在 Redis 缓存,缓存了 icon 数据。
由此可以确定,重复的原因是因为 Redis 缓存,并且可以人为设置缓存内容,以便设置活动中的 Gif。在缓存过期时间内,无法通过此 api 获取其他 Gif。

亲亲留个评论再走呗

正在加载评论区...