爬取哔哩哔哩首页头部 Gif 图

2019 年 8 月 20 日 星期二(已编辑)
951
AI 生成的摘要
文章讲述了在哔哩哔哩首页头部显示的 Gif 是异步加载的,通过访问 API 得到 JSON 数据后,使用 Python 进行爬取。结果发现只有 18 张有效且不重复的 Gif。作者推测可能是为了避免在同一时间内过多插表命令导致服务器压力过大,从而做了后端限制。分析 B 站泄露的后端源码后发现,该 JSON 数据模型没有改变,并且 Dao 层存在 Redis 缓存,缓存了 icon 数据。这意味着重复 Gif 是由于 Redis 缓存引起的,并且可以人为设置缓存内容。在缓存过期时间内,无法通过 API 获取其他 Gif。
这篇文章上次修改于 2020 年 11 月 14 日 星期六,可能部分内容已经不适用,如有疑问可询问作者。

爬取哔哩哔哩首页头部 Gif 图

在哔哩哔哩首页头部如下位置有一个 Gif,每次刷新都不同。

通过检查发现他是异步加载的。

访问 api 后得到一个 json 数据。

然后使用 Python 进行爬取。

import requests
from pymongo import MongoClient
import os
import time
import random

total = 0


def main():
    api = 'http://api.bilibili.com/x/web-interface/index/icon'
    global total
    r = requests.session()
    headers = {
        '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'
    }
    db = MongoClient('127.0.0.1', 27017).gif
    gif = db.gif
    s = set()

    try:
        os.mkdir('gifs')
    except:
        pass

    for i in range(10000):
        c = r.get(api).json()
        time.sleep(random.randint(10, 30) / 100)
        if c['data']['id'] in s:
            continue
        else:
            s.add(c['data']['id'])
        dic = {
            'url': 'https:' + c['data']['icon'],
            'id': c['data']['id'],
            'title': c['data']['title']
        }
        print('当前正在处理:', dic['id'], '\t', dic['title'])
        gif.insert_one(dic)
        with open('gifs/' + str(dic['id']) + '.' + dic['title'] + '.gif', 'wb+') as f:
            content = r.get(dic['url'], headers=headers).content
            f.write(content)
            total = total + 1


if __name__ == '__main__':
    main()
    print(total)

发起大量请求后发现,仅仅有 18 张是有效的,不重复。于是想可能是后端做了限制,缓存之内,防止在同一时间内造成过多插表命令,导致服务器压力过大。

透过前段时间泄露的 B 站后端源码分析,该 JSON 数据模型并没有发生改变。

再次查找发现 Dao 层存在 Redis 缓存,缓存了 icon 数据。

由此可以确定,重复的原因是因为 Redis 缓存,并且可以人为设置缓存内容,以便设置活动中的 Gif。在缓存过期时间内,无法通过此 api 获取其他 Gif。

  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • 爬取哔哩哔哩首页头部 Gif 图 - 静かな森