Reverse-b站刷播放

摘要

本文内容转自网络,个人学习记录使用,请勿传播

x站刷播放逆向

1.一个正常用户,如何实现给b站视频增加一次播放呢?

  • 点击播放按钮。

2.如何通过程序,自动给视频增加一个播放呢?

  • 用程序模拟点击播放按钮后,发起的请求即可。
  • 当我们点击播放按钮后,观察到抓包工具捕获到了大概十几条数据包,那是不是意味着程序需要模拟这十几个数据包的请求发送呢?
    • 不一定!
    • 但是,注意,点击了播放按钮后,当前b站这个视频页面(浏览器)其实是发执行了两步操作
      • 发起了点击播放按钮对应的请求(重点关注)
      • 发起了视频持续播放过程的请求 (暂时放一下)

3.如何可以仅仅将点击了播放按钮后对应的请求数据包获取呢?

  • 打开开发者工具里面的抓包工具
  • 刷新页面,抓包工具捕获到相关的数据包(意义不大)
  • 在抓包工具中,清空目前已有的数据包
  • 点击播放按钮,在抓包工具中,重新捕获到了一些数据包
    • 这些数据包一定是点击了播放按钮和视频持续播放对应所有的数据包(A1)
      • now
      • web?
      • h5
      • heartbeat
      • 54087….
      • Total…
  • 再次清空抓包工具中的数据包,然后,再次播放视频,单独捕获视频持续播放对应的数据包:(视频持续播放对应的数据包 A2)
    • heartbeat
    • web?
    • 54087
    • total
  • 结论:第一次点击播放按钮后,发起的数据包有哪些?
    • A1类型的数据包 - A2类型的数据包
      • now
      • h5
    • 单独第一次点击播放按钮后,发起的请求的数据包只有now和h5.
    • 因此,想给视频增加播放量,只需要让程序模拟now这个请求或者h5这个请求,或者同时模拟now和h5请求即可!!!

4.now数据包进行基本分析

  • 数据包重点关注哪些内容?

    • 请求参数

      • jsonp: jsonp,且请求参数是固定不变的,因此可以忽略。
    • 请求头信息

      • referer
      • user-agent
    • cookie

      • cookie的键值对比较多。

        • 思考:目前在抓包工具中now数据包中,看到的所有的cookie都是属于这个now数据包的吗?

          • 有可能不是!如何检测是不是呢?

          • 在开发者工具中,定位到application这个选项卡,点击cookies,然后将b站所有的cookie给清除。

          • 再次刷新页面(注意每次重新刷新请求,务必先清除cookie),点击播放按钮,找到now数据包的cookies,发现仅有8个键值对。

          • 1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            buvid3 = E0212A22-CE5F-2D4B-C5E6-F7570189BA3B43527infoc; 

            CURRENT_FNVAL = 4048;

            b_lsid = 8C2921A7_1800407860D;

            _uuid = 93101022D5-210AF-5738-D87C-8989EADA8C8E43604infoc;

            buvid4 = 470CA30A-8DF5-92FC-931E-28D9C5E012C789949-022012421-e1+nZA0uNaJdA3gSdXO4dw%3D%3D;

            buvid_fp = e201bfe1170d7011c37fc0c8c6e863e1;

            blackside_state = 0;

            sid = lbvltb0w
          • 验证这些cookie是否存在动态变化的键值对。

            • 重新刷新请求,再次捕获now数据包,提取cookie和上次的cookie最比对,通过比对发现,如下几个键值对是动态变化的

              • 1
                2
                3
                4
                5
                6
                7
                buvid3 = xxx

                b_lsid = 8C2921A7_1800407860D;

                _uuid = xxx

                sid = lbvltb0w

5.h5数据包进行基本分析

  • 数据包重点关注哪些内容?

    • 请求参数:

      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        aid: 339482092
        cid: 540871843
        bvid: BV17R4y1G7qt
        part: 1
        mid: 0
        lv: 0
        ftime: 1629287097 【动态变化】
        stime: 1649335326 【动态变化】
        jsonp: jsonp
        type: 3
        sub_type: 0
        from_spmid: 333.9299.0.0
        auto_continued_play: 0
        refer_url:
        bsource:
        spmid: 333.788.0.0
      • 验证下请求参数哪些是动态变化?

        • 1
          2
          ftime: 1629287097 【动态变化】
          stime: 1649335326 【动态变化】
    • 请求头

      • referer
      • user-agent
    • cookie:和now数据包的cookie形态是一致,只要now的cookie处理了,就可以直接作用在h5这个数据包中。

6.buvid3捕获

  • buvid3它是cookie中的一个动态变化的键值对。(首先考虑)

  • 指定数据包中携带的cookie获取途径有哪些? (首先考虑)

    • 其他请求发送后,响应数据中会存在动态变化的cookie值
    • 其他请求的响应头中
      • 如果某一个请求的响应头信息中存在set-cookie这个头信息(或者查看cookie现象卡中的response-cookies),则表示该请求发送后,会产生一个新的cookie值
    • js相关的算法动态生成 (最后考虑)
  • buvid3这个动态变化的cookie值到底是从哪里来的?

    • now数据包中已经有了buvid3这个值,因此buvid一定是在now前面的某个数据包的响应中、响应头中或者是js中生成的。

    • 发现,在当前视频播放页的数据包的响应头中存在buvid3这个值。

    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      import requests
      def get_buvid3():
      url = 'https://www.bilibili.com/video/BV17R4y1G7qt?spm_id_from=333.999.0.0'
      headers = {
      'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36'
      }
      response = requests.get(url=url,headers=headers)
      #将响应头中的cookie获取即可
      result = response.cookies.get_dict()
      return result['buvid3']
      buvid3_value = get_buvid3()
      print(buvid3_value)

7._uuid捕获

  • _uuid也是一个动态变化的cookie值,并且我们已经知道,cookie的生成方式有三种。

  • 分析:

    • 在抓包工具中,先定位到当前播放页对应的数据包,该数据包中只携带了buvid3这一个cookie,然后,逐个往下查看其他数据包的cookie,发现在一个web开头的数据包的cookie中携带了_uuid和b_lsid这两个动态变化的cookie,则uuid和b_lsid这两个cookie值,一定是在当前播放页的数据包和web开头数据包中间的数据包中产生的!
    • 在当前播放页的数据包和web开头数据包中间的数据包中的响应头和响应内容中,并没有发现uuid和b_lsid的值,因此断定,这两个cookie值一定通过js相关算法获取的!
    • 清空cookie,重新发起请求,全局搜索_uuid
  • 全局搜索_uuid

    • 全局搜索后,出现两个js数据包,其中存在uuid的生成算法。

    • 在log_reporter这个js数据包的4718行发现了可疑之处,通过打断点测试,证实了,此处就是用来生成uuid的值。

      • Js附加的知识点:

        • 三目运算符(实现条件判断,就和if-else功能一样):

          • 语法:条件语句 ? 语句1 : 语句2

            • 当条件语句成立,执行语句1,否则执行语句2

            • 1
              2
              3
              4
              5
              #类似python的下述语法
              if 条件语句:
              语句1
              else:
              语句2
      • 4718行打下的断点语句:

        • 1
          2
          3
              条件语句             语句1           语句2
          t && "null" !== t ? this._uuid = t : (this._uuid = Object(v.a)()
          #如果t为空,则条件语句不成立,则执行语句2,在语句2中就是将Object(v.a)()赋值给uuid,则Object(v.a)()就是用来生成uuid的值。
        • Object(v.a)()

          • Object(v.a)是一个函数名,在函数名后面加括号,就是函数调用。假设Object(v.a)表示xxx,则Object(v.a)()就表示xxx()形式的函数调用。
        • js改写:

        • 1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          a = function(e) {
          for (var t = "",
          n = 0; n < e; n++) t += o(16 * Math.random());
          return s(t, e)
          },
          s = function(e, t) {
          var n = "";
          if (e.length < t) for (var r = 0; r < t - e.length; r++) n += "0";
          return n + e
          },
          o = function(e) {
          return Math.ceil(e).toString(16).toUpperCase()
          }
          function get_uuid() {
          var e = a(8),
          t = a(4),
          n = a(4),
          r = a(4),
          o = a(12),
          i = (new Date).getTime();
          return e + "-" + t + "-" + n + "-" + r + "-" + o + s((i % 1e5).toString(), 5) + "infoc"
          }
        • python代码

        • 1
          2
          3
          4
          5
          6
          7
          def get_uuid():
          import execjs
          node = execjs.get()
          fp = open('uuid.js','r',encoding='utf-8')
          ctx = node.compile(fp.read())
          uuid = ctx.eval('get_uuid()')
          return uuid

8.b_lsid

  • 分析:

    • 在抓包工具中,先定位到当前播放页对应的数据包,该数据包中只携带了buvid3这一个cookie,然后,逐个往下查看其他数据包的cookie,发现在一个web开头的数据包的cookie中携带了_uuid和b_lsid这两个动态变化的cookie,则uuid和b_lsid这两个cookie值,一定是在当前播放页的数据包和web开头数据包中间的数据包中产生的!
    • 在当前播放页的数据包和web开头数据包中间的数据包中的响应头和响应内容中,并没有发现uuid和b_lsid的值,因此断定,这两个cookie值一定通过js相关算法获取的!
    • 清空cookie,重新发起请求,全局搜索b_lsid
  • 全局搜索b_lsid

    • 搜索到两个js的数据包,内部是含有b_lsid。

    • js前置知识点:在js中如何设置cookie

      • 在js中有一个内置函数叫做setCookie,通过这个函数就可以设置请求中的cookie。
      • setCookie参数:
        • 参数1:cookie的key (重点)
        • 参数2:cookie的value值 (重点)
        • 参数3:cookie的有效时长
        • 参数4:cookie在服务器中的存储路径
    • 在log-reporter.js数据包的865行发现了可以之处:

      • 1
        2
        c.a.setCookie("b_lsid", t, 0, "current-domain")
        #因此这个t的值就是b_lsid这个动态变化的cookie值!
      • 分析变量t到底是什么?

        • 1
          2
          3
          4
          5
          #发现了t的来源
          #下述代码就是在给e,t和t这几个变量赋值
          var e = this.splitDate()
          , t = Object(f.b)(e.millisecond)
          , t = "".concat(Object(f.c)(8), "_").concat(t);
        • 1
          2
          3
          4
          5
          6
          t = Object(f.b)(e.millisecond) #t的初始值。Object(f.b)是函数名,e.millisecond是函数的参数。xxx(参数)
          #将t的初始值进行了字符串的拼接
          #concat函数是用来拼接字符串的
          #将“”和Object(f.c)(8)返回的字符串使用_为间隔拼接到一起
          #将上述拼接的结果在和t拼接到一起
          t = "".concat(Object(f.c)(8), "_").concat(t)
      • js改写:

      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        function get_first_t(e) {
        return Math.ceil(e).toString(16).toUpperCase()
        }

        function a() {
        var e = 8;
        for (var t = "",
        n = 0; n < e; n++) t += o(16 * Math.random());
        return s(t, e)
        }

        o = function(e) {
        return Math.ceil(e).toString(16).toUpperCase()
        }

        s = function(e, t) {
        var n = "";
        if (e.length < t) for (var r = 0; r < t - e.length; r++) n += "0";
        return n + e
        }

        function get_final_t(e) {
        var t = get_first_t(e);
        result = a();
        return "".concat(result, "_").concat(t);
        }
      • python代码

      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        def get_b_lsid():
        import execjs
        import time
        e = str(int(time.time() * 1000))
        node = execjs.get()
        fp = open('b_lsid.js','r',encoding='utf-8')
        ctx = node.compile(fp.read())
        uuid = ctx.eval('get_final_t("%s")'%e)
        return uuid
        print(get_b_lsid())

9.sid捕获

  • 逐个数据包的查看,最终发现在v2这个数据包的响应头发现了sid的值。

  • 搜索的注意注意事项:

    • 如果你想要在url,请求参数或者是响应内容中搜索指定关键字
      • 使用点击数据包按下contrl+f进行搜索
    • 如果想要在js代码中定位指定关键字
      • 点击三个点,在search中搜索
  • 结论:

    • 在v2这个数据包的响应头中发现了sid的值,则我们只需要对v2数据包进行请求发送,则可以在其response中提取到sid的值即可!
  • 对v2数据包进行分析:

    • url:https://api.bilibili.com/x/player/v2?cid=160478265&aid=94009583&bvid=BV1UE411W7ZS
    • 请求方式:get
    • 请求参数:

      • cid
      • aid
      • buvid:可以从播放页的url中直接提取出来。表示的就是播放的视频的唯一标识。
    • 只需要将v2数据包中的cid,aid和buvid三个请求参数动态获取后,就可以完成对v2数据包的请求,请求结束后,就获取了sid这个动态变化的cookie。

9.1 处理各种id(cid,aid和buvid)

  • 请求参数的生成方式:

    • 可以会出现在其他请求的响应数据中(首先考虑)
    • js算法动态生成(其次考虑)
  • 处理cid:

    • 基于抓包工具进行contrl+f形式的全局搜索,会发现cid出现在了一个叫做【pagelist】数据包的响应数据中
    1
    2
    3
    4
    5
    6
    7
    8
    import requests
    headers = {
    'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36'
    }
    url = 'https://api.bilibili.com/x/player/pagelist?bvid=BV1UE411W7ZS&jsonp=jsonp'
    cid_ret_json = requests.get(url,headers=headers).json()
    cid = cid_ret_json['data'][0]['cid']
    print(cid)
  • 处理aid:

    • aid的机制更新了,在更新之前和cid的获取方式是一致的,反爬机制更新后,aid的获取机制就变化了。

    • 实现最新的aid获取的方式:

      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        #作业:要获取aid的值,和视频的播放量
        import requests
        import re
        headers = {
        'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36'
        }
        url = 'https://www.bilibili.com/video/BV1UE411W7ZS?spm_id_from=333.999.0.0'

        page_text = requests.get(url,headers=headers).text
        ret = re.search('"stat":\{"aid":(?P<aid>\d+),"view":(?P<view>\d+),"danmaku',page_text)
        #aid和播放量获取
        print(ret.group("aid"),ret.group("view"))
    • 本次课,我们先用一个固定接口获取aid的值:

    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      def get_ids(play_url):
      import requests
      headers = {
      'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36'
      }
      #获取cid
      url = 'https://api.bilibili.com/x/player/pagelist?bvid=BV1UE411W7ZS&jsonp=jsonp'
      cid_ret_json = requests.get(url,headers=headers).json()
      cid = cid_ret_json['data'][0]['cid']
      #获取bvid
      #播放页的url
      play_page_url = play_url
      bvid = play_page_url.split('/')[-1]

      #获取aid
      aid_url = "https://api.bilibili.com/x/web-interface/view?cid=%s&bvid=%s"%(cid, bvid)
      res = requests.get(aid_url,headers=headers)
      res_json = res.json()
      aid = res_json['data']['aid']
      #播放量
      view_count = res_json['data']['stat']['view']
      #视频总时长
      duration = res_json['data']['pages'][0]['duration'] # 当前视频长度

      return cid,aid,bvid,view_count,duration

      ret = get_ids('https://www.bilibili.com/video/BV1UE411W7ZS')
      print(ret)

v2数据包的完全模拟,获取sid

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import requests
import re
headers = {
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36'
}
def get_ids(play_url):
import requests
headers = {
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36'
}
#获取cid
url = 'https://api.bilibili.com/x/player/pagelist?bvid=BV1UE411W7ZS&jsonp=jsonp'
cid_ret_json = requests.get(url,headers=headers).json()
cid = cid_ret_json['data'][0]['cid']
#获取bvid
#播放页的url
play_page_url = play_url
bvid = play_page_url.split('/')[-1]

#获取aid
aid_url = "https://api.bilibili.com/x/web-interface/view?cid=%s&bvid=%s"%(cid, bvid)
res = requests.get(aid_url,headers=headers)
res_json = res.json()
aid = res_json['data']['aid']
#播放量
view_count = res_json['data']['stat']['view']
#视频总时长
duration = res_json['data']['pages'][0]['duration'] # 当前视频长度

return cid,aid,bvid,view_count,duration

def get_sid(play_url):
cid,aid,bvid,view, duration = get_ids(play_url)
headers = {
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36'
}
url = 'https://api.bilibili.com/x/player/v2'
params = {
'cid':cid,
'aid':aid,
'bvid':bvid
}
response = requests.get(url,params=params,headers=headers)
sid = response.cookies.get_dict()['sid']
return sid

sid = get_sid("https://www.bilibili.com/video/BV1UE411W7ZS")
print(sid)

注意:至此,now数据包的所有的cookie都已经处理完毕!

10.now请求的完全模拟

  • 重点,如何将之前获取的cookie全部整合或者说作用在now的请求中!

    • 最好选择使用session对象进行cookie的整合!
    • session对象本质作用:
      • 如果一个数据包的响应头中携带了一个set-cookie的头信息,则该数据包请求成功后,服务端会按照当前请求成功的数据包的要求给客户端返回一组指定的cookie值。
      • 如果使用session对象对携带set-cookie头信息的请求进行发送,则服务端产生的cookie也会存储到session对象中,下次使用session对象发起其他的请求,则其他请求就会携带上这个cookie值!
      • 如果可以将now数据包所有的cookie都存储到session对象中,则使用session对象直接发起请求,就可以完全模拟了now请求!
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    import requests
    #播放页的url(即将要刷播放的视频)
    play_url = '某视频播放页的url'
    headers = {
    'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36'
    }
    #创建了一个新的session对象,该对象中暂无保存任何cookie
    seesion = requests.Session()
    #1.整合buvid3到session对象中
    def get_buvid3(play_url):
    url = play_url
    seesion.get(url=url,headers=headers)
    get_buvid3(play_url)

    #2.整合uuid到session对象中
    def get_uuid():
    import execjs
    node = execjs.get()
    fp = open('uuid.js','r',encoding='utf-8')
    ctx = node.compile(fp.read())
    uuid = ctx.eval('get_uuid()')
    return uuid
    uuid = get_uuid()
    #手动将一组cookie存储到session对象
    seesion.cookies.set('_uuid',uuid)

    #3.b_lsid整合到session对象中
    def get_b_lsid():
    import execjs
    import time
    e = str(int(time.time() * 1000))
    node = execjs.get()
    fp = open('b_lsid.js','r',encoding='utf-8')
    ctx = node.compile(fp.read())
    lsid = ctx.eval('get_final_t("%s")'%e)
    return lsid
    lsid = get_b_lsid()
    seesion.cookies.set('b_lsid',lsid)

    #4.sid整合到session对象中
    def get_ids(play_url):
    # 获取bvid
    # 播放页的url
    play_page_url = play_url
    bvid = play_page_url.split('/')[-1]

    #获取cid
    url = 'https://api.bilibili.com/x/player/pagelist?bvid=%s&jsonp=jsonp'%bvid
    cid_ret_json = requests.get(url,headers=headers).json()
    cid = cid_ret_json['data'][0]['cid']


    #获取aid
    aid_url = "https://api.bilibili.com/x/web-interface/view?cid=%s&bvid=%s"%(cid, bvid)
    res = requests.get(aid_url,headers=headers)
    res_json = res.json()
    aid = res_json['data']['aid']
    #播放量
    view_count = res_json['data']['stat']['view']
    #视频总时长
    duration = res_json['data']['pages'][0]['duration'] # 当前视频长度

    return cid,aid,bvid,view_count,duration

    def get_sid(play_url):
    cid,aid,bvid,view, duration = get_ids(play_url)
    headers = {
    'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36'
    }
    url = 'https://api.bilibili.com/x/player/v2'
    params = {
    'cid':cid,
    'aid':aid,
    'bvid':bvid
    }
    seesion.get(url,params=params,headers=headers)
    get_sid(play_url)

    #剩下固定不变的cookie的整合
    seesion.cookies.set('CURRENT_FNVAL',"4048")
    seesion.cookies.set('buvid4','470CA30A-8DF5-92FC-931E-28D9C5E012C789949-022012421-e1+nZA0uNaJdA3gSdXO4dw%3D%3D')
    seesion.cookies.set('buvid_fp','e201bfe1170d7011c37fc0c8c6e863e1')
    seesion.cookies.set('blackside_state','0')
    #至此cookie的整合结束
    cid,aid,bvid,view_count,duration = get_ids(play_url)
    print('视频的原始播放:',view_count)
    now_url = 'https://api.bilibili.com/x/click-interface/click/now?jsonp=jsonp'
    ret = seesion.get(url=now_url,headers=headers).json()
    # print(ret)
    cid,aid,bvid,view_count,duration = get_ids(play_url)
    print('now请求后的播放:',view_count)
    • 发现对now进行了模拟后,播放量并没有涨,因此需要继续对h5进行模拟!

11.h5的请求模拟

  • h5数据包的cookie和now是一样的

  • h5数据包携带了请求参数:

    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      aid: 339482092  #已知
      cid: 540871843 #已知
      bvid: BV17R4y1G7qt #已知
      part: 1 #固定
      mid: 0 #固定
      lv: 0 #固定
      ftime: 1629287097 【动态变化】
      stime: 1649335326 【动态变化】
      jsonp: jsonp #固定
      type: 3 #固定
      sub_type: 0 #固定
      from_spmid: 333.9299.0.0 #固定
      auto_continued_play: 0 #固定
      refer_url: #固定
      bsource: #固定
      spmid: 333.788.0.0 #固定
    • 1
      2
      3
      4
      5
      6
      7
      8
      #两个参数的值就是时间戳
      ftime: 1629287097 【动态变化】
      stime: 1649335326 【动态变化】
      #stime > ftime

      #stime就是当前的时间戳
      #ftime第一次点击播放按钮对应的时间戳
      #核心:stime的值一定要大于ftime即可,大多少无所谓
    • h5进行请求模拟:完整代码

    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      104
      105
      106
      107
      108
      109
      110
      111
      112
      113
      import requests
      import time
      #播放页的url(即将要刷播放的视频)
      play_url = 'xxx某视频的播放页urlxxx'
      headers = {
      'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36'
      }
      #创建了一个新的session对象,该对象中暂无保存任何cookie
      seesion = requests.Session()
      #1.整合buvid3到session对象中
      def get_buvid3(play_url):
      url = play_url
      seesion.get(url=url,headers=headers)
      get_buvid3(play_url)

      #2.整合uuid到session对象中
      def get_uuid():
      import execjs
      node = execjs.get()
      fp = open('uuid.js','r',encoding='utf-8')
      ctx = node.compile(fp.read())
      uuid = ctx.eval('get_uuid()')
      return uuid
      uuid = get_uuid()
      #手动将一组cookie存储到session对象
      seesion.cookies.set('_uuid',uuid)

      #3.b_lsid整合到session对象中
      def get_b_lsid():
      import execjs
      import time
      e = str(int(time.time() * 1000))
      node = execjs.get()
      fp = open('b_lsid.js','r',encoding='utf-8')
      ctx = node.compile(fp.read())
      lsid = ctx.eval('get_final_t("%s")'%e)
      return lsid
      lsid = get_b_lsid()
      seesion.cookies.set('b_lsid',lsid)

      #4.sid整合到session对象中
      def get_ids(play_url):
      # 获取bvid
      # 播放页的url
      play_page_url = play_url
      bvid = play_page_url.split('/')[-1]

      #获取cid
      url = 'https://api.bilibili.com/x/player/pagelist?bvid=%s&jsonp=jsonp'%bvid
      cid_ret_json = requests.get(url,headers=headers).json()
      cid = cid_ret_json['data'][0]['cid']


      #获取aid
      aid_url = "https://api.bilibili.com/x/web-interface/view?cid=%s&bvid=%s"%(cid, bvid)
      res = requests.get(aid_url,headers=headers)
      res_json = res.json()
      aid = res_json['data']['aid']
      #播放量
      view_count = res_json['data']['stat']['view']
      #视频总时长
      duration = res_json['data']['pages'][0]['duration'] # 当前视频长度

      return cid,aid,bvid,view_count,duration

      def get_sid(play_url):
      cid,aid,bvid,view, duration = get_ids(play_url)
      headers = {
      'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36'
      }
      url = 'https://api.bilibili.com/x/player/v2'
      params = {
      'cid':cid,
      'aid':aid,
      'bvid':bvid
      }
      seesion.get(url,params=params,headers=headers)
      get_sid(play_url)

      #剩下固定不变的cookie的整合
      seesion.cookies.set('CURRENT_FNVAL',"4048")
      seesion.cookies.set('buvid4','470CA30A-8DF5-92FC-931E-28D9C5E012C789949-022012421-e1+nZA0uNaJdA3gSdXO4dw%3D%3D')
      seesion.cookies.set('buvid_fp','e201bfe1170d7011c37fc0c8c6e863e1')
      seesion.cookies.set('blackside_state','0')
      #至此cookie的整合结束
      import random
      cid,aid,bvid,view_count,duration = get_ids(play_url)
      print('视频的原始播放:',view_count)
      h5_url = 'https://api.bilibili.com/x/click-interface/click/web/h5'
      ctime = int(time.time())
      data = {
      "aid": aid,
      "cid": cid,
      "bvid": bvid,
      "part": "1",
      "mid": "0",
      "lv": "0",
      "ftime":str(ctime - random.randint(100,500)),
      "stime": str(ctime),
      "jsonp": "jsonp",
      "type": "3",
      "sub_type": "0",
      "from_spmid": "333.999.0.0",
      "auto_continued_play": "0",
      "refer_url":"" ,
      "bsource":"" ,
      "spmid": "333.788.0.0",
      }
      ret = seesion.post(h5_url,headers=headers,data=data).json()
      print(ret)

      cid,aid,bvid,view_count,duration = get_ids(play_url)
      print('h5请求后的播放:',view_count)

注意:

- 播放量无法不间断运行程序实现增长的,经过测试一个ip请求间隔在70-100秒之间,增加播放量是没问题的。
  • 如何解决呢?
    • 使用代理池!每次请求都使用不同的代理ip,则可以实现批量刷播放!

自己思考:

如何实现刷完播率。