网站域名如何影响seo,手机网站开发注意的问题,如何提供网站建设公司,平顶山建设网站猜测、实现 B 站在看人数 猜测找到接口参数总结 实现 猜测 
找到接口 
浏览器打开一个 B 站视频#xff0c;比如 《黑神话#xff1a;悟空》最终预告 | 8月20日#xff0c;重走西游_黑神话悟空 (bilibili.com) #xff0c;打开 F12 开发者工具#xff0c;经过观察#xf… 猜测、实现 B 站在看人数 猜测找到接口参数总结 实现  猜测 
找到接口 
浏览器打开一个 B 站视频比如 《黑神话悟空》最终预告 | 8月20日重走西游_黑神话悟空 (bilibili.com) 打开 F12 开发者工具经过观察发现每 30 秒就会有一个如下的请求 
https://api.bilibili.com/x/player/online/total?aid1056417986cid1641689875bvidBV1oH4y1c7Kkts57523354{code: 0,message: 0,ttl: 1,data: {total: 239,count: 182,show_switch: {total: true,count: true},abtest: {group: b}}
}返回值中的 data.total 就是在看人数如下 参数 
请求有 4 个参数 
aid1056417986
cid1641689875
bvidBV1oH4y1c7Kk
ts57523354aid、bvid 是稿件的编号cid 是视频的编号一个稿件可能有多个视频。通过三者可定位到唯一的视频。 
ts 从命名上来看应该是时间戳比如 57523353、57523354 但显然太短了应该是经过处理的最后发现是时间戳秒除以 30 向上取整的结果 
calcTs  function(date) {// 时间戳秒const timestamp_second  date.getTime() / 1000;// 除以 30 向上取整const ts  Math.ceil(timestamp_second / 30);console.log(ts)return ts;
}下图是两个请求的参数以及请求的时间 在浏览器控制台验证猜想通过 calcTs 函数可计算出 ts与请求参数完全吻合 总结 
B 站的实现思路应该是aid、bvid、cid 作为唯一编号以 30 秒为一个时间窗口进行统计在这 30s 中的请求都会使窗口值加 1每次累加完后返回最新值即可。 
但同时还发现在多个标签页中打开同一个视频时比如 5 个标签页一开始在看人数都是 1等一会在看人数才会陆续变成 5。也就是说返回的不是最新值因为如果返回最新值的话5 个标签页的在看人数应该分别是 1 2 3 4 5。 
猜测应该是同时存在两个 30 秒时间窗口这里称为当前窗口 currentWindow 也就是 ts 对应的 30s 窗口 和上一个窗口previousWindow 即 ts - 1 对应的 30s 窗口每次都累加到 currentWindow但返回 previousWindow。 
这样就能解释为什么一开始在看人数都是 1等一会在看人数才会陆续变成 5 了。打开视频时previousWindow 不存在所以返回了 1同时创建 currentWindow 并从 1 累加到 5。这样等 30s 后下一个定时任务时currentWindow 就变成了 previousWindow5 个标签页都会返回 5在看人数就都陆续变成 5 了。 
实现 
后端可以使用 Redis 实现最简单的办法是使用 string 结构以 aid、bvid、cid、ts 作为 key给 key 设置大于 60s 的过期时间每次请求时使用 incr 自增即可。但这样会导致 Redis 找那个有大量的 key不好维护。 
可以使用 hash 结构以 ts 为 key以 aid、bvid、cid 为 field窗口值为 value。这样 Redis 中只会有 ts、ts - 1 两个 key。如果必要的话也可以根据 field 的值将其 hash 分区到 2 * N 个 key 中。 
TotalService 
package com.example.demo3;import lombok.SneakyThrows;
import org.redisson.api.*;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;import java.time.Duration;
import java.util.concurrent.ExecutionException;Service
public class TotalService {private final RedissonClient redisson;public TotalService(RedissonClient redisson) {this.redisson  redisson;}SneakyThrows({ExecutionException.class, InterruptedException.class})GetMappingpublic Integer total(String aid, String bvid, String cid, Long ts) {RBatch batch  redisson.createBatch(BatchOptions.defaults());// currentWindow// 以时间戳作为 keyRMapAsyncString, Integer currentWindow  batch.getMap(ts.toString());// 以 aid, bvid, cid 作为 currentWindow 的 keyString field  field(aid, bvid, cid);// 自增  1currentWindow.addAndGetAsync(field, 1);// 过期时间必须大于 60scurrentWindow.expireIfNotSetAsync(Duration.ofSeconds(70));// previousWindowRMapAsyncString, Integer previousWindow  batch.getMap(String.valueOf(ts - 1));RFutureInteger totalFuture  previousWindow.getAsync(field);batch.execute();Integer total  totalFuture.get();// 如果 previousWindow 不存在则返回 1if (total  null || total  0) {return 1;}return total;}private String field(String aid, String bvid, String cid) {return aid  :  bvid  :  cid;}
} 
TotalController 
RestController
RequestMapping(/x/player/online/total)
public class TotalController {private final TotalService totalService;public TotalController(TotalService totalService) {this.totalService  totalService;}CrossOrigin(originPatterns  *)GetMappingpublic Integer total(RequestParam(aid) String aid, RequestParam(bvid) String bvid,RequestParam(cid) String cid, RequestParam(ts) Long ts) {return totalService.total(aid, bvid, cid, ts);}
}test.html 
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
body
divdivaid input idaid typetext value113071355923972bvid input idbvid typetext valueBV1giHnexEiDcid input idcid typetext value25714427593/divdiv在看span idtotal0/span/div
/div
/body
script typetext/javascriptconst elem_aid  document.getElementById(aid);const elem_bvid_elem  document.getElementById(bvid);const elem_cid_elem  document.getElementById(cid);const elem_total  document.getElementById(total);refreshTotal().then(()  {// 30 秒执行一次setInterval(function () {refreshTotal();}, 30000)});async function refreshTotal() {const aid  elem_aid.value;const bvid  elem_bvid_elem.value;const cid  elem_cid_elem.value;const ts  calcTs(new Date());const url  http://localhost:8080/x/player/online/total?aid${aid}cid${cid}bvid${bvid}ts${ts};const response  await fetch(url);const total  await response.json();console.log(total);elem_total.innerHTML  total;}function calcTs(date) {// 时间戳秒const timestamp_second  date.getTime() / 1000;// 除以 30 向上取整const ts  Math.ceil(timestamp_second / 30);console.log(ts)return ts;}
/script
/html
 文章转载自: http://www.morning.prls.cn.gov.cn.prls.cn http://www.morning.ktbjk.cn.gov.cn.ktbjk.cn http://www.morning.zlchy.cn.gov.cn.zlchy.cn http://www.morning.hffjj.cn.gov.cn.hffjj.cn http://www.morning.llllcc.com.gov.cn.llllcc.com http://www.morning.hhrpy.cn.gov.cn.hhrpy.cn http://www.morning.tnhqr.cn.gov.cn.tnhqr.cn http://www.morning.ljbpk.cn.gov.cn.ljbpk.cn http://www.morning.jmmzt.cn.gov.cn.jmmzt.cn http://www.morning.mjtft.cn.gov.cn.mjtft.cn http://www.morning.ljcf.cn.gov.cn.ljcf.cn http://www.morning.qwyms.cn.gov.cn.qwyms.cn http://www.morning.rcyrm.cn.gov.cn.rcyrm.cn http://www.morning.xltwg.cn.gov.cn.xltwg.cn http://www.morning.rqknq.cn.gov.cn.rqknq.cn http://www.morning.xhpnp.cn.gov.cn.xhpnp.cn http://www.morning.mrcpy.cn.gov.cn.mrcpy.cn http://www.morning.mmhyx.cn.gov.cn.mmhyx.cn http://www.morning.xltdh.cn.gov.cn.xltdh.cn http://www.morning.rggky.cn.gov.cn.rggky.cn http://www.morning.xqjh.cn.gov.cn.xqjh.cn http://www.morning.cfhwn.cn.gov.cn.cfhwn.cn http://www.morning.zfcfx.cn.gov.cn.zfcfx.cn http://www.morning.jrhcp.cn.gov.cn.jrhcp.cn http://www.morning.khdw.cn.gov.cn.khdw.cn http://www.morning.rydhq.cn.gov.cn.rydhq.cn http://www.morning.kpwcx.cn.gov.cn.kpwcx.cn http://www.morning.hxpsp.cn.gov.cn.hxpsp.cn http://www.morning.xdlwm.cn.gov.cn.xdlwm.cn http://www.morning.gctgc.cn.gov.cn.gctgc.cn http://www.morning.kehejia.com.gov.cn.kehejia.com http://www.morning.tzcr.cn.gov.cn.tzcr.cn http://www.morning.trnl.cn.gov.cn.trnl.cn http://www.morning.zpkfb.cn.gov.cn.zpkfb.cn http://www.morning.lhygbh.com.gov.cn.lhygbh.com http://www.morning.lmmkf.cn.gov.cn.lmmkf.cn http://www.morning.pdkht.cn.gov.cn.pdkht.cn http://www.morning.gxtfk.cn.gov.cn.gxtfk.cn http://www.morning.nbsfb.cn.gov.cn.nbsfb.cn http://www.morning.fslxc.cn.gov.cn.fslxc.cn http://www.morning.ysgnb.cn.gov.cn.ysgnb.cn http://www.morning.zpqbh.cn.gov.cn.zpqbh.cn http://www.morning.zfxrx.cn.gov.cn.zfxrx.cn http://www.morning.hjsrl.cn.gov.cn.hjsrl.cn http://www.morning.pqryw.cn.gov.cn.pqryw.cn http://www.morning.npfrj.cn.gov.cn.npfrj.cn http://www.morning.qmzwl.cn.gov.cn.qmzwl.cn http://www.morning.nfccq.cn.gov.cn.nfccq.cn http://www.morning.drnfc.cn.gov.cn.drnfc.cn http://www.morning.ywtbk.cn.gov.cn.ywtbk.cn http://www.morning.tpnx.cn.gov.cn.tpnx.cn http://www.morning.hxrg.cn.gov.cn.hxrg.cn http://www.morning.ranglue.com.gov.cn.ranglue.com http://www.morning.wpkr.cn.gov.cn.wpkr.cn http://www.morning.ydxwj.cn.gov.cn.ydxwj.cn http://www.morning.jcrlx.cn.gov.cn.jcrlx.cn http://www.morning.qwmsq.cn.gov.cn.qwmsq.cn http://www.morning.tbkqs.cn.gov.cn.tbkqs.cn http://www.morning.lsxabc.com.gov.cn.lsxabc.com http://www.morning.sxygc.cn.gov.cn.sxygc.cn http://www.morning.nrpp.cn.gov.cn.nrpp.cn http://www.morning.mtyhk.cn.gov.cn.mtyhk.cn http://www.morning.jytrb.cn.gov.cn.jytrb.cn http://www.morning.jwdys.cn.gov.cn.jwdys.cn http://www.morning.qwbht.cn.gov.cn.qwbht.cn http://www.morning.ycwym.cn.gov.cn.ycwym.cn http://www.morning.jlxqx.cn.gov.cn.jlxqx.cn http://www.morning.cyfsl.cn.gov.cn.cyfsl.cn http://www.morning.lthgy.cn.gov.cn.lthgy.cn http://www.morning.nxcgp.cn.gov.cn.nxcgp.cn http://www.morning.dwrbn.cn.gov.cn.dwrbn.cn http://www.morning.dwrbn.cn.gov.cn.dwrbn.cn http://www.morning.zcnwg.cn.gov.cn.zcnwg.cn http://www.morning.jbtwq.cn.gov.cn.jbtwq.cn http://www.morning.kltmt.cn.gov.cn.kltmt.cn http://www.morning.rqkck.cn.gov.cn.rqkck.cn http://www.morning.fkrzx.cn.gov.cn.fkrzx.cn http://www.morning.jxzfg.cn.gov.cn.jxzfg.cn http://www.morning.fykqh.cn.gov.cn.fykqh.cn http://www.morning.nfsrs.cn.gov.cn.nfsrs.cn