并不是完全破解,只是从100条结果到500条,分享思路供交流学习

b站查看其他用户的关注与粉丝时常常遇到这样一个页面,限制查看5页以后的数据,目的应该是为了保护用户的隐私数据

根据页面的显示结果,一页最多20条的结果,也就是最多只能看到100条结果

可以看下相关的关注api

https://api.bilibili.com/x/relation/followings?vmid=808171&pn=1&ps=20&order=desc&jsonp=jsonp&callback=__jp4

各个参数作用如下

GET
https://api.bilibili.com/x/relation/followings
vmid:用户ID
pn=1:  页码
ps=20:  单页结果(1~50)
order=desc:正序还是倒序/关注时间(desc/asc)

由于后端只对pn范围做了限制

因此我们使用ps单页50个结果就使得结果范围扩大到250条

配合asc,正序+倒序最多可以看到500条查询结果,更可以直接查询任意用户的早期关注

示例:

请求

GET https://api.bilibili.com/x/relation/followings?vmid=808171&pn=1&ps=2&order=asc HTTP/1.1
content-type: application/json

返回

HTTP/1.1 200 OK
Date: Wed, 19 Aug 2020 07:08:22 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 895
Connection: close
Bili-Status-Code: 0
Bili-Trace-Id: 306d2cfe3b5f3cd0
Expires: Wed, 19 Aug 2020 07:08:21 GMT
Cache-Control: no-cache
X-Cache-Webcdn: BYPASS from zl-hk-w-01

{
  "code": 0,
  "message": "0",
  "ttl": 1,
  "data": {
    "list": [
      {
        "mid": 70093,
        "attribute": 0,
        "mtime": 1360755003,
        "tag": null,
        "special": 0,
        "uname": "12dora",
        "face": "http://i0.hdslb.com/bfs/face/94c77e24253ae4be2e521d7113583068808e696b.png",
        "sign": "weibo@12dora",
        "official_verify": {
          "type": 0,
          "desc": ""
        },
        "vip": {
          "vipType": 2,
          "vipDueDate": 1621094400000,
          "dueRemark": "",
          "accessStatus": 0,
          "vipStatus": 1,
          "vipStatusWarn": "",
          "themeType": 0,
          "label": {
            "path": ""
          }
        }
      },
      {
        "mid": 258063,
        "attribute": 0,
        "mtime": 1367807564,
        "tag": null,
        "special": 0,
        "uname": "白金丶",
        "face": "http://i1.hdslb.com/bfs/face/fceedb9659abf149bf452937cf52224e41ffcb94.jpg",
        "sign": "关注我的微博吧w\n微博http://weibo.com/tongchang0820\n",
        "official_verify": {
          "type": -1,
          "desc": ""
        },
        "vip": {
          "vipType": 2,
          "vipDueDate": 1628006400000,
          "dueRemark": "",
          "accessStatus": 0,
          "vipStatus": 1,
          "vipStatusWarn": "",
          "themeType": 0,
          "label": {
            "path": ""
          }
        }
      }
    ],
    "re_version": 3219718925,
    "total": 198
  }
}

粉丝api

https://api.bilibili.com/x/relation/followers?vmid=808171&pn=1&ps=20&order=desc&jsonp=jsonp&callback=__jp12

followings接口变成followers接口,并且order字段无效

附上利用脚本

import time
import requests
import json,re

#url = "https://api.bilibili.com/x/relation/followings"
url = "https://api.bilibili.com/x/relation/followers"
headers = {
    'user-agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10; rv:33.0) Gecko/20100101 Firefox/33.0",
    'content-type': "application/json"
    }
uid=
userlist=[]

total=0
for order in ['asc','desc']:
    for i in range(1,6):
        querystring = {"vmid":uid,"pn":i,"ps":50,"order":order}
        response = requests.request("GET", url, headers=headers, params=querystring)
        res=json.loads(response.text)
        if('data' in res):
            print('[%d]%s:'%(i,order)+str(len(res['data']['list'])))
            for i in res['data']['list']:
                if i not in userlist:
                    userlist.append(i)
            total=res['data']['total']
#二次去重
def dedup(_list):
    _temp=[]
    for i in _list:
        if i not in _temp: _temp.append(i)
    return _temp

#排序
#print(userlist)
userlist=sorted(userlist,key=lambda e:e['mid'])
userlist=dedup(userlist)
userlist=sorted(userlist,key=lambda e:e['mtime'])
#输出
#中文格式化函数
def my_align(_string, _length, _type='L'):
    """
    中英文混合字符串对齐函数
    my_align(_string, _length[, _type]) -> str
    :param _string:[str]需要对齐的字符串
    :param _length:[int]对齐长度
    :param _type:[str]对齐方式('L':默认,左对齐;'R':右对齐;'C'或其他:居中对齐)
    :return:[str]输出_string的对齐结果
    """
    _str_len = len(_string)  # 原始字符串长度(汉字算1个长度)
    for _char in _string:  # 判断字符串内汉字的数量,有一个汉字增加一个长度
        if u'\u3000' <= _char <= u'\u9fa5' or u'\u3040' <= _char <= u'\u30FF':  # 判断一个字是否为汉字(这句网上也有说是“ <= u'\u9ffff' ”的)
            _str_len += 1
        
    _space = _length-_str_len  # 计算需要填充的空格数
    if _type == 'L':  # 根据对齐方式分配空格
        _left = 0
        _right = _space
    elif _type == 'R':
        _left = _space
        _right = 0
    else:
        _left = _space//2
        _right = _space-_left
    return ' '*_left + _string + ' '*_right

for user in userlist:
    print('UID:%9d 昵称:%s 关注时间:%s 用户状态:%s'
    %(user['mid'],
      my_align(user['uname'],20),
      time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(user['mtime'])),
      ('大会员' if user['vip']['vipType']>=2 else '普通用户'))
    )
print("共获取到%d/%d个%s的关注"%(len(userlist),total,str(uid)))