抖音弹幕获取的另一种方式
背景需求公司最近需要做一个直播尝试,需要获取抖音弹幕的信息,没想到抖音的直播开放平台没有相关的接口开放出来,感觉这个绝对是有问题的,作为开发者,获取自己直播间的相关信息,是个很正常的需求。 然后诉诸网络,有人做了付费的服务来获取弹幕,比较贵,不过感觉挺厉害的,好像就是破解了算法,接口信息很详细,不过抖音也会换算法,这个接口估计也得跟着改,所以人家这个付费好像也能够理解。 实现思路所以公司考虑自己做,然后我就上场了 .第一步github找思路,发现都是广告,没有可利用的,不过在大量的信息中还是能够了解到只鳞片爪的,大家的思路基本是硬钢算法。 .分析抖音的网页直播间的请求,发现弹幕信息是个定时请求,返回数据是protobuf形式的,没有加密,只要protobuf序列化即可。 然后请求的关键在于请求中需要计算signature,还有什么x-xx啥的字段,然后结合github,发现还是么法找出前端的加密算法。 不过找到了protobuf的定义获取方式,这个还是比较关键的,有所了解的同学会方向,定义的proto...
Node.js + Kafka Docker部署实践
部署经验在使用 Docker 部署 Kafka 时,主要使用了 bitnami/kafka 镜像。这个镜像在 DockerHub 上口碑较好,功能完善。 关键配置点最重要的配置是 KAFKA_CFG_ADVERTISED_LISTENERS 参数: 1KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://xxx.xxx.xxx.xxx:9092 需要配置内网 IP(有些场景也可以使用外网 IP) 这个配置对客户端连接至关重要 Docker Compose 配置 这个版本是 kraft 的,没有 zookeeper,使用起来感觉比较方便。 另一个关键点是端口映射。多次经验表明,不能使用默认端口,例如 Redis 和 Kafka 的...
egg-mongoose 多数据库配置实践
背景在开发运维平台时,需要支持多分支环境,每个分支连接不同的数据库。为了实现数据库的动态切换,对 egg-mongoose 进行了多数据库配置。由于网上相关资料较少,特此记录实现方案。 实现步骤1. 配置多数据库连接在 config.default.js 中配置多个数据库连接: 123456789101112131415161718config.mongoose = { clients: { // clientId, 通过 app.mongooseDB.get('clientId') 访问实例 local: { url: 'mongodb://xxx:xxx@xxx:/xxx-s?authSource=admin', options: { }, }, master: { url:...
2021第一篇
2020年回顾考研经历年初参加考研,虽然与分数线差距较大,但这次经历让我对专业知识有了更深的理解。因为考研失利,没有及时准备换工作,导致现在的薪资水平已接近行业底线。计划在年底开始准备面试和工作调整。 职业发展 完成了软件设计师证书考试,这是今年为数不多的成就之一 收获了一个不错的刷题资源,作者的讲解深入浅出,让人有继续学习的动力 2021年规划学习计划 继续考研准备 软件架构师考试准备 关于架构师考试的思考虽然业界普遍认为架构师证书在互联网公司用处不大,但备考过程中我发现: 内容虽然偏传统,但涉及了很多上层建筑的知识 对系统架构设计能力有很大帮助 整体收获超出预期 考研感悟 重新认识了马克思主义理论的哲理性 发现计算机专业知识的深度和细节 深感”温故而知新”的重要性 职业规划 保持每日算法学习 寻找更大的平台发展机会 当前公司虽然环境舒适,但技术发展较为停滞 更倾向于在工作中学习,纯兴趣驱动的技术探索难以坚持 虽然目前的工作环境还不错,但为了更好的发展,是时候做出改变了。
LeetCode - 链表求和
题目链接LeetCode 2. 两数相加 解题思路这道题主要的关键点在于最后的位数的处理。如果两数位数不等,那么就要进行补位操作。 代码实现123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */let reverseNode = function(head) { let preNode = null; let nextNode = null; let currentNode = head; while (currentNode) { nextNode = currentNode.next; // 保存下一个节点 ...
LeetCode - 链表反转
题目链接LeetCode 206. 反转链表 解题思路关键在于维护 next 指针。我们需要在遍历链表的过程中,逐步反转每个节点的指向。 代码实现12345678910111213141516171819202122232425/** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } *//** * @param {ListNode} head * @return {ListNode} */var reverseList = function(head) { let current = head; let preNode = null; let nextNode = null; while (current) { nextNode = current.next; // 保存下一个节点 ...
ABSD 体系结构演化
引言软件体系结构的演化是一个持续的过程,需要遵循一定的规范和步骤。本文将详细介绍 ABSD 体系结构演化的六个关键步骤。 演化的关键步骤1. 需求变动归类 系统化归类用户需求变化 将变化需求与现有构件对应 标记无对应构件的变动,为后续创建新构件做准备 2. 制定演化计划在改变原有结构之前,开发团队需要制定周密的体系结构演化计划,作为后续演化开发工作的指南。计划应包含具体的时间节点和验收标准。 3. 构件的修改与管理 根据需求变动归类情况进行构件调整 增加、删除或修改现有构件 完成相关功能性测试 确保修改不影响现有功能 4. 更新构件交互关系 梳理构件间的依赖关系 更新构件间的控制流 确保接口兼容性 维护系统整体一致性 5. 构件组装与测试 使用组装支持工具完成构件组装 完成整个软件系统的链接和合成 形成新的体系结构 进行整体功能和性能测试 6. 技术评审 确认上述步骤的执行情况 评估组装后的体系结构是否反映了需求变动 验证是否符合用户需求 检查系统整体性能指标 最佳实践 保持完整的文档记录 建立有效的版本控制 进行充分的回归测试 制定应急回滚方案 总结ABSD...
LeetCode 每日一题 - 两数之和
题目描述给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。 解题思路方法一: 暴力循环最初采用双重循环的方式,但在大数据量时会超时。 方法二: Map优化使用 Map 数据结构可以避免多次遍历: 1234567891011121314var twoSum = function(nums, target) { let map = new Map(); let result; for(let key in nums) { let value = nums[key]; result = target - value; if(map.has(result)) { return [map.get(result), key]; } map.set(value, key); ...
LeetCode - 三数之和题解
题目描述给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c,使得 a + b + c = 0。请找出所有满足条件且不重复的三元组。 解题思路双指针法123456789101112131415161718192021222324252627282930var threeSum = function(nums) { let result = []; nums.sort((a, b) => a - b); // 先排序 for(let i = 0; i < nums.length - 2; i++) { // 跳过重复值 if(i > 0 && nums[i] === nums[i-1]) continue; let left = i + 1; let right = nums.length - 1; while(left < right)...
LeetCode - 分隔链表题解
题目描述给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。需要保持节点的相对顺序。 解题思路双指针法123456789101112131415161718192021222324252627var partition = function(head, x) { // 创建两个虚拟头节点 let smallHead = new ListNode(0); let bigHead = new ListNode(0); // 用于移动的指针 let small = smallHead; let big = bigHead; // 遍历原链表 while(head) { if(head.val < x) { small.next = head; small = small.next; } else { big.next =...


