js逆向实战(1)-- 某☁️音乐下载
下载某云音乐源文件.mp4格式

首先随便点进一首歌,如图所示获取该音乐id,然后点击播放键,打开F12进行查询XHR



由此可知,实际请求网址是
https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token=「你的token」url需带上token,请求参数有两个:params、encSecKey返回json里的id就是该音乐id,url就是本次的目标音乐源文件链接
继续查看启动器,查看该路由的调用堆栈信息,找到关键位置打断点,不会找断点的就每个堆栈全部点进去设置断点,然后看哪一个断点结束后url已完成请求的就是关键位置,从下图的文件中可知,核心文件是core_xxxxx.js,可以直接下载到本地方便查看代码。(堆栈执行顺序是由下至上)


第一步,已成功定位到请求路由,e7d.data里已经带有(params、encSecKey),后续就直接会请求了,那么就继续向上一个堆栈找此函数的参数(x7q,e7d)中的e7d是从哪里传的。
PS:请注意,一定要找到我们要找的核心url是否由此断点发出的,由于一些方法会被反复调用,参数值是不一定的。
第二步,上图已封装好了e7d,且参数params、encSecKey已出现,是由window.asrsea产生的,继续查找window.asrsea是哪个方法。
window.asrsea(JSON.stringify(i7b), bsc2x(["流泪", "强"]), bsc2x(RU7N.md), bsc2x(["爱心", "女孩", "惊恐", "大笑"]));
鼠标悬浮该方法后定位至这里,核心就是这个function d,接受4个参数,分别对应上面的4个值。
其中第一个参数i7b是以下参数构成music_id = XXXXXX
song_data = {"ids": f"[{music_id}]","level": "standard","encodeType": "aac","csrf_token": csrf_token
}第三个参数md是一个固定列表,第二、第四个参数也是一个短列表值。


核心方法已找到,就是function d(),剩下的工作就是把d方法里需要涉及到的所有function全部找出来,比如function b、c,然后继续从b、c里继续递归找方法,这一步工作比较繁琐需要耐心。直至自己用js能把function d给跑通就算成功。
通过js里的方法可知,里面算法还涉及到了加密,需要用到crypto-js库,上网百度搜一下直接下载该库的代码保存本地。

以下是js文件代码:
var CryptoJS = require('./package/crypto-js.js');var bd7W = {};var maxDigits,ZERO_ARRAY,bigZero,bigOne,dpl10,lr10,hexatrigesimalToChar,hexToChar,highBitMasks,lowBitMasks,biRadixBase = 2,biRadixBits = 16,bitsPerDigit = biRadixBits,biRadix = 65536,biHalfRadix = biRadix >>> 1,biRadixSquared = biRadix * biRadix,maxDigitVal = biRadix - 1,maxInteger = 9999999999999998;setMaxDigits(20),dpl10 = 15,lr10 = biFromNumber(1e15),hexatrigesimalToChar = new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"),hexToChar = new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"),highBitMasks = new Array(0, 32768, 49152, 57344, 61440, 63488, 64512, 65024, 65280, 65408, 65472, 65504, 65520, 65528, 65532, 65534, 65535),lowBitMasks = new Array(0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535);function encryptedString(a, b) {for (var f, g, h, i, j, k, l, c = new Array, d = b.length, e = 0; d > e;)c[e] = b.charCodeAt(e),e++;for (; 0 != c.length % a.chunkSize;)c[e++] = 0;for (f = c.length, g = "", e = 0; f > e; e += a.chunkSize) {for (j = new BigInt, h = 0, i = e; i < e + a.chunkSize; ++h)j.digits[h] = c[i++],j.digits[h] += c[i++] << 8;k = a.barrett.powMod(j, a.e),l = 16 == a.radix ? biToHex(k) : biToString(k, a.radix),g += l + " "}return g.substring(0, g.length - 1)
}function biSubtract(a, b) {var c,d,e,f;if (a.isNeg != b.isNeg)b.isNeg = !b.isNeg,c = biAdd(a, b),b.isNeg = !b.isNeg;else {for (c = new BigInt, e = 0, f = 0; f < a.digits.length; ++f)d = a.digits[f] - b.digits[f] + e,c.digits[f] = 65535 & d,c.digits[f] < 0 && (c.digits[f] += biRadix),e = 0 - Number(0 > d);if (-1 == e) {for (e = 0, f = 0; f < a.digits.length; ++f)d = 0 - c.digits[f] + e,c.digits[f] = 65535 & d,c.digits[f] < 0 && (c.digits[f] += biRadix),e = 0 - Number(0 > d);c.isNeg = !a.isNeg} elsec.isNeg = a.isNeg}return c
}function biCompare(a, b) {if (a.isNeg != b.isNeg)return 1 - 2 * Number(a.isNeg);for (var c = a.digits.length - 1; c >= 0; --c)if (a.digits[c] != b.digits[c])return a.isNeg ? 1 - 2 * Number(a.digits[c] > b.digits[c]) : 1 - 2 * Number(a.digits[c] < b.digits[c]);return 0}function biMultiplyByRadixPower(a, b) {var c = new BigInt;return arrayCopy(a.digits, 0, c.digits, b, c.digits.length - b), c}function arrayCopy(a, b, c, d, e) {var g,h,f = Math.min(b + e, a.length);for (g = b, h = d; f > g; ++g, ++h)c[h] = a[g]}function biShiftLeft(a, b) {var e,f,g,h,c = Math.floor(b / bitsPerDigit),d = new BigInt;for (arrayCopy(a.digits, 0, d.digits, c, d.digits.length - c), e = b % bitsPerDigit, f = bitsPerDigit - e, g = d.digits.length - 1, h = g - 1; g > 0; --g, --h)d.digits[g] = d.digits[g] << e & maxDigitVal | (d.digits[h] & highBitMasks[e]) >>> f;return d.digits[0] = d.digits[g] << e & maxDigitVal, d.isNeg = a.isNeg, d}function biFromNumber(a) {var c,b = new BigInt;for (b.isNeg = 0 > a, a = Math.abs(a), c = 0; a > 0;)b.digits[c++] = a & maxDigitVal,a >>= biRadixBits;return b}function biNumBits(a) {var e,b = biHighIndex(a),c = a.digits[b],d = (b + 1) * bitsPerDigit;for (e = d; e > d - bitsPerDigit && 0 == (32768 & c); --e)c <<= 1;return e}function biDivideModulo(a, b) {var f,g,h,i,j,k,l,m,n,o,p,q,r,s,c = biNumBits(a),d = biNumBits(b),e = b.isNeg;if (d > c)return a.isNeg ? (f = biCopy(bigOne), f.isNeg = !b.isNeg, a.isNeg = !1, b.isNeg = !1, g = biSubtract(b, a), a.isNeg = !0, b.isNeg = e) : (f = new BigInt, g = biCopy(a)), new Array(f, g);for (f = new BigInt, g = a, h = Math.ceil(d / bitsPerDigit) - 1, i = 0; b.digits[h] < biHalfRadix;)b = biShiftLeft(b, 1),++i,++d,h = Math.ceil(d / bitsPerDigit) - 1;for (g = biShiftLeft(g, i), c += i, j = Math.ceil(c / bitsPerDigit) - 1, k = biMultiplyByRadixPower(b, j - h); -1 != biCompare(g, k);)++f.digits[j - h],g = biSubtract(g, k);for (l = j; l > h; --l) {for (m = l >= g.digits.length ? 0 : g.digits[l], n = l - 1 >= g.digits.length ? 0 : g.digits[l - 1], o = l - 2 >= g.digits.length ? 0 : g.digits[l - 2], p = h >= b.digits.length ? 0 : b.digits[h], q = h - 1 >= b.digits.length ? 0 : b.digits[h - 1], f.digits[l - h - 1] = m == p ? maxDigitVal : Math.floor((m * biRadix + n) / p), r = f.digits[l - h - 1] * (p * biRadix + q), s = m * biRadixSquared + (n * biRadix + o); r > s;)--f.digits[l - h - 1],r = f.digits[l - h - 1] * (p * biRadix | q),s = m * biRadix * biRadix + (n * biRadix + o);k = biMultiplyByRadixPower(b, l - h - 1),g = biSubtract(g, biMultiplyDigit(k, f.digits[l - h - 1])),g.isNeg && (g = biAdd(g, k), --f.digits[l - h - 1])}return g = biShiftRight(g, i), f.isNeg = a.isNeg != e, a.isNeg && (f = e ? biAdd(f, bigOne) : biSubtract(f, bigOne), b = biShiftRight(b, i), g = biSubtract(b, g)), 0 == g.digits[0] && 0 == biHighIndex(g) && (g.isNeg = !1), new Array(f, g)}function BarrettMu_modulo(a) {var i,b = biDivideByRadixPower(a, this.k - 1),c = biMultiply(b, this.mu),d = biDivideByRadixPower(c, this.k + 1),e = biModuloByRadixPower(a, this.k + 1),f = biMultiply(d, this.modulus),g = biModuloByRadixPower(f, this.k + 1),h = biSubtract(e, g);for (h.isNeg && (h = biAdd(h, this.bkplus1)), i = biCompare(h, this.modulus) >= 0; i;)h = biSubtract(h, this.modulus),i = biCompare(h, this.modulus) >= 0;return h}function BarrettMu_multiplyMod(a, b) {var c = biMultiply(a, b);return this.modulo(c)}function biDivideByRadixPower(a, b) {var c = new BigInt;return arrayCopy(a.digits, b, c.digits, 0, c.digits.length - b), c}function reverseStr(a) {var c,b = "";for (c = a.length - 1; c > -1; --c)b += a.charAt(c);return b}function digitToHex(a) {var b = 15,c = "";for (i = 0; 4 > i; ++i)c += hexToChar[a & b],a >>>= 4;return reverseStr(c)}function biToHex(a) {var d,b = "";for (biHighIndex(a), d = biHighIndex(a); d > -1; --d)b += digitToHex(a.digits[d]);return b}function biModuloByRadixPower(a, b) {var c = new BigInt;return arrayCopy(a.digits, 0, c.digits, 0, b), c}function biCompare(a, b) {if (a.isNeg != b.isNeg)return 1 - 2 * Number(a.isNeg);for (var c = a.digits.length - 1; c >= 0; --c)if (a.digits[c] != b.digits[c])return a.isNeg ? 1 - 2 * Number(a.digits[c] > b.digits[c]) : 1 - 2 * Number(a.digits[c] < b.digits[c]);return 0}function biMultiply(a, b) {var d,h,i,k,c = new BigInt,e = biHighIndex(a),f = biHighIndex(b);for (k = 0; f >= k; ++k) {for (d = 0, i = k, j = 0; e >= j; ++j, ++i)h = c.digits[i] + a.digits[j] * b.digits[k] + d,c.digits[i] = h & maxDigitVal,d = h >>> biRadixBits;c.digits[k + e + 1] = d}return c.isNeg = a.isNeg != b.isNeg, c}function BarrettMu_powMod(a, b) {var d,e,c = new BigInt;for (c.digits[0] = 1, d = a, e = b;;) {if (0 != (1 & e.digits[0]) && (c = this.multiplyMod(c, d)), e = biShiftRight(e, 1), 0 == e.digits[0] && 0 == biHighIndex(e))break;d = this.multiplyMod(d, d)}return c}function biShiftRight(a, b) {var e,f,g,h,c = Math.floor(b / bitsPerDigit),d = new BigInt;for (arrayCopy(a.digits, c, d.digits, 0, a.digits.length - c), e = b % bitsPerDigit, f = bitsPerDigit - e, g = 0, h = g + 1; g < d.digits.length - 1; ++g, ++h)d.digits[g] = d.digits[g] >>> e | (d.digits[h] & lowBitMasks[e]) << f;return d.digits[d.digits.length - 1] >>>= e, d.isNeg = a.isNeg, d}function biMultiplyDigit(a, b) {var c,d,e,f;for (result = new BigInt, c = biHighIndex(a), d = 0, f = 0; c >= f; ++f)e = result.digits[f] + a.digits[f] * b + d,result.digits[f] = e & maxDigitVal,d = e >>> biRadixBits;return result.digits[1 + c] = d, result}function biDivide(a, b) {return biDivideModulo(a, b)[0]}function biCopy(a) {var b = new BigInt(!0);return b.digits = a.digits.slice(0), b.isNeg = a.isNeg, b}function BarrettMu(a) {this.modulus = biCopy(a),this.k = biHighIndex(this.modulus) + 1;var b = new BigInt;b.digits[2 * this.k] = 1,this.mu = biDivide(b, this.modulus),this.bkplus1 = new BigInt,this.bkplus1.digits[this.k + 1] = 1,this.modulo = BarrettMu_modulo,this.multiplyMod = BarrettMu_multiplyMod,this.powMod = BarrettMu_powMod}function BigInt(a) {this.digits = "boolean" == typeof a && 1 == a ? null : ZERO_ARRAY.slice(0),this.isNeg = !1}function charToHex(a) {var h,b = 48,c = b + 9,d = 97,e = d + 25,f = 65,g = 90;return h = a >= b && c >= a ? a - b : a >= f && g >= a ? 10 + a - f : a >= d && e >= a ? 10 + a - d : 0}function hexToDigit(a) {var d,b = 0,c = Math.min(a.length, 4);for (d = 0; c > d; ++d)b <<= 4,b |= charToHex(a.charCodeAt(d));return b
}function biFromHex(a) {var d,e,b = new BigInt,c = a.length;for (d = c, e = 0; d > 0; d -= 4, ++e)b.digits[e] = hexToDigit(a.substr(Math.max(d - 4, 0), Math.min(d, 4)));return b}function RSAKeyPair(a, b, c) {this.e = biFromHex(a),this.d = biFromHex(b),this.m = biFromHex(c),this.chunkSize = 2 * biHighIndex(this.m),this.radix = 16,this.barrett = new BarrettMu(this.m)}function biHighIndex(a) {for (var b = a.digits.length - 1; b > 0 && 0 == a.digits[b];)--b;return b}function setMaxDigits(a) {maxDigits = a,ZERO_ARRAY = new Array(maxDigits);for (var b = 0; b < ZERO_ARRAY.length; b++)ZERO_ARRAY[b] = 0;bigZero = new BigInt,bigOne = new BigInt,bigOne.digits[0] = 1}var Hb6V = function(i7b, u7n) {try {u7n = u7n.toLowerCase();if (i7b === null)return u7n == "null";if (i7b === undefined)return u7n == "undefined";return bd7W.toString.call(i7b).toLowerCase() == "[object " + u7n + "]"} catch (e) {console.log(e)return !1}};var md = ["色", "流感", "这边", "弱", "嘴唇", "亲", "开心", "呲牙", "憨笑", "猫", "皱眉", "幽灵", "蛋糕", "发怒", "大哭", "兔子", "星星", "钟情", "牵手", "公鸡", "爱意", "禁止", "狗", "亲亲", "叉", "礼物", "晕", "呆", "生病", "钻石", "拜", "怒", "示爱", "汗", "小鸡", "痛苦", "撇嘴", "惶恐", "口罩", "吐舌", "心碎", "生气", "可爱", "鬼脸", "跳舞", "男孩", "奸笑", "猪", "圈", "便便", "外星", "圣诞"]var emj = {"色": "00e0b","流感": "509f6","这边": "259df","弱": "8642d","嘴唇": "bc356","亲": "62901","开心": "477df","呲牙": "22677","憨笑": "ec152","猫": "b5ff6","皱眉": "8ace6","幽灵": "15bb7","蛋糕": "b7251","发怒": "52b3a","大哭": "b17a8","兔子": "76aea","星星": "8a5aa","钟情": "76d2e","牵手": "41762","公鸡": "9ec4e","爱意": "e341f","禁止": "56135","狗": "fccf6","亲亲": "95280","叉": "104e0","礼物": "312ec","晕": "bda92","呆": "557c9","生病": "38701","钻石": "14af6","拜": "c9d05","怒": "c4f7f","示爱": "0c368","汗": "5b7a4","小鸡": "6bee2","痛苦": "55932","撇嘴": "575cc","惶恐": "e10b4","口罩": "24d81","吐舌": "3cfe4","心碎": "875d3","生气": "e8204","可爱": "7b97d","鬼脸": "def52","跳舞": "741d5","男孩": "46b8e","奸笑": "289dc","猪": "6935b","圈": "3ece0","便便": "462db","外星": "0a22b","圣诞": "8e7","流泪": "01000","强": "1","爱心": "0CoJU","女孩": "m6Qyw","惊恐": "8W8ju","大笑": "d"}var gO9F = function(i7b) {return Hb6V(i7b, "function")}var bh7a = function(k7d, cH8z, O7H) {if (!k7d || !k7d.length || !gO9F(cH8z))return this;if (!!k7d.forEach) {k7d.forEach(cH8z, O7H);return this}for (var i = 0, l = k7d.length; i < l; i++)cH8z.call(O7H, k7d[i], i, k7d);return this}var bsc2x = function(cya8S) {var m7f = [];bh7a(cya8S, function(cxZ8R) {m7f.push(emj[cxZ8R])});return m7f.join("")};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 decrypt(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}function get_efg(){var r = {}r.e = bsc2x(["流泪", "强"])r.f = bsc2x(md)r.g = bsc2x(["爱心", "女孩", "惊恐", "大笑"])return r}
以下是python部分代码,由于要用到js,需要用到execjs库,自行百度pip install。
import traceback
import json
import requests
import execjswith open("wangyiyun.js") as f:jscode = f.read()
js = execjs.compile(jscode)csrf_token = "your_token"
url = f"https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token={csrf_token}"headers = {"Accept": "*/*","Host": "music.163.com","Accept-Language": "zh-CN,zh-Hans;q=0.9","Content-Type": "application/x-www-form-urlencoded","Accept-Encoding": "gzip, deflate, br","User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.2 Safari/605.1.15","Referer": "https://music.163.com/","Connection": "keep-alive","Cookie": "ntes_kaola_ad=1; JSESSIONID-WYYY=NNam6ZvnitTQAIxhjcnkVGOJe1CSrnqIOsBnuOzx405%2FJAUSng5IDkYIFo00Xb%2BoUldg8unn3ikRohd8TEg%2F5A9IF0d3vIrPq0ggue%2BD%2FCFTwZBaj%2FfbHOgwt15v2R4uXH8%2FJuMri%2F3zPb%2Bl7TH%2B4XFVYq9BghtkAelO6p5uAC4QQxNh%3A1735613258319; _iuqxldmzr_=32; playerid=96541318; WEVNSM=1.0.0; WM_TID=%2FnYekZpayJFEEEVQRRfHMEPNaHmTqyHZ; MUSIC_U=006C5AF78BF74B16F27E5B57A85731911569EB8ABB9380E9315B54803127FFDF3C459640CCB0E2BDE8425D2EE33764BC1DB30AA186B850E1CED2B79EF2436E56F8786A63776BFC2243956C5AC987B3A85797BC545993FB84F14E3C4C66EF506A087542A5DE0B218EEA044FDCED41F7037A2EA93679113D60D72EAD7603A7B74BAF1EA4753BF65B585F5130F58CC7711D5EB79F559AD803761591C3D9AB83F967DDFA019B5C6C58BB126197139D1D4BB311DED63FECC8F6651349C211AEE6BB2A772FFCB717C731082DE27A19C5F24FB6A3311D4B585E8FA92DF7D35A41F4FCCA7129B921D0ABA174034FCDB36CAE4BB69011E30F7A7A657B1D74C7DCE0CCEB7B01E6F34CE848E3627CAF9D536C3255A80CF5B8064216064E40C7AD67CDF74EC118D8F2D4B6D4A0031A2969ABF5BB2FC4CFDE6E679AA4CB5609C96901D706E9500E94B86D80E4A6A3065227ED8690F5686FF885DC3BB6F1DA7467CEB7D4D42A10B4; __csrf=ca6ddf56d40cc8a27f331f202fe4b326; gdxidpyhxdE=4xfjyEeg4lc3N%5Ch2d%5Cmuya67isI3pZMPzyE5piBKE4MbnmjX8cO%2BUPnScJ7ZVrK8%2FyENi%2FPm%2FUJ%5C7Jt7%2Fu%5CxVq0KD8x%2Bs2uyBrRX6bcW9sjSWg%5Cw%2F7KNEkKk%5C6Mn6dM0bzaQBt%2F06wgBdKtOe3TuWkbDmcE6EvqXOdSnvvjBjs44kdz0%3A1735610638700; __snaker__id=1FPbd4ulJdEVbVUp; ntes_utid=tid._.m%252BLT1NjmAjZAUkFUAAaSMBOdaWzOWutc._.0; sDeviceId=YD-YPiVIvIe3u5EAxABBUfFxyhoxuMxXPie; WNMCID=scyqtk.1735609723331.01.0; WM_NI=AvJ1%2BaTN%2Bars6kp4BqZR6lew0ErnCxDEjplQcna1dpw2o38u%2BYsJZfwf7oZZx3RYpR1b0M2XDa5vbBs0LlSAcWKBQpCU5WBUbXnW%2BM%2BjOjngWravnIJ5CDCtziN4QsN0MW8%3D; WM_NIKE=9ca17ae2e6ffcda170e2e6eea6fb4089be9ab8f74483eb8ab3c55f928f8e83d769869482b1c73985abb6a5e72af0fea7c3b92a83aa86d2aa6b9892e582f179f6b5c0d5c17b9a8efa8de87df49bbe8fc274889ba691ef5ba1b2afd2e77cb5eea1d4bb7fe987bdabd96eb5baf990d952bced9ebaf35af3be00aeb15488bffb97e14ab1f0848dd24ba18985a3d47c818bfbb8c15fa288a2b8aa47e9b6818bed6d95aeaf97ed438aeb8da5c280bab782d5d4798ef083b8bb37e2a3; _ntes_nnid=0abb01037659f4b4a2020921c96bcfd4,1735609718336; _ntes_nuid=0abb01037659f4b4a2020921c96bcfd4; NMTID=00Ob7X1eXe08UIQIk_Bl7cELz7aKHkAAAGQCjtDIA",
}# 音乐id
music_id = 2122122972
song_data = {"ids": f"[{music_id}]","level": "standard","encodeType": "aac","csrf_token": csrf_token
}# 获取js运行的结果
try:efg_obj = js.call("get_efg")res = js.call("decrypt", *(json.dumps(song_data), efg_obj["e"], efg_obj["f"], efg_obj["g"]))
except:print(traceback.format_exc())data = {"params": res["encText"],"encSecKey": res["encSecKey"],
}resp = requests.post(url, headers=headers, data=data)print(resp.status_code)
print(resp.text)music = requests.get(url=resp.json()["data"][0]["url"])
with open(f"{music_id}.m4a", "wb") as f:f.write(music.content)相关文章:
js逆向实战(1)-- 某☁️音乐下载
下载某云音乐源文件.mp4格式 首先随便点进一首歌,如图所示获取该音乐id,然后点击播放键,打开F12进行查询XHR 由此可知,实际请求网址是 https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token「你的token」url需带…...
AIA - APLIC之三(附APLIC处理流程图)
本文属于《 RISC-V指令集基础系列教程》之一,欢迎查看其它文章。 1 APLIC复位 APLIC复位后,其所有状态都变得有效且一致,但以下情况除外: 每个中断域的domaincfg寄存器(spec第 4.5.1 节);可能是machine-level interrupt domain的MSI地址配置寄存器(spec第4.5.3 和4.5…...
React Router 向路由组件传state参数浏览器回退历史页面显示效果问题
昨天在看尚硅谷张天禹老师讲的 React教程p90,老师讲到 React路由的 replace模式和push模式,老师的演示效果与自己本地操作不太一样。 老师的效果:点击查看消息1,消息2,消息3 再点回退,可以依次查看到 消息…...
线程池与并发工具:Java的分身管理器
1 线程池的概念 线程池是一种执行器(Executor),用于在一个后台线程中执行任务。线程池的主要目的是减少在创建和销毁线程时所产生的性能开销。通过重用已经创建的线程来执行新的任务,线程池提高了程序的响应速度,并且提…...
字玩FontPlayer开发笔记8 Tauri2文件系统
字玩FontPlayer开发笔记8 Tauri2文件系统 字玩FontPlayer是笔者开源的一款字体设计工具,使用Vue3 ElementUI开发,源代码: github: https://github.com/HiToysMaker/fontplayer gitee: https://gitee.com/toysmaker/fontplayer 笔记 字玩目…...
头歌python实验:网络安全应用实践3-验证码识别
第1关:简单的验证码识别 本关任务:编写一个能简单识别验证码的小程序。 为了完成本关任务,你需要掌握: 使用 pytesseract 库与 PIL 库解析图片;环境配置;读取图片文本信息。使用 pytesseract 库与 PIL 库解析图片 pytesseract 库可以从图像中提取文本。Tesseract 是一…...
客户案例:基于慧集通(DataLinkX)集成平台的金蝶云星空与HIS系统集成案例--凭证模板的配置(一)
当前的原型客户是一家医院,财务系统使用的是金蝶云星空,需要与医院专用的HIS系统进行集成。本文档主要是介绍其中的凭证模板的配置功能。 凭证模板组件旨在生成凭证前,通过内部整理整合原始单据数据,将其转化为可生成一张凭证的数…...
基于 Python 的大学教室资源管理系统的设计与实现
标题:基于 Python 的大学教室资源管理系统的设计与实现 内容:1.摘要 摘要:随着高校教育的不断发展,教室资源的管理变得越来越重要。为了提高教室资源的利用率,本文设计并实现了一个基于 Python 的大学教室资源管理系统。该系统采用了 B/S 架…...
nginx-灰度发布策略(split_clients)
一. 简述: 基于客户端的灰度发布(也称为蓝绿部署或金丝雀发布)是一种逐步将新版本的服务或应用暴露给部分用户,以确保在出现问题时可以快速回滚并最小化影响的技术。对于 Nginx,可以通过配置和使用不同的模块来实现基于…...
nginx正向代理从安装到使用一网打尽系列(二)使用
一、背景 使用场景大总结,可作为参考手册用 nginx正向代理从安装到使用一网打尽系列(一)安装 nginx正向代理从安装到使用一网打尽系列(二)使用 二、使用场景 1、所有内网应用都不能直接访问外网,但需要…...
Bash Shell的操作环境
目录 1、路径与指令搜寻顺序 2、bash的进站(开机)与欢迎信息:/etc/issue,/etc/motd (1)/etc/issue (2)/etc/motd 3、bash的环境配置文件 (1)login与non-…...
Python爬虫基础——认识网页结构(各种标签的使用)
1、添加<div>标签的代码定义了两个区块的宽度和高度均为100px,边框的格式也相同,只是区块中显示的内容不同; 2、添加<ul>和<ol>标签分别用于定义无序列表和有序列表。<il>标签位于<ul>标签或<ol>标签之…...
如何实现一个充满科技感的官网(二)
背景 在上一篇文章 《如何实现一个充满科技感的官网(一)》 中,我们初步了解了该官网的整体设计,并与大家探讨了它的视觉呈现和用户体验。 我们前期的内部设计偏向简洁,所以开始思考如何提升网站的整体设计感。这些尝…...
GNU链接器简介
GNU链接器简介 1 使用简单程序简介链接脚本1.1 测试程序1.2 编译测试程序1.2.1 不使用链接器编译1.2.1.1 不使用链接器编译1.2.1.2 读取objdump_test 的结构 1.2.2 使用链接器去链接1.2.2.1 链接脚本1.2.2.2 使用链接脚本编译1.2.2.3 读取objdump 的结构 2 链接脚本2.1 基本连接…...
欧几里得算法(简单理解版,非严格证明)
欧几里得算法用于求解两个整数的最大公约数,又称为辗转相除 依据的基本定理: GCD(a,b)GCD(a%b,b) 证明: 对于搞理论的人可能需要会严格证明,但是对于我们一般人而言,只要能理解其原理并记住即可,后者实际上…...
Mac软件介绍之录屏软件Filmage Screen
软件介绍 Filmage Screen 是一款专业的视频录制和编辑软件,适用于 Mac 系统 可以选择4k 60fps,可以选择录制电脑屏幕,摄像头录制,可以选择区域录制。同时也支持,简单的视频剪辑。 可以同时录制电脑麦克风声音 标准…...
Ubuntu cuda-cudnn中断安装如何卸载
文章目录 问题描述解决方法使用强制移除 问题描述 Ubuntu22.04系统,在终端中执行apt insatll安装或dpkg .deb安装时如果强制关闭终端会导致安装失败(安装包会变成iu状态或ru状态,安装成功的应该是ii状态) 此时,无论是…...
CSS——7.CSS注释
<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>css注释</title><link rel"stylesheet" type"text/css" href"a.css"/></head><body><!--头部开始(h…...
鸿蒙APP之从开发到发布的一点心得
引言: 做鸿蒙开发大概有1年左右时间了,从最开始的看官方文档、看B站视频,到后来成功发布两款个人APP(房贷计算极简版、时简时钟 轻喷,谢谢)。简单描述一下里边遇到的坑以及一些经历吧。 学习鸿蒙开发 个…...
某小程序sign签名参数逆向分析
文章目录 1. 写在前面2. 接口分析3. 分析还原 【🏠作者主页】:吴秋霖 【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
