当前位置: 首页 > news >正文

python爬虫获取网易云音乐评论歌词以及歌曲地址

python爬虫获取网易云音乐评论歌词以及歌曲地址

  • 一.寻找数据接口
  • 二.对负载分析
  • 三.寻找参数加密过程
    • 1.首先找到评论的请求包并找到发起程序
    • 2.寻找js加密的代码
  • 四.扣取js的加密源码
    • 1.加密函数参数分析
      • ①.JSON.stringify(i0x)
      • ②bse6Y(["流泪", "强"])
      • ③bse6Y(Qu1x.md)
      • ④.bse6Y(["爱心", "女孩", "惊恐", "大笑"])
    • 1.加密函数分析
  • 五.在本地环境使用此函数
    • 1.直接将js代码复制并用js环境运行
    • 2.将js代码翻译为python代码
  • 六.python代码

一.寻找数据接口

评论
url:https://music.163.com/weapi/comment/resource/comments/get
在这里插入图片描述

在这里插入图片描述
歌词
url:https://music.163.com/weapi/song/lyric
在这里插入图片描述

在这里插入图片描述

歌曲地址
url:https://music.163.com/weapi/song/enhance/player/url/v1
在这里插入图片描述

二.对负载分析

从三个接口的负载我们可以得出

data={
params:加密数据
encSecKey:加密数据
}

所以我们只需要找出这个两个参数的加密过程就能模拟请求并得到我们想要的数据

三.寻找参数加密过程

因为这三个接口的加密是一样的这里我们用评论的接口来讲解

1.首先找到评论的请求包并找到发起程序

在这里插入图片描述
f12打开调试并且点击网络然后找到对应的包https://music.163.com/weapi/comment/resource/comments/get
点击发起程序

2.寻找js加密的代码

我们先点击发起程序的第一个进入到js文件中找到请求发出的地方也就是
send()函数

先加个断点然后刷新页面(下图)
在这里插入图片描述

在这里插入图片描述


刷新后我们就可以看到调用栈然后从第一个往下点一直找到send()(上图)


在这里插入图片描述
找到send()后我们取消掉前面的断点并给send()打上断点然后再次刷新网页(上图)
在这里插入图片描述

这个url代表的是此次请求发送的url我们评论的url为https://music.163.com/weapi/comment/resource/comments/get所以我们点击上面的小三角放过此次请求直至抓取到我们所需的请求(上图)
在这里插入图片描述
在这里插入图片描述
我们现在就抓取到了评论请求的data数据等信息我们可以看到此时的信息还是加密的所以我们要继续向前找寻找到它未加密的地方(上图)
在这里插入图片描述
data的加密数据在t0x这个调用栈前面是没有的所以我们就能确定数据是在这个调用栈中被加密然后我们ctrl+ F 直接搜索params就定位到了加密的函数

四.扣取js的加密源码

var bVi6c = window.asrsea(JSON.stringify(i0x), bse6Y(["流泪", "强"]), bse6Y(Qu1x.md), bse6Y(["爱心", "女孩", "惊恐", "大笑"]));e0x.data = j0x.cr1x({params: bVi6c.encText,encSecKey: bVi6c.encSecKey})

根据上一步我们找到的源码我们可以看出
我们所需的两个加密数据 params,encSecKey都是由 bVi6c产生的
bVi6c是由 这个函数生成的所以只需要取出这个函数的加密过程就能模拟出我们的加密数据

window.asrsea(JSON.stringify(i0x), bse6Y(["流泪", "强"]), bse6Y(Qu1x.md), bse6Y(["爱心", "女孩", "惊恐", "大笑"]));

1.加密函数参数分析

我们先给函数打上断点然后刷新网页
在这里插入图片描述
和上面的步骤一样还是需要点击三角知道找到我们所需的接口

①.JSON.stringify(i0x)

JSON.stringify()
JSON.stringify 是 JavaScript 中的一个全局函数,用于将一个 JavaScript 值(如 JavaScript 对象或数组)转换为 JSON 格式的字符串。这对于将数据保存到文件、在网页之间传递数据、或发送到服务器(例如通过 AJAX 请求)非常有用,因为 JSON 是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。
这个函数的作用就是将i0x转换为json格式
我们点击控制台然后输入i0x就可以得到i0x的值

{"rid": "R_SO_4_28188263","threadId": "R_SO_4_28188263","pageNo": "1","pageSize": "20","cursor": "-1","offset": "0","orderType": "1","csrf_token": "71bfd80a0c48b6dbdef22c1499cd480c"
}

rid与threadId就是歌的id
csrf_token是用户的登录状态
剩下的就是关于评论的参数

使用JSON.stringify()函数将i0x转换后我们就得到了第一个参数

②bse6Y([“流泪”, “强”])

第二个参数我们可以看出他是一个函数的返回值他的参数是[“流泪”, “强”]所以我们认为他的值是固定的
我们只需要在控制台输入bse6Y([“流泪”, “强”])就可以得到第二个参数的值
在这里插入图片描述
bse6Y([“流泪”, “强”])=‘010001’

③bse6Y(Qu1x.md)

首先我们要获取Qu1x.md的值我们直接控制台输入Qu1x.md
在这里插入图片描述

['色', '流感', '这边', '弱', '嘴唇', '亲', '开心', '呲牙', '憨笑', '猫', '皱眉', '幽灵', '蛋糕', '发怒', '大哭', '兔子', '星星', '钟情', '牵手', '公鸡', '爱意', '禁止', '狗', '亲亲', '叉', '礼物', '晕', '呆', '生病', '钻石', '拜', '怒', '示爱', '汗', '小鸡', '痛苦', '撇嘴', '惶恐', '口罩', '吐舌', '心碎', '生气', '可爱', '鬼脸', '跳舞', '男孩', '奸笑', '猪', '圈', '便便', '外星', '圣诞']

所以bse6Y(Qu1x.md)值也是固定的
在这里插入图片描述
在这里插入图片描述

bse6Y(Qu1x.md)=‘00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7’

④.bse6Y([“爱心”, “女孩”, “惊恐”, “大笑”])

和参数二一样他也是一个固定值直接控制台输出

bse6Y(["爱心", "女孩", "惊恐", "大笑"])='0CoJUm6Qyw8W8jud'

1.加密函数分析

window.asrsea(JSON.stringify(i0x), bse6Y(["流泪", "强"]), bse6Y(Qu1x.md), bse6Y(["爱心", "女孩", "惊恐", "大笑"]))

我们已经得到了window.asrsea()的参数现在只有找到此函数的源码就可以模拟加密了
我们直接ctrl+F搜索window.asrsea
在这里插入图片描述
我们直接把这个函数复制下来

!function() {function a(a) {var d, e, b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", c = "";for (d = 0; a > d; d += 1)e = Math.random() * b.length,e = Math.floor(e),c += b.charAt(e);return c}function b(a, b) {var c = CryptoJS.enc.Utf8.parse(b), d = CryptoJS.enc.Utf8.parse("0102030405060708"), e = CryptoJS.enc.Utf8.parse(a), f = CryptoJS.AES.encrypt(e, c, {iv: d,mode: CryptoJS.mode.CBC});return f.toString()}function c(a, b, c) {var d, e;return setMaxDigits(131),d = new RSAKeyPair(b,"",c),e = encryptedString(d, a)}function d(d, e, f, g) {var h = {}, i = a(16);return h.encText = b(d, g),h.encText = b(h.encText, i),h.encSecKey = c(i, e, f),h}function e(a, b, d, e) {var f = {};return f.encText = c(a + e, b, d),f}window.asrsea = d,
}();

这就是加密函数

五.在本地环境使用此函数

1.直接将js代码复制并用js环境运行

python如何执行js代码: https://blog.csdn.net/python_9k/article/details/138562809
Node.js安装与配置(详细步骤): https://blog.csdn.net/qq_42006801/article/details/124830995

2.将js代码翻译为python代码

如果读不懂js代码直接复制给ai来使用

这段JavaScript代码定义了一系列函数,用于生成随机字符串、使用AES加密、使用RSA加密,以及组合这些加密步骤来形成最终的加密数据。下面是对这些函数及其作用的详细解释:
1. a(a)
•  功能:生成一个长度为a的随机字符串,字符串由字母(大小写)和数字组成。
•  实现:使用Math.random和Math.floor生成随机索引,从字符集b中选取字符,最终拼接成一个随机字符串。
2. b(a, b)
•  功能:使用AES算法加密字符串a,密钥是b。
•  实现:使用CryptoJS库中的AES加密方法,采用CBC模式,IV(初始化向量)固定为0102030405060708,加密后返回加密字符串的Base64编码。
3. c(a, b, c)
•  功能:使用RSA算法加密字符串a,公钥由b和c组成(b是公钥的指数,c是模数)。
•  实现:使用RSAKeyPair创建一个RSA公钥,然后使用encryptedString方法加密字符串a。
4. d(d, e, f, g)
•  功能:组合AES和RSA加密,首先使用AES加密d,然后对加密后的AES密钥再进行一次AES加密,并使用RSA加密生成的随机字符串i。
•  实现: 
•  生成16位随机字符串i。
•  使用g作为AES密钥加密d。
•  使用i作为新的AES密钥再次加密前一步的输出。
•  使用RSA公钥(e和f)加密i。
•  返回一个对象,包含encText(两次AES加密后的结果)和encSecKey(RSA加密后的结果)。
5. e(a, b, d, e)
•  功能:使用RSA算法加密字符串a加上e,公钥由b和d组成。
•  实现:与c函数相似,但是将a + e作为要加密的字符串。
6. window.asrsea = d
•  功能:将d函数绑定到window对象的asrsea属性上,使其在全局范围内可用。
加密步骤总结
•  首先,生成一个随机字符串i。
•  使用g作为AES密钥加密原始数据d。
•  再次使用i作为AES密钥加密上一步的结果。
•  最后,使用RSA公钥加密i,生成encSecKey。
•  返回一个包含encText(两次AES加密的结果)和encSecKey(RSA加密的结果)的对象。
这种加密策略通常用于网络请求中,尤其是音乐流媒体服务或API接口,以保护数据在传输过程中的安全。

六.python代码

main.py


from Crypto.Cipher import AES
import base64
from Crypto.Util.Padding import pad
import requests
from jiami import Ajimport re
def gdata(decrypt_str):key_str = '0CoJUm6Qyw8W8jud'iv_str = "0102030405060708"a = "ouPO61mhRSoLJEwz"encrypt_str = aes_cbc_encrypt_text(decrypt_str, key_str, iv_str)encrypt_str = aes_cbc_encrypt_text(encrypt_str, a, iv_str)return encrypt_strdef idh():name = input('请输入歌名: ')i1x = {'csrf_token': "",'limit': "8",'s': name}data = i1xaj = Aj(data)url = 'https://music.163.com/weapi/search/suggest/web'res = requests.post(url, data={'params': aj.getparams(data), 'encSecKey': aj.getenseckey()})return str(res.json()["result"]["songs"][0]["id"])def aes_cbc_encrypt_text(decrypt_text: str, key: str, iv: str) -> str:"""加密AES_CBC的明文:param decrypt_text: 明文:param key: 密钥:param iv: 密钥偏移量:return: 密文"""aes2 = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))encrypt_text = aes2.encrypt(pad(decrypt_text.encode('utf-8'), AES.block_size, style='pkcs7'))encrypt_text = str(base64.encodebytes(encrypt_text), encoding='utf-8').replace("\n", "")return encrypt_textidd=idh()
rid='R_SO_4_'+idd# AES_CBC加密模式
decrypt_str = "{\"ids\":\"["+str(idd)+"]\",\"level\":\"standard\",\"encodeType\":\"aac\"}"
decrypt_str2='{\"rid\": \"%s\",\"threadId\": \"%s\",\"pageNo\": \"1\",\"pageSize\": \"20\",\"cursor\": \"-1\",\"offset\": \"0\",\"orderType\": \"1\"}'%(rid,rid)
decrypt_str3='{\"id\":\"%s\",\"lv\": \"-1\",\"tv\":\"-1\"}'%iddparams=gdata(decrypt_str)
params2=gdata(decrypt_str2)
params3=gdata(decrypt_str3)
encSecKey="c13dc213bd5889986ef8a7af39406c640bf77c6a5a34fe86324b648708b3af49919368a2d555771ea5453a605be7bfeaca0860696a9a9889e24a925bfeb56455f7275e534e733eaa5f94392d7b75da0701b8f38a3006bd6cd10cce66d64daa39f6dd12f970421d79b91abc8116012ee4f2dc8c7648c527abc22158b0338a9171"
url='https://music.163.com/weapi/song/enhance/player/url/v1?'
url2='https://music.163.com/weapi/comment/resource/comments/get?'
url3='https://music.163.com/weapi/song/lyric'
data={'params': params,
'encSecKey': encSecKey
}
data2={
'params': params2,
'encSecKey': encSecKey
}
data3={
'params': params3,
'encSecKey': encSecKey
}
res=requests.post(url,data=data)
res2=requests.post(url2,data=data2)
res3=requests.post(url3,data=data3)
print("评论:")
for i in res2.json()["data"]["comments"]:print(i["content"])
#print(res.text)
print('___________________________________________________________________')
print("歌曲url:")
print(res.json()['data'][0]['url'])
print('___________________________________________________________________')
print("歌词:")
txt=res3.json()["lrc"]
list=re.findall(r'\[(.*?)\](.*?)\\n',str(txt),re.S)
for i in list:print(i[1])

jiami.py

from Crypto.Cipher import AES
from base64 import b64encode
import jsonclass Aj:g='0CoJUm6Qyw8W8jud'i="7HCEonr7xwebMhJV"def __init__(self,data):self.data=datadef getenseckey(self):return "774c6922c77e2d39c9ec18d91210752d86517dee1ab731b3f8a41306ef5b92bc5809105f6cd679375d557dbf59746e1ace6b5a8a313efd70d3c645d198e3e509dbb61776926032eaccfa92c6f5921c8672baf3a2fd5d6d08c1a6869200fbb5e3191902026144060d6e58afcd9ef95f8be592fa80a25791c5b51a1264905026cf"def jiamiAES(self,data, key):# data=data.encode("utf-8")iv = '0102030405060708'aes = AES.new(key=key.encode("utf-8"), IV=iv.encode("utf-8"), mode=AES.MODE_CBC)bs = aes.encrypt(data.encode("utf-8"))return str(b64encode(bs), "utf-8")def getparams(self,data):data = json.dumps(data)data = self.to_16(data)t1 = self.jiamiAES(data,self.g)t2 = self.jiamiAES(self.to_16(t1),self.i)return t2def to_16(self,data):pad = 16 - len(data) % 16data += chr(pad) * padreturn data

相关文章:

python爬虫获取网易云音乐评论歌词以及歌曲地址

python爬虫获取网易云音乐评论歌词以及歌曲地址 一.寻找数据接口二.对负载分析三.寻找参数加密过程1.首先找到评论的请求包并找到发起程序2.寻找js加密的代码 四.扣取js的加密源码1.加密函数参数分析①.JSON.stringify(i0x)②bse6Y(["流泪", "强"])③bse6Y…...

中间件的理解

内容来源于学习网站整理。【一看就会】什么是前端开发的中间件?_哔哩哔哩_bilibili 每日八股文~白话说mq,消息中间件_哔哩哔哩_bilibili 例如: 1)两个人打电话,中间的通信网络就是中间件。 2)菜鸟驿站&…...

django实现用户的注册、登录、注销功能

创建django项目的步骤:Django项目的创建步骤-CSDN博客 一、前置工作 配置数据库,设置数据库引擎为mysql 1、在settings文件中找到DATABASES, 配置以下内容 DATABASES {"default": {ENGINE: django.db.backends.mysql, # 数据库引擎NAME: dja…...

【JAVA 常用API】数据库字段存储JSON格式数据,JAVA中如何将List<Entity>或者对象实体转换为字符串

在Java中,可以使用第三方库如Jackson或Gson来进行JSON的转换。这些库提供了将Java对象转换为JSON字符串的方法。 一:Gson API转Json Getter Setter NoArgsConstructor AllArgsConstructor ToString Builder public class Person {private String name;p…...

AI算不出9.11和9.9哪个大?六家大模型厂商总结了这些原因

大模型“答对”或“答错”其实是个概率问题。关于“9.11和9.9哪个大”,这样一道小学生难度的数学题难倒了一众海内外AI大模型。7月17日,第一财经报道了国内外“12个大模型8个都会答错”这道题的现象,大模型的数学能力引发讨论。 “从技术人员…...

MacBook电脑远程连接Linux系统的服务器方法

一、问题简介 Windows 操作系统的电脑可使用Xshell等功能强大的远程连接软件。通过连接软件,用户可以在一台电脑上访问并控制另一台远程计算机。这对于远程技术支持、远程办公等场景非常有用。但是MacBook电脑的macOS无法使用Xshell。 在Mac上远程连接到Windows服…...

CSS-0_3 CSS和单位

文章目录 CSS的值和单位属性值长度单位CSS和绝对单位CSS和相对单位百分比em & rem视口 颜色单位 碎碎念 CSS的值和单位 我们知道,CSS是由属性和属性值所组成的表 随着CSS的发展,属性不说几千也有几百,我从来不支持去背诵所有的可能性。…...

【代码随想录|贪心算法 455. 分发饼干 376. 摆动序列 53. 最大子数组和】

代码随想录|贪心算法 455. 分发饼干 一、455. 分发饼干1.代码2.问题 二、376. 摆动序列1.代码 三、53. 最大子数组和1.代码 总结 python 一、455. 分发饼干 455. 分发饼干 1.代码 代码如下(示例): class Solution:def findContentChildr…...

swift小知识点(二)

1、 Swift 枚举 Swift 中使用 enum 关键词来创建枚举并且把它们的整个定义放在一对大括号内: enum enumname {// 枚举定义放在这里 } 如下事例: // 定义枚举 enum DaysofaWeek {case Sundaycase Mondaycase TUESDAYcase WEDNESDAYcase THURSDAYcase…...

机器人产业发展格局多元化,创业公司突破瓶颈需多维施策

当前,机器人产业的发展格局呈现出多元化、快速增长和技术不断创新的特点。从全球视角来看,机器人市场持续增长,预计到2026年全球人形机器人市场规模将超过20亿美元,到2030年有望突破200亿美元,显示出巨大的市场潜力和发…...

接口测试JMeter-1.接口测试初识

第一章 接口测试初识 1. 接口测试理论基础 “接口测试”一个让人觉得非常高大上的名词,特别是对于刚入门的测试同学而言。随着测试技术不断的深化,“接口测试”出现在我们视野中的频次越来越高。那么接口测试到底是如何做的?接口测试的优势又…...

[米联客-安路飞龙DR1-FPSOC] FPGA基础篇连载-22 TPG图像测试数据发生器设计

软件版本:Anlogic -TD5.9.1-DR1_ES1.1 操作系统:WIN10 64bit 硬件平台:适用安路(Anlogic)FPGA 实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板 板卡获取平台:https://milianke.tmall.com/ 登录“米联客”FPGA社区 ht…...

如何通过企业微信会话存档保护企业利益?

赵总: 张经理,最近行业内频发数据泄露事件,我们的客户资料和内部沟通记录安全吗? 张经理: 赵总,我们已经采取了一系列措施来加强数据安全。特别是针对企业微信的沟通记录,我们最近引入了安企神软件,它能很…...

git修改提交姓名

git config --global user.name “新用户名” git config --global user.email “新邮箱地址” 修改提交的用户名 git config --global user.name “yu***”...

5、在共享内存无指针编程:句柄HANDLE转换为指针

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 共享内存里面不能用指针&#…...

hive动态分区导致xceivercount超限,hdfs无法创建新连接

目录 一、事件复盘: 二、解决方案: 三、讨论 一、事件复盘: hdfs无法创建新的文件,xceivercount超过最大设置,平时每个datanode只有100个左右的连接,突然达到8000以上。 事故原因,跨多天的…...

如何识别Android init 中的缓慢操作

Android 14 开机时间优化措施汇总-CSDN博客 Android 14 开机时间优化措施-CSDN博客根据systrace报告优化系统时需要关注的指标和优化策略-CSDN博客Android系统上常见的性能优化工具-CSDN博客Android上如何使用perfetto分析systrace-CSDN博客Android系统设置kernel log level的…...

JVM:常用工具总结

文章目录 一、jstat工具 一、jstat工具 Jstat工具是JDK自带的一款监控工具,可以提供各种垃圾回收、类加载、编译信息等不同的数据。使用方法为:jstat -gc进程ID每次统计的时间间隔(毫秒)统计次数。 C代表Capacity容量&#xff0c…...

二染色,CF 1594D - The Number of Imposters

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1594D - The Number of Imposters 二、解题报告 1、思路分析 并查集&…...

Go语言并发编程-Channel通信_2

Channel通信 Channel概述 不要通过共享内存的方式进行通信,而是应该通过通信的方式共享内存 这是Go语言最核心的设计模式之一。 在很多主流的编程语言中,多个线程传递数据的方式一般都是共享内存,而Go语言中多Goroutine通信的主要方案是Cha…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

无法与IP建立连接,未能下载VSCode服务器

如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...

android13 app的触摸问题定位分析流程

一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...