JS逆向-某易云音乐下载器
文章目录
- 介绍
- 下载链接
- Robots文件
- 搜索功能
- JS逆向
- **函数a:生成随机字符串**
- **函数b:AES-CBC加密**
- **函数c:RSA公钥加密**
- 歌曲下载
- 总结
介绍
在某易云音乐中,很多歌曲听是免费的,但下载需要VIP,此程序旨在“可听”则可下,只要能够听的歌,都可以下载下来。
而此篇博客则着重讲此代码是如何编写的,如果只想要下载工具,请自行查看下载链接。
注意,此程序仅做学习参考,任何违法行为与作者无关。
下载链接
GitHub:https://github.com/13337356453/163Music
CSDN:https://download.csdn.net/download/realmels/90855703
Robots文件
养成好习惯,爬虫之前,先看robots文件。
禁止爬取
/prime/m/gift-receive
文件,刚好,我们这次不爬取此文件。
搜索功能
在某易云音乐中提供了搜索功能,可以通过关键词搜索歌曲。
而我们的程序需要通过用户关键词来搜索内容,因此需要首先从搜索功能开始爬取。
在这里通过歌曲abc为例,进行搜索功能的分析与实现。
在搜索栏输入关键字abc,按下回车键得到搜索结果。
按下F12进入开发者工具,选中Network,点击XHR查看Ajax的请求包
刷新界面,出现了很多请求包
逐个查看请求包的Response,寻找搜索歌曲的请求包。
在路径为
/weapi/cloudsearch/get/web
的请求包中,我们可以看到歌曲的搜索信息。
可以确定这个就是搜索歌曲的请求包。
接下来分析请求参数。
这是一个POST请求,请求的URL为:https://music.163.com/weapi/cloudsearch/get/web
,POST的参数如下:
params=NM406wjNCdicjbT3ZSuA7X6ICkCBzfN6rA1KAeZR4Pmpv6VhTT8jKqR/ZRpGitFCp77TipjrdwPahGWiMjGf2cLrREp5Gadgeseo9l9+IMfrwG/JmgDfW9pLZaRIagi+MSESFlTJnlH3vJI7YbqwWPjgfbyzBX0sgw4l3IXxfuamFggnztM3DlEhB1uCBUPqEpDFlsMW8pPdEPtaJS47Y2DMXBY/SJVOa8Y3nD/rjP2lhw5sXaZ3qs5LEwmYKiriEAaZ6fRmKJb4Vn6Ay6ELCBWL74DqjF4BPh8GsEPicXdah/nR0BPoM+suZbKCICMK
encSecKey=8b987300e7f1a5e657c7a69d3c9ff9a4d9ab1c3dc1b2328df473600103b1fe18aa4898008ac9d03074c2cb560543ac22740c4c0c1f7d2c14535f938344a999224733d97e75ffdc26dc2a7ac9afff302f127b29ee762ce02061b9ce89ad2b9006938ed0e62667bfbac656b12adbe951ccff0d02dacd27fb94de7473fa933043ec
别的都容易理解,这两个参数是什么呢?
我们从JS文件中找答案。
JS逆向
在这里先科普基本知识。一个网站,分为前端和后端,前端负责展现好看的页面,后端负责处理繁杂的数据。用户通过前端界面,将数据发送到后端,后端代码处理数据,将相应的结果发送到前端,呈现在用户眼前。这个过程通过request/response,实现。因此,前端所有奇形怪状的参数,都可以在前端代码中找到蛛丝马迹。毕竟,后端代码是不可见的,而前端代码是公开的。
首先需要明白params和encSecKey这两个参数是如何产生的,这里我们复制encSecKey,在开发者工具中选中Sources,按下Ctrl+Shift+F进行全局搜索。
在这里我们逐个进行分析,首先打开这个core开头的JS文件,顾名思义,core就是核心,因此最可能有我们想要的数据。
打开文件后按下Ctrl+F进行文件内搜索,搜索encSecKey,查询到三个结果。
我们分别进行分析。
在第二次出现的地方,我们需要的两个参数:params和encsecKey同时出现
怀疑这里有参数的生成逻辑,打一个断点。
刷新页面,程序运行到断点处停止。
可以看到,params和encsecKey这两个参数分别是bYE4I这个对象的两个属性。而bYE4I这个对象是由window.asrsea这个函数生成的。
我们把光标放到window.asrsea这个函数上,查看这个函数的真实面目。
跳转到函数d
我们可以看到,函数d中调用了函数a,b,c。正好这三个参数都在d函数的附近,我们一起复制过来查看。
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}
我们在d函数中打上断点,分析d函数的参数
一直点击上方的下一步,同时眼睛观察着右边的实时参数值。
多走几步,我们会发现函数d接受的四个参数中,e,f,g都是固定值,值如下:
e=010001
f=00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7
g=0CoJUm6Qyw8W8jud
而参数d的值却一直在变化。
我们一直点下一步的按钮,同时盯着参数,点着点着,会发现右侧的d参数发生变化,大多数时候都是csrf_token的值,我们不用管,但偶尔会出现别的内容,而大概点了几十次后,参数会变成:
d="{\"hlpretag\":\"<span class=\\\"s-fc7\\\">\",\"hlposttag\":\"</span>\",\"s\":\"abc\",\"type\":\"1\",\"offset\":\"0\",\"total\":\"true\",\"limit\":\"30\",\"csrf_token\":\"\"}"
在其中,出现了我们的关键词abc,以及出现歌曲的数量30
确定d函数就是生成参数的逻辑。
接下来仔细分析d函数。
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}
首先定义了一个空对象h,然后通过a函数生成内容,赋值给i,接下来通过b函数生成第一个encText,赋给h的属性,接受参数d和g,再用b函数二次处理encText,参数为第一次处理的encText和i,这就是提交时所需的params;同时用c函数生成encsecKey,接受参数i,e,f
接下来我们逐个分析a,b,c函数
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)}
人与动物的区别就是人会使用工具,我们直接问deepseek
这是deepseek的回答。
函数a:生成随机字符串
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
}
- 功能:生成指定长度的随机字符串,字符集包括大小写字母和数字。
- 参数:
a
控制字符串长度。 - 实现细节:
- 循环
a
次,每次从字符池b
中随机选取一个字符。 - 使用
Math.random()
生成随机索引,可能不够安全(非密码学安全随机数)。
- 循环
- 安全问题:
Math.random()
在浏览器中可能被预测,建议改用crypto.getRandomValues()
。
- 用途:生成临时密钥、Nonce 或盐值。
函数b:AES-CBC加密
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()
}
- 功能:使用 AES-CBC 模式加密数据,密钥由参数提供。
- 参数:
a
:明文数据(UTF-8 字符串)。b
:加密密钥(UTF-8 字符串)。
- 实现细节:
- 固定初始化向量(IV)
0102030405060708
。 - 使用
CryptoJS
库进行加密,返回 Base64 编码的密文。
- 固定初始化向量(IV)
- 安全问题:
- 固定IV:CBC 模式要求每次加密使用随机 IV,否则可能导致明文模式泄露。
- 密钥建议使用二进制格式(如 PBKDF2 派生),而非直接字符串。
- 用途:加密传输敏感数据。
函数c:RSA公钥加密
function c(a, b, c) {var d, e;return setMaxDigits(131),d = new RSAKeyPair(b,"",c),e = encryptedString(d, a)
}
- 功能:使用 RSA 公钥加密数据。
- 参数:
a
:明文数据(字符串或数值)。b
:公钥指数(通常为"10001"
十六进制)。c
:RSA 模数(n)。
- 实现细节:
setMaxDigits(131)
设置大整数位数(支持最大 131 位,对应 1024 位 RSA)。RSAKeyPair
仅使用公钥指数和模数,私钥留空,表明这是公钥加密。encryptedString
可能是自定义函数,实现 RSA 加密逻辑。
- 安全问题:
- 需确认是否使用正确填充(如 PKCS#1 v1.5 或 OAEP),默认可能不安全。
- 用途:加密对称密钥(如 AES 密钥)以便安全传输。
知道了函数的用途,我们开始编写Python代码。
写一个工具类,分别实现函数abcd的功能,名字为JS,定义四个静态方法:
import base64
import random
from binascii import hexlifyfrom Crypto.Cipher import AES
from Crypto.Util.Padding import padclass JS:@staticmethoddef d(d,e="010001",f="00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7",g="0CoJUm6Qyw8W8jud"):'''生成数据'''i=JS.a(16)h_encText=JS.b(d,g)encText=JS.b(h_encText,i)encSecKey=JS.c(i,e,f)return encText,encSecKey@staticmethoddef a(a):'''生成16位随机字符'''b="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"c=""for i in range(a):e = random.randint(0, len(b) - 1)c+=b[e]return c@staticmethoddef b(a,b):'''AES加密'''key = b.encode('utf-8')iv = "0102030405060708".encode('utf-8')data = a.encode('utf-8')cipher = AES.new(key, AES.MODE_CBC, iv)encrypted = cipher.encrypt(pad(data, AES.block_size))return base64.b64encode(encrypted).decode('utf-8')@staticmethoddef c(a,b,c):'''RSA加密'''a = a[::-1]result = pow(int(hexlify(a.encode()), 16), int(b, 16), int(c, 16))return format(result, 'x').zfill(131)
至于这几个函数是如何改写的。。其实很简单。
接下来的步骤就很简单了,编写搜索歌曲功能代码:
import requests
from urllib.parse import quote
from json import loadsfrom JS import JSrequests.packages.urllib3.disable_warnings()
class Searcher:url="https://music.163.com/weapi/cloudsearch/get/web?csrf_token="headers={'Host': 'music.163.com','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36','Referer': 'https://music.163.com/search/','Content-Type': 'application/x-www-form-urlencoded',}jsonStr="{\"hlpretag\":\"<span class=\\\"s-fc7\\\">\",\"hlposttag\":\"</span>\",\"s\":\"%s\",\"type\":\"1\",\"offset\":\"0\",\"total\":\"true\",\"limit\":\"%d\",\"csrf_token\":\"\"}"def __init__(self,keyword,proxies={},number=1,cookie=""):self.keyword=keywordself.proxies=proxiesself.number=numberself.headers['Cookie']=cookiedef getData(self):s=self.jsonStr%(self.keyword,self.number)params,encSecKey=JS.d(s)data=f"""params={quote(params)}&encSecKey={quote(encSecKey)}"""try:r=requests.post(self.url,headers=self.headers,data=data,verify=False,timeout=10,proxies=self.proxies)if r.status_code==200:result=loads(r.content.decode())return result['result']['songs']return Noneexcept Exception as e:print(f'[!] {e}')return None
注意注意,这里有个非常坑的点,就是在传输data中,数据还要进行URL加密,否则就会报400,参数错误。这个点害了我一晚上。
我们成功实现了通过关键字搜索功能,获取到歌曲的id,name,这两个参数至关重要
歌曲下载
选中一首歌,我们打开详细页。
打开开发者工具抓包,同时点击播放按钮
抓取到数据包后,我们逐个分析。
锁定到
/weapi/song/enhance/player/url/v1
这个请求包,在请求包中,我们可以看到歌曲的下载链接。
我们把这个链接复制到浏览器打开,成功播放了歌曲,确定就是下载链接。
接下来我们分析这个请求包的参数。
熟悉的params和encsecKey,我们之前已经分析过了
使用同样方法打好断点,再次点击播放按钮,查看传入的参数。
这里出现了歌曲id,原始的参数为:
d="{\"ids\":\"[33004804]\",\"level\":\"exhigh\",\"encodeType\":\"aac\",\"csrf_token\":\"\"}"
于是我们可以编写相关Python代码:
from json import loads
from urllib.parse import quoteimport requestsfrom JS import JSrequests.packages.urllib3.disable_warnings()
class Musicer:url='https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token='headers={'Host': 'music.163.com','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36','Referer': 'https://music.163.com/search/','Content-Type': 'application/x-www-form-urlencoded',}jsonStr='{"ids":"[%s]","level":"exhigh","encodeType":"aac","csrf_token":""}'def __init__(self,musicid,cookie,name,proxies={}):self.musicid=str(musicid)self.headers['Cookie']=cookieself.proxies=proxiesself.name=namedef getDownloadUrl(self):s=self.jsonStr%self.musicidparams,encSecKey=JS.d(s)data=f"""params={quote(params)}&encSecKey={quote(encSecKey)}"""try:r=requests.post(self.url,headers=self.headers,data=data,verify=False,timeout=10,proxies=self.proxies)if r.status_code==200:return loads(r.content.decode())['data'][0]['url']return Noneexcept Exception as e:print(e)return Nonedef download(self):url=self.getDownloadUrl()try:r=requests.get(url,proxies=self.proxies,verify=False,timeout=10)if r.status_code==200:with open(f'{self.name}.mp3','wb') as f:f.write(r.content)print(f"[+] {self.name}.mp3 已保存")except Exception as e:print(f'[!] {e}')
至此,本项目全部完成。
总结
本博客仅做学习参考,任何违法犯罪行为与本文作者无关。
相关文章:
JS逆向-某易云音乐下载器
文章目录 介绍下载链接Robots文件搜索功能JS逆向**函数a:生成随机字符串****函数b:AES-CBC加密****函数c:RSA公钥加密** 歌曲下载总结 介绍 在某易云音乐中,很多歌曲听是免费的,但下载需要VIP,此程序旨在“…...
Qt与Hid设备通信
什么是HID? HID(Human Interface Device)是直接与人交互的电子设备,通过标准化协议实现用户与计算机或其他设备的通信,典型代表包括键盘、鼠标、游戏手柄等。 为什么HID要与qt进行通信? 我这里的应…...
QT使用QXlsx读取excel表格中的图片
前言 读取excel表格中的图片的需求比较小众,QXlsx可以操作excel文档,进行图片读取、插入操作,本文主要分享单独提取图片和遍历表格提取文字和图片。 源码下载 github 开发环境准备 把下载的代码中的QXlsx目录,整个拷贝到所创建…...
二叉树进阶
一、二叉搜索树 1.二叉搜索树的概念 二叉搜索树又称二叉排序树,它也可以是一棵空树,或是具备以下性质的树: 1.1 若它的左子树不为空,则它左子树上所有节点的值都小于根节点的值。 1.2 若它的右子树不为空,则它右子…...
腾讯 CodeBuddy 杀入 AI 编程赛道,能否撼动海外工具霸主地位?
在 AI 编程助手领域,海外的 Cursor 等工具风头正劲,如今腾讯带着 CodeBuddy 隆重登场,国产 AI 编程助手能否借其之力崛起?让我们一探究竟。 官网: 腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴 实战安装教程 …...
项目QT+ffmpeg+rtsp(二)——海康威视相机测试
文章目录 前言一、验证RTSP地址的有效性1.1 使用VLC播放器验证1.2 使用FFmpeg命令行验证1.3 使用Python代码检查网络连接1.4 检查摄像头Web界面1.5 使用RTSP客户端工具二、关于IPV4的地址2.1 原来2.1.1 原因2.2 解决2.3 显示前言 昨晚拿到一个海康威视的相机,是连接上了交换机…...
vscode用python开发maya联动调试设置
如何在VScode里编写Maya Python脚本_哔哩哔哩_bilibili1 包括1,maya的python全面在vscode支持,2,通过mayacode发送到maya,3同步调试 import maya.cmds as cmds 1、让 maya.cmds编译通过 下载Autodesk_Maya_2018_6_Update_DEVK…...
Postman遇到脚本不支持replaceIn函数
目录: 1、问题现象2、代码处理3、执行结果 1、问题现象 2、代码处理 function replaceVariables(template) {// 获取所有变量(环境变量全局变量)const variables pm.environment.toObject();const globalVars pm.globals.toObject();const…...
精益数据分析(64/126):移情阶段的用户触达策略——从社交平台到精准访谈
精益数据分析(64/126):移情阶段的用户触达策略——从社交平台到精准访谈 在创业的移情阶段,精准找到目标用户并开展深度访谈是验证需求的关键。今天,我们结合《精益数据分析》中的方法论,探讨如何利用Twit…...
turn.js与 PHP 结合使用来实现 PDF 文件的页面切换效果
将 Turn.js 与 PHP 结合使用来实现 PDF 文件的页面切换效果,你需要一个中间步骤将 PDF 转换为 Turn.js 可以处理的格式(如 HTML 页面或图片)。以下是实现这一功能的步骤和示例代码: 步骤 1: 安装必要的库 首先,你需要…...
SQL Server 与 Oracle 常用函数对照表
一、字符串处理函数 SQL Server 函数SQL Server 实例Oracle 函数Oracle 实例输出结果CONCATSELECT CONCAT(A, B, C);CONCATSELECT CONCAT(A, B) FROM DUAL;ABC(SQL) AB(Oracle)SUBSTRINGSELECT SUBSTRING(Hello, 2, 3);SUBSTRSEL…...
数据治理新纪元:全面解读TSDDITAI系列评估规范
在数字化转型的浪潮中,数据已成为驱动业务增长和创新的核心要素。然而,如何确保大数据产品、企业、人才及数据资源的优质与合规,成为了摆在行业面前的重大课题。为此,TSDDITAI系列评估规范应运而生,为大数据产业的健康…...
电子电路:什么是色环电阻器,怎么识别和计算阻值?
识别和计算色环电阻的阻值需要掌握颜色编码规则和基本步骤。以下是具体方法及窍门: 一、色环电阻的基本规则 色环数量: 4环电阻:前2环为有效数字,第3环为倍乘(10ⁿ),第4环为误差。5环电阻:前3环为有效数字,第4环为倍乘,第5环为误差。6环电阻(较少见):前3环为有效数…...
UE中的各种旋转
1 直接修改第三人称玩家的角度 注意不是修改玩家的actor或者pawn,而是修改controller的旋转 这只会修改相机的方向,不会修改角色的方向,因为第三人控制器的根物体不受controller控制,而相机弹簧臂受controller控制 如果修改角色…...
游戏引擎学习第289天:将视觉表现与实体类型解耦
回顾并为今天的工作设定基调 我们正在继续昨天对代码所做的改动。我们已经完成了“脑代码(brain code)”的概念,它本质上是一种为实体构建的自组织控制器结构。现在我们要做的是把旧的控制逻辑迁移到这个新的结构中,并进一步测试…...
NestJS——日志、NestJS-logger、pino、winston、全局异常过滤器
个人简介 👀个人主页: 前端杂货铺 🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步…...
list重点接口及模拟实现
list功能介绍 c中list是使用双向链表实现的一个容器,这个容器可以实现。插入,删除等的操作。与vector相比,vector适合尾插和尾删(vector的实现是使用了动态数组的方式。在进行头删和头插的时候后面的数据会进行挪动,时…...
Linux | mdadm 创建软 RAID
注:本文为 “Linux mdadm RAID” 相关文章合辑。 略作重排,未整理去重。 如有内容异常,请看原文。 Linux 下用 mdadm 创建软 RAID 以及避坑 喵ฅ・ﻌ・ฅ Oct 31, 2023 前言 linux 下组软 raid 用 mdadm 命令,multi…...
迁移学习:解锁AI高效学习与泛化能力的密钥
前言 在人工智能(AI)技术日新月异的今天,迁移学习(Transfer Learning)作为一项革命性技术,正深刻改变着机器学习领域的格局。 它不仅让模型能够像人类一样“举一反三”,更在加速模型开发、提升性…...
前端-HTML元素
目录 HTML标签是什么? 什么是HTML元素? HTML元素有哪些分类方法? 什么是HTML头部元素 更换路径 注:本文以leetbook为基础 HTML标签是什么? HTML标签是HTML语言中最基本单位和重要组成部分 虽然它不区分大小写&a…...
STM32之蜂鸣器和按键
一、蜂鸣器的原理与应用 基本概念 蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。 工作原理 蜂鸣器一般分为两类:有源…...
H3C UIS 超融合管理平台原理解读以及日常运维实操与故障处理
前言:超融合(Hyper-Converged Infrastructure, HCI)是将计算、存储、网络和虚拟化资源整合到统一硬件平台中,并通过软件定义技术实现资源池化与灵活管理的架构。H3C(新华三)和华为作为国内领先的ICT厂商&am…...
【强化学习】#5 时序差分学习
主要参考学习资料:《强化学习(第2版)》[加]Richard S.Suttion [美]Andrew G.Barto 著 文章源文件:https://github.com/INKEM/Knowledge_Base 缩写说明 DP:动态规划GPI:广义策略迭代MC:蒙特卡洛…...
Day119 | 灵神 | 二叉树 | 二叉树的最近共公共祖先
Day119 | 灵神 | 二叉树 | 二叉树的最近共公共祖先 236.二叉树的最近共公共祖先 236. 二叉树的最近公共祖先 - 力扣(LeetCode) 思路: 二叉树的最近公共祖先【基础算法精讲 12】_哔哩哔哩_bilibili 首先我们采用后序遍历 递归函数返回值…...
Elasticsearch 性能优化面试宝典
Elasticsearch 性能优化面试宝典 🚀 目录 设计调优 🏗️写入调优 ⚡查询调优 🔍综合设计 💎总结 📝设计调优 🏗️ 面试题1:索引设计优化 题目: 假设需要设计一个电商商品索引,日增数据量1TB,要求支持多维度查询(名称、分类、价格区间)。请说明索引设计的关…...
mysql数据库-中间件MyCat
1. MyCat简介 在整个 IT 系统架构中,数据库是非常重要,通常又是访问压力较大的一个服务,除了在程序开发的本身做优化,如: SQL 语句优化、代码优化,数据库的处理本身优化也是非常重要的。主从、热备、分表分…...
制作大风车动画
这个案例的风车旋转应用了图形变换来实现,速度和缩放比例应用slider来实现,其中图片的速度,图片大小的信息通过State来定义变量管理,速度和和缩放比例的即时的值通过Prop来管理。 1. 案例效果截图 2. 案例运用到的知识点 2.1. 核…...
嘉立创EDA成图:文件管理
在 工程 文 件夹 中 新建 一 个以 自 己选 手 编号 后 8 位 命名 的 项目 工 程文 件 按要求名字命名(这里以日期命名) 选择半离线或者全离线 添加路径 1. 新建 图 纸文 件 ,文 件 名为 moban.elibz; 点击保存之后打开文件夹有这…...
Vim编辑器命令模式操作指南
Vim 的命令模式(即 Normal 模式)是 Vim 的核心操作模式,用于执行文本编辑、导航、搜索、保存等操作。以下是命令模式下的常用操作总结: 1. 模式切换 进入命令模式:在任何模式下按 Esc 键(可能需要多次按&a…...
jvm安全点(一)openjdk17 c++源码垃圾回收安全点信号函数处理线程阻塞
1. 信号处理入口 JVM_HANDLE_XXX_SIGNAL 是 JVM 处理信号的统一入口,负责处理 SIGSEGV、SIGBUS 等信号。javaSignalHandler 是实际注册到操作系统的信号处理函数,直接调用 JVM_HANDLE_XXX_SIGNAL。 2. 安全点轮询页的识别 …...
手机打电话时由对方DTMF响应切换多级IVR语音应答(二)
手机打电话时由对方DTMF响应切换多级IVR语音应答(二) --本地AI电话机器人 一、前言 前面的篇章《手机打电话时由对方DTMF响应切换多级IVR语音应答(一)》中,我们从理论的角度论述了“根据对方按下DTMF值响应多级IVR”…...
【Java ee初阶】HTTP(2)
一、HTTP的方法 方法 说明 支持的HTTP协议版本 GET 获取资源 1.0、1.1 POST 传输实体主体 1.0、1.1 PUT 传输文件 1.0、1.1 HEAD 获得报文首部 1.0、1.1 DELETE 删除文件 1.0、1.1 OPTIONS 询问支持的方法 1.1 TRACE 追踪路径 1.1 CONNECT 要求用隧道…...
计算机视觉与深度学习 | Python实现EMD-SSA-VMD-LSTM-Attention时间序列预测(完整源码和数据)
EMD-SSA-VMD-LSTM-Attention 一、完整代码实现二、代码结构解析三、关键数学公式四、参数调优建议五、性能优化方向六、工业部署建议 以下是用Python实现EMD-SSA-VMD-LSTM-Attention时间序列预测的完整解决方案。该方案结合了四层信号分解技术与注意力增强的深度学习模型&#…...
Java 应用如何实现 HTTPS:加密数据传输的实用指南
Java 应用如何实现 HTTPS:加密数据传输的实用指南 在当今的互联网环境中,数据安全至关重要,HTTPS 作为加密的数据传输协议,为 Java 应用提供了安全通信的保障。本文将深入探讨 Java 应用如何实现 HTTPS,通过详细代码实…...
手机打电话时如何将通话对方的声音在手机上识别成文字
手机打电话时如何将通话对方的声音在手机上识别成文字 --本地AI电话机器人 上一篇:手机打电话时由对方DTMF响应切换多级IVR语音应答(一) 下一篇:手机打电话时由对方DTMF响应切换多级IVR语音应答(二) 一、…...
18.自动化生成知识图谱的多维度质量评估方法论
文章目录 一、结构维度评估1.1 拓扑结构评估1.1.1 基础图论指标1.1.2 层级结构指标 1.2 逻辑一致性评估1.2.1 形式逻辑验证1.2.2 约束满足度 二、语义维度评估2.1 语义一致性评估2.1.1 标签语义分析2.1.2 关系语义评估 2.2 语义表示质量2.2.1 嵌入质量2.2.2 上下文语义评估 三、…...
W5500使用ioLibrary库创建TCP客户端
1、WIZnet全硬件TCP/IP协议栈 WIZnet全硬件TCP/IP协议栈,支持TCP,UDP,IPv4,ICMP,ARP,IGMP以及PPPoE协议。 以太网:支持BSD和WIZCHIP(W5500/W5300/W5200/W5100/W5100S)的SOCKET APIs驱动程序。 互联网: DHCP客户端 DNS客户端 FTP客…...
2025B难题练习
1.启动多任务排序 拓扑排序 每次选入度为0的点 对每次选的点进行排序 package mainimport ("bufio""fmt""os""slices""strings" )func main() {scanner : bufio.NewScanner(os.Stdin)scanner.Scan()text : scanner.Text()…...
20250517让NanoPi NEO core开发板在Ubuntu core16.04.2下支持TF卡的热插拔
20250517让NanoPi NEO core开发板在Ubuntu core16.04.2下支持TF卡的热插拔 2025/5/17 17:52 缘起:实测NanoPi NEO core开发板上电之后,后插入的TF卡不认/不支持热插拔。 Ubuntu core16.04.2 Ubuntu core20.04 Ubuntu core16.04.3 用NanoPi NEO core开发板…...
Vue百日学习计划Day19-20天详细计划-Gemini版
重要提示: 番茄时钟: 每个番茄钟为25分钟学习,之后休息5分钟。每完成4个番茄钟,进行一次15-30分钟的长休息。动手实践: DevTools 的使用和 Git 命令的掌握都需要大量的实际操作。请务必边学边练。环境准备:…...
Uniapp、Flutter 和 React Native 全面对比
文章目录 前言Uni-app、Flutter 和 React Native 跨平台框架对比报告1. 性能对比2. 跨平台能力3. 学习曲线4. 社区生态与第三方库5. 原生能力扩展6. UI 渲染能力7. 企业支持与典型使用场景8. 开发效率与工具链 前言 将对 Uniapp、Flutter 和 React Native 进行全面对比&#x…...
【Linux笔记】——线程互斥与互斥锁的封装
🔥个人主页🔥:孤寂大仙V 🌈收录专栏🌈:Linux 🌹往期回顾🌹:【Linux笔记】——Linux线程封装 🔖流水不争,争的是滔滔不息 一、线程互斥的概念二、互…...
Linux面试题集合(4)
现有压缩文件:a.tar.gz存在于etc目录,如何解压到data目录 tar -zxvf /etc/a.tar.gz -C /data 给admin.txt创建一个软链接 ln -s admin.txt adminl 查找etc目录下以vilinux开头的文件 find /etc -name vilinux* 查找admin目录下以test开头的文件 find admin -name te…...
Java二叉树题目练习
Java二叉题目练习 相同的树对称二叉树平衡二叉树二叉树的最近公共祖先二叉树的层序遍历二叉树层序遍历 ||二叉树遍历 相同的树 二叉树的题目大多数时候就可以采用递归的方法写 因为二叉树是由根左子树和右子树组成,每一棵左子树和右子树又可以被看成一颗完整的树&am…...
WORD个人简历单页326款模版分享下载
WORD个人简历模版下载:WORD个人简历模版https://pan.quark.cn/s/7e79a822c490...
Linux容器技术详解
容器技术基础 什么是容器 容器是一种轻量级的虚拟化技术,它将应用程序及其依赖(库、二进制文件、配置文件等)打包在一个独立的单元中,可以在任何支持容器运行时的环境中一致地运行。 Docker官网:https://www.docker…...
显卡、Cuda和pytorch兼容问题
这里写目录标题 驱动与CUDA版本兼容性问题1. **驱动与CUDA版本兼容性问题**2. **任务特性与硬件适配差异**3. **优化策略与框架配置差异**4. **散热与功耗限制**5. **数据传输与CPU瓶颈**排查建议总结 查询PyTorch中实际使用的CUDA版本**1. 查询PyTorch中实际使用的CUDA版本***…...
仅需三张照片即可生成沉浸式3D购物体验?谷歌电商3D方案全解析
随着消费者对线上购物体验的要求不断提高,传统2D图片已难以满足用户“真实感知商品”的需求。尤其在鞋类、家具、服装等高决策成本的商品上,缺乏空间感和交互性的购物方式成为转化率瓶颈。 谷歌敏锐地捕捉到这一趋势,早在2022年起便开始探索通过生成式AI技术实现“低成本、…...
PIC16F877A LCD1602 DHT11 温湿度读取显示代码 MPLAB
#include <xc.h> #include <stdio.h> #include <stdlib.h> #...
PIC16F18877 的主时钟 设置方法
#include <xc.h>// ========== 配置位设置 ========== // #pragma config FEXTOSC = OFF // 使用内部振荡器 #pragma...