Web Spider XHR断点 千千XX 歌曲下载(三)

news2024/11/24 7:47:28

Web Spider XHR断点 千千XX 歌曲下载


首先声明: 此次案例只为学习交流使用,切勿用于其他非法用途
注:网站url、接口url请使用base64.b64decode自行解码

文章目录

  • Web Spider XHR断点 千千XX 歌曲下载
  • 前言
  • 一、资源推荐
  • 二、任务说明
  • 三、网站分析
  • 四、XHR断点调试,使用WT-JS还原JS加密代码
  • 五、代码实现
    • 1、JS加密代码:encode.js
    • 2、execjs模块调用JS代码
    • 3、python代码
  • 六、Pip模块安装
  • 总结


前言

目标网站地址:aHR0cHM6Ly9tdXNpYy45MXEuY29tLw==
在这里插入图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、资源推荐

JS逆向加密解密工具 下载使用:https://blog.csdn.net/EXIxiaozhou/article/details/128034062

二、任务说明

1、输入歌手名,歌曲名等关键词,可以检索相关的信息;
2、输入该平台的歌曲ID,即可完成歌曲的下载;
在这里插入图片描述
最终结果
在这里插入图片描述

三、网站分析

实现思路

  • 1、通过关键词检索,拿到歌曲信息;
  • 2、通过歌曲ID请求某接口,拿到歌曲的播放链接;
  • 3、通过歌曲的播放链接进行歌曲下载;

1、打开网站,首页搜索框输入关键词,按回车键,可以发现数据就在网页中,替换搜索关键词即可;

关键词检索歌曲信息url:aHR0cHM6Ly9tdXNpYy45MXEuY29tL3NlYXJjaD93b3JkPcfgu6i0yQ==在这里插入图片描述
数据可以直接看到,使用解析模块直接提取想要的数据
在这里插入图片描述
2、分析获取歌曲下载链的XHR接口,来到歌曲播放页面,歌曲的下载链接由下列接口返回的;
获取歌曲下载链的XHR接口url:aHR0cHM6Ly9tdXNpYy45MXEuY29tL3YxL3NvbmcvdHJhY2tsaW5r
在这里插入图片描述
分析请求时提交的参数,是一个GET请求,sign是MD5加密字符串,appid是版本号写死即可,TSID是歌曲ID,timestamp是10位的时间戳
加密的明文数据为下列的字符串,只需更换TSID,timestamp这两个参数即可

f'TSID={TSID歌曲ID}&appid=16073360&timestamp={timestamp时间戳}0b50b02fd0d73a9c4c8c3a781c30845f'

在这里插入图片描述
3、拿到歌曲的下载链接打开就可以直接播放啦
在这里插入图片描述

四、XHR断点调试,使用WT-JS还原JS加密代码

逆向思路

  • 1、通过浏览器,资源面板,添加XHR断点,让其在浏览器请求之前断住,以便我们分析请求参数;
  • 2、通过资源面板下的调用堆栈,进行跟值,找到加密代码处;
  • 3、拿到加密明文后,使用WT-JS还原JS加密代码
  • 4、通过python代码调用JS代码实现整个任务;

1、根据接口的url,下XHR断点,这里以获取歌曲下载链的XHR接口为例;
如果浏览器向该接口发送请求则会在发包前进行断点;
在这里插入图片描述
2、在歌曲播放页面刷新一下页面即可触发XHR断点,可以发现此处的代码参数已经生成,需要通过调用堆栈进行跟值,找到加密代码处,一个一个往下跟,正常流程是每从堆栈切换至一个新的函数,得取消之前的断点,在新函数处重新下断点,刷新操作;
在这里插入图片描述
通过调用堆栈跟值来到此处明文加密函数,在createSign()方法中重新下断点;
注意return处的断点,断前不断后(以避免值出现重复计算),加密的明文就是 r += secret的值;
在这里插入图片描述
3、还原JS加密代码,点击生成JS加密代码,粘贴至pycharm编辑器中调试
在这里插入图片描述
打开pycharm调试JS加密代码
在这里插入图片描述

五、代码实现

1、JS加密代码:encode.js

var CryptoJS = CryptoJS || (function (Math, undefined) {
    var crypto;
    if (typeof window !== 'undefined' && window.crypto) {
        crypto = window.crypto;
    }
    if (typeof self !== 'undefined' && self.crypto) {
        crypto = self.crypto;
    }
    if (typeof globalThis !== 'undefined' && globalThis.crypto) {
        crypto = globalThis.crypto;
    }
    if (!crypto && typeof window !== 'undefined' && window.msCrypto) {
        crypto = window.msCrypto;
    }
    if (!crypto && typeof global !== 'undefined' && global.crypto) {
        crypto = global.crypto;
    }
    if (!crypto && typeof require === 'function') {
        try {
            crypto = require('crypto');
        } catch (err) {}
    }
    var cryptoSecureRandomInt = function () {
        if (crypto) {
            if (typeof crypto.getRandomValues === 'function') {
                try {
                    return crypto.getRandomValues(new Uint32Array(1))[0];
                } catch (err) {}
            }
            if (typeof crypto.randomBytes === 'function') {
                try {
                    return crypto.randomBytes(4).readInt32LE();
                } catch (err) {}
            }
        }
        throw new Error('Native crypto module could not be used to get secure random number.');
    };
    var create = Object.create || (function () {
        function F() {}
        return function (obj) {
            var subtype;
            F.prototype = obj;
            subtype = new F();
            F.prototype = null;
            return subtype;
        };
    }());
    var C = {};
    var C_lib = C.lib = {};
    var Base = C_lib.Base = (function () {
        return {
            extend: function (overrides) {
                var subtype = create(this);
                if (overrides) {
                    subtype.mixIn(overrides);
                }
                if (!subtype.hasOwnProperty('init') || this.init === subtype.init) {
                    subtype.init = function () {
                        subtype.$super.init.apply(this, arguments);
                    };
                }
                subtype.init.prototype = subtype;
                subtype.$super = this;
                return subtype;
            }, create: function () {
                var instance = this.extend();
                instance.init.apply(instance, arguments);
                return instance;
            }, init: function () {}, mixIn: function (properties) {
                for (var propertyName in properties) {
                    if (properties.hasOwnProperty(propertyName)) {
                        this[propertyName] = properties[propertyName];
                    }
                }
                if (properties.hasOwnProperty('toString')) {
                    this.toString = properties.toString;
                }
            }, clone: function () {
                return this.init.prototype.extend(this);
            }
        };
    }());
    var WordArray = C_lib.WordArray = Base.extend({
        init: function (words, sigBytes) {
            words = this.words = words || [];
            if (sigBytes != undefined) {
                this.sigBytes = sigBytes;
            } else {
                this.sigBytes = words.length * 4;
            }
        }, toString: function (encoder) {
            return (encoder || Hex).stringify(this);
        }, concat: function (wordArray) {
            var thisWords = this.words;
            var thatWords = wordArray.words;
            var thisSigBytes = this.sigBytes;
            var thatSigBytes = wordArray.sigBytes;
            this.clamp();
            if (thisSigBytes % 4) {
                for (var i = 0; i < thatSigBytes; i++) {
                    var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
                    thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
                }
            } else {
                for (var j = 0; j < thatSigBytes; j += 4) {
                    thisWords[(thisSigBytes + j) >>> 2] = thatWords[j >>> 2];
                }
            }
            this.sigBytes += thatSigBytes;
            return this;
        }, clamp: function () {
            var words = this.words;
            var sigBytes = this.sigBytes;
            words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
            words.length = Math.ceil(sigBytes / 4);
        }, clone: function () {
            var clone = Base.clone.call(this);
            clone.words = this.words.slice(0);
            return clone;
        }, random: function (nBytes) {
            var words = [];
            var r = (function (m_w) {
                var m_w = m_w;
                var m_z = 0x3ade68b1;
                var mask = 0xffffffff;
                return function () {
                    m_z = (0x9069 * (m_z & 0xFFFF) + (m_z >> 0x10)) & mask;
                    m_w = (0x4650 * (m_w & 0xFFFF) + (m_w >> 0x10)) & mask;
                    var result = ((m_z << 0x10) + m_w) & mask;
                    result /= 0x100000000;
                    result += 0.5;
                    return result * (Math.random() > .5 ? 1 : -1);
                }
            });
            var RANDOM = false, _r;
            try {
                cryptoSecureRandomInt();
                RANDOM = true;
            } catch (err) {}
            for (var i = 0, rcache; i < nBytes; i += 4) {
                if (!RANDOM) {
                    _r = r((rcache || Math.random()) * 0x100000000);
                    rcache = _r() * 0x3ade67b7;
                    words.push((_r() * 0x100000000) | 0);
                    continue;
                }
                words.push(cryptoSecureRandomInt());
            }
            return new WordArray.init(words, nBytes);
        }
    });
    var C_enc = C.enc = {};
    var Hex = C_enc.Hex = {
        stringify: function (wordArray) {
            var words = wordArray.words;
            var sigBytes = wordArray.sigBytes;
            var hexChars = [];
            for (var i = 0; i < sigBytes; i++) {
                var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
                hexChars.push((bite >>> 4).toString(16));
                hexChars.push((bite & 0x0f).toString(16));
            }
            return hexChars.join('');
        }, parse: function (hexStr) {
            var hexStrLength = hexStr.length;
            var words = [];
            for (var i = 0; i < hexStrLength; i += 2) {
                words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
            }
            return new WordArray.init(words, hexStrLength / 2);
        }
    };
    var Latin1 = C_enc.Latin1 = {
        stringify: function (wordArray) {
            var words = wordArray.words;
            var sigBytes = wordArray.sigBytes;
            var latin1Chars = [];
            for (var i = 0; i < sigBytes; i++) {
                var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
                latin1Chars.push(String.fromCharCode(bite));
            }
            return latin1Chars.join('');
        }, parse: function (latin1Str) {
            var latin1StrLength = latin1Str.length;
            var words = [];
            for (var i = 0; i < latin1StrLength; i++) {
                words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
            }
            return new WordArray.init(words, latin1StrLength);
        }
    };
    var Utf8 = C_enc.Utf8 = {
        stringify: function (wordArray) {
            try {
                return decodeURIComponent(escape(Latin1.stringify(wordArray)));
            } catch (e) {
                throw new Error('Malformed UTF-8 data');
            }
        }, parse: function (utf8Str) {
            return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
        }
    };
    var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
        reset: function () {
            this._data = new WordArray.init();
            this._nDataBytes = 0;
        }, _append: function (data) {
            if (typeof data == 'string') {
                data = Utf8.parse(data);
            }
            this._data.concat(data);
            this._nDataBytes += data.sigBytes;
        }, _process: function (doFlush) {
            var processedWords;
            var data = this._data;
            var dataWords = data.words;
            var dataSigBytes = data.sigBytes;
            var blockSize = this.blockSize;
            var blockSizeBytes = blockSize * 4;
            var nBlocksReady = dataSigBytes / blockSizeBytes;
            if (doFlush) {
                nBlocksReady = Math.ceil(nBlocksReady);
            } else {
                nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
            }
            var nWordsReady = nBlocksReady * blockSize;
            var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
            if (nWordsReady) {
                for (var offset = 0; offset < nWordsReady; offset += blockSize) {
                    this._doProcessBlock(dataWords, offset);
                }
                processedWords = dataWords.splice(0, nWordsReady);
                data.sigBytes -= nBytesReady;
            }
            return new WordArray.init(processedWords, nBytesReady);
        }, clone: function () {
            var clone = Base.clone.call(this);
            clone._data = this._data.clone();
            return clone;
        }, _minBufferSize: 0
    });
    var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({
        cfg: Base.extend(),
        init: function (cfg) {
            this.cfg = this.cfg.extend(cfg);
            this.reset();
        }, reset: function () {
            BufferedBlockAlgorithm.reset.call(this);
            this._doReset();
        }, update: function (messageUpdate) {
            this._append(messageUpdate);
            this._process();
            return this;
        }, finalize: function (messageUpdate) {
            if (messageUpdate) {
                this._append(messageUpdate);
            }
            var hash = this._doFinalize();
            return hash;
        }, blockSize: 512 / 32,
        _createHelper: function (hasher) {
            return function (message, cfg) {
                return new hasher.init(cfg).finalize(message);
            };
        }, _createHmacHelper: function (hasher) {
            return function (message, key) {
                return new C_algo.HMAC.init(hasher, key).finalize(message);
            };
        }
    });
    var C_algo = C.algo = {};
    return C;
}(Math));

(function (Math) {
    var C = CryptoJS;
    var C_lib = C.lib;
    var WordArray = C_lib.WordArray;
    var Hasher = C_lib.Hasher;
    var C_algo = C.algo;
    var T = [];
    (function () {
        for (var i = 0; i < 64; i++) {
            T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0;
        }
    }());
    var MD5 = C_algo.MD5 = Hasher.extend({
        _doReset: function () {
            this._hash = new WordArray.init([0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476]);
        }, _doProcessBlock: function (M, offset) {
            for (var i = 0; i < 16; i++) {
                var offset_i = offset + i;
                var M_offset_i = M[offset_i];
                M[offset_i] = ((((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) | (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00));
            }
            var H = this._hash.words;
            var M_offset_0 = M[offset + 0];
            var M_offset_1 = M[offset + 1];
            var M_offset_2 = M[offset + 2];
            var M_offset_3 = M[offset + 3];
            var M_offset_4 = M[offset + 4];
            var M_offset_5 = M[offset + 5];
            var M_offset_6 = M[offset + 6];
            var M_offset_7 = M[offset + 7];
            var M_offset_8 = M[offset + 8];
            var M_offset_9 = M[offset + 9];
            var M_offset_10 = M[offset + 10];
            var M_offset_11 = M[offset + 11];
            var M_offset_12 = M[offset + 12];
            var M_offset_13 = M[offset + 13];
            var M_offset_14 = M[offset + 14];
            var M_offset_15 = M[offset + 15];
            var a = H[0];
            var b = H[1];
            var c = H[2];
            var d = H[3];
            a = FF(a, b, c, d, M_offset_0, 7, T[0]);
            d = FF(d, a, b, c, M_offset_1, 12, T[1]);
            c = FF(c, d, a, b, M_offset_2, 17, T[2]);
            b = FF(b, c, d, a, M_offset_3, 22, T[3]);
            a = FF(a, b, c, d, M_offset_4, 7, T[4]);
            d = FF(d, a, b, c, M_offset_5, 12, T[5]);
            c = FF(c, d, a, b, M_offset_6, 17, T[6]);
            b = FF(b, c, d, a, M_offset_7, 22, T[7]);
            a = FF(a, b, c, d, M_offset_8, 7, T[8]);
            d = FF(d, a, b, c, M_offset_9, 12, T[9]);
            c = FF(c, d, a, b, M_offset_10, 17, T[10]);
            b = FF(b, c, d, a, M_offset_11, 22, T[11]);
            a = FF(a, b, c, d, M_offset_12, 7, T[12]);
            d = FF(d, a, b, c, M_offset_13, 12, T[13]);
            c = FF(c, d, a, b, M_offset_14, 17, T[14]);
            b = FF(b, c, d, a, M_offset_15, 22, T[15]);
            a = GG(a, b, c, d, M_offset_1, 5, T[16]);
            d = GG(d, a, b, c, M_offset_6, 9, T[17]);
            c = GG(c, d, a, b, M_offset_11, 14, T[18]);
            b = GG(b, c, d, a, M_offset_0, 20, T[19]);
            a = GG(a, b, c, d, M_offset_5, 5, T[20]);
            d = GG(d, a, b, c, M_offset_10, 9, T[21]);
            c = GG(c, d, a, b, M_offset_15, 14, T[22]);
            b = GG(b, c, d, a, M_offset_4, 20, T[23]);
            a = GG(a, b, c, d, M_offset_9, 5, T[24]);
            d = GG(d, a, b, c, M_offset_14, 9, T[25]);
            c = GG(c, d, a, b, M_offset_3, 14, T[26]);
            b = GG(b, c, d, a, M_offset_8, 20, T[27]);
            a = GG(a, b, c, d, M_offset_13, 5, T[28]);
            d = GG(d, a, b, c, M_offset_2, 9, T[29]);
            c = GG(c, d, a, b, M_offset_7, 14, T[30]);
            b = GG(b, c, d, a, M_offset_12, 20, T[31]);
            a = HH(a, b, c, d, M_offset_5, 4, T[32]);
            d = HH(d, a, b, c, M_offset_8, 11, T[33]);
            c = HH(c, d, a, b, M_offset_11, 16, T[34]);
            b = HH(b, c, d, a, M_offset_14, 23, T[35]);
            a = HH(a, b, c, d, M_offset_1, 4, T[36]);
            d = HH(d, a, b, c, M_offset_4, 11, T[37]);
            c = HH(c, d, a, b, M_offset_7, 16, T[38]);
            b = HH(b, c, d, a, M_offset_10, 23, T[39]);
            a = HH(a, b, c, d, M_offset_13, 4, T[40]);
            d = HH(d, a, b, c, M_offset_0, 11, T[41]);
            c = HH(c, d, a, b, M_offset_3, 16, T[42]);
            b = HH(b, c, d, a, M_offset_6, 23, T[43]);
            a = HH(a, b, c, d, M_offset_9, 4, T[44]);
            d = HH(d, a, b, c, M_offset_12, 11, T[45]);
            c = HH(c, d, a, b, M_offset_15, 16, T[46]);
            b = HH(b, c, d, a, M_offset_2, 23, T[47]);
            a = II(a, b, c, d, M_offset_0, 6, T[48]);
            d = II(d, a, b, c, M_offset_7, 10, T[49]);
            c = II(c, d, a, b, M_offset_14, 15, T[50]);
            b = II(b, c, d, a, M_offset_5, 21, T[51]);
            a = II(a, b, c, d, M_offset_12, 6, T[52]);
            d = II(d, a, b, c, M_offset_3, 10, T[53]);
            c = II(c, d, a, b, M_offset_10, 15, T[54]);
            b = II(b, c, d, a, M_offset_1, 21, T[55]);
            a = II(a, b, c, d, M_offset_8, 6, T[56]);
            d = II(d, a, b, c, M_offset_15, 10, T[57]);
            c = II(c, d, a, b, M_offset_6, 15, T[58]);
            b = II(b, c, d, a, M_offset_13, 21, T[59]);
            a = II(a, b, c, d, M_offset_4, 6, T[60]);
            d = II(d, a, b, c, M_offset_11, 10, T[61]);
            c = II(c, d, a, b, M_offset_2, 15, T[62]);
            b = II(b, c, d, a, M_offset_9, 21, T[63]);
            H[0] = (H[0] + a) | 0;
            H[1] = (H[1] + b) | 0;
            H[2] = (H[2] + c) | 0;
            H[3] = (H[3] + d) | 0;
        }, _doFinalize: function () {
            var data = this._data;
            var dataWords = data.words;
            var nBitsTotal = this._nDataBytes * 8;
            var nBitsLeft = data.sigBytes * 8;
            dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
            var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000);
            var nBitsTotalL = nBitsTotal;
            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = ((((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) | (((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00));
            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ((((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) | (((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00));
            data.sigBytes = (dataWords.length + 1) * 4;
            this._process();
            var hash = this._hash;
            var H = hash.words;
            for (var i = 0; i < 4; i++) {
                var H_i = H[i];
                H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) | (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00);
            }
            return hash;
        }, clone: function () {
            var clone = Hasher.clone.call(this);
            clone._hash = this._hash.clone();
            return clone;
        }
    });
    function FF(a, b, c, d, x, s, t) {
        var n = a + ((b & c) | (~b & d)) + x + t;
        return ((n << s) | (n >>> (32 - s))) + b;
    }
    function GG(a, b, c, d, x, s, t) {
        var n = a + ((b & d) | (c & ~d)) + x + t;
        return ((n << s) | (n >>> (32 - s))) + b;
    }
    function HH(a, b, c, d, x, s, t) {
        var n = a + (b ^ c ^ d) + x + t;
        return ((n << s) | (n >>> (32 - s))) + b;
    }
    function II(a, b, c, d, x, s, t) {
        var n = a + (c ^ (b | ~d)) + x + t;
        return ((n << s) | (n >>> (32 - s))) + b;
    }
    C.MD5 = Hasher._createHelper(MD5);
    C.HmacMD5 = Hasher._createHmacHelper(MD5);
}(Math));

function MD5_Encrypt(word) {
    return CryptoJS.MD5(word).toString();
    //反转:
    //return CryptoJS.MD5(word).toString().split("").reverse().join("");
}

2、execjs模块调用JS代码

import execjs
with open(file='encode.js', mode='r', encoding='utf-8') as fis:
     js_code = fis.read()  # 读取JS代码文件
js_obj = execjs.compile(js_code)  # 激将JS代码传入
js_obj.call('function', 'params')  # 调用JS的函数, 参数1:函数名、参数2:该函数所需要的参数

3、python代码

import os
import time
import execjs
import requests
from lxml import etree


class Spider(object):
    def __init__(self):
        self.headers = {
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
            'Chrome/95.0.4638.69 Safari/537.36',
            'authority': 'music.91q.com'
        }
        with open(file='encode.js', mode='r', encoding='utf-8') as fis:
            js_code = fis.read()
        self.js_obj = execjs.compile(js_code)
        self.timestamp = int(time.time())
        self.appid = 16073360
        self.secret = '0b50b02fd0d73a9c4c8c3a781c30845f'
        self.resource_path = 'music_download'

    def create_directory(self):
        if os.path.exists(self.resource_path) is False:
            os.mkdir(self.resource_path)

    def song_download(self, song_name, music_url):
        file_path = f"{self.resource_path}/{song_name}.mp3"
        response = requests.get(url=music_url, headers=self.headers)
        with open(file_path, 'wb') as fis:
            for chunk in response.iter_content(chunk_size=1000):
                fis.write(chunk)
                fis.flush()
        print(music_url)
        print(f"{file_path} - 下载完成!")

    def get_params(self, song_id):
        encode_string = f'TSID={song_id}&appid={self.appid}&timestamp={self.timestamp}{self.secret}'
        sign = self.js_obj.call('MD5_Encrypt', encode_string)
        params = {
            'sign': sign,
            'appid': self.appid,
            'TSID': song_id,
            'timestamp': self.timestamp
        }
        print(params)
        return params

    def parse(self, song_id):
        url = 'https://music.91q.com/v1/song/tracklinko'
        params = self.get_params(song_id=song_id)
        response = requests.get(url=url, headers=self.headers, params=params)
        result = {'status': False}
        if response.status_code == 200 and response.json()['data']['path'] is not None:
            json_data = response.json()
            result['song_name'] = json_data['data']['title']
            result['singer'] = json_data['data']['artist'][0]['name']
            result['music_url'] = json_data['data']['path']
            result['status'] = True
        return result

    def runs(self, keyword):
        self.create_directory()
        keyword_search_url = f'https://music.91q.com/search?word={keyword}'
        response = requests.get(url=keyword_search_url, headers=self.headers)
        selects = etree.HTML(response.text)
        li_list = selects.xpath('//ul[@data-v-e9211496=""]/li')
        song_info_item = dict()
        for li in li_list[1:]:
            song_name = li.xpath('div[@class="song ellipsis clearfix"]/div[@class="song-box"]/a/text()')[0]
            singer = li.xpath('div[@class="artist ellipsis"]/a/text()')[0]
            song_id = li.xpath('div[@class="song ellipsis clearfix"]/div[@class="song-box"]/a/@href')[0]
            song_id = song_id.replace('/song/', '')
            song_info_item[song_id] = song_name
            print(f"歌名:{song_name},\t\t歌曲ID:{song_id},\t\t歌手:{singer}")
        song_id = input("请输入歌曲ID:").strip()
        result = self.parse(song_id)
        if result['status'] is False:
            print(f"{song_id} - Vip歌曲不能下载")
            return False
        self.song_download(song_name=result['song_name'], music_url=result['music_url'])


if __name__ == '__main__':
    ky = input("请输入搜索关键词:").strip()
    Spider().runs(keyword=ky)

六、Pip模块安装

镜像地址

  • 清华:https://pypi.tuna.tsinghua.edu.cn/simple
  • 阿里云:http://mirrors.aliyun.com/pypi/simple/
  • 中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/
  • 华中理工大学:http://pypi.hustunique.com/
  • 山东理工大学:http://pypi.sdutlinux.org/
  • 豆瓣:http://pypi.douban.com/simple/

案例使用到的第三方模块以及对应版本

  • requests==2.27.0
  • PyExecJS==1.5.1
  • lxml==4.9.1

pip指定模块安装:pip install 模块名 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip指定requirements.txt文件安装:pip install -i https://pypi.doubanio.com/simple/ -r requirements.txt


总结

例如:以上就是今天要讲的内容,此次案例只为学习交流使用,切勿用于其他非法用途,网站url、接口url请使用base64.b64decode自行解码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/157615.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

knife4j使用与步骤

1、导入依赖<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>3.0.3</version> </dependency>2、knife4j的配置类&#xff08;可有可无&#xff09;package…

为什么程序员的工资比其他行业高这么多?

不止一次听到有人说程序员工资高&#xff0c;更有甚者喊着“把IT工资打下来”。 拜托大哥大姐们&#xff01;看事情要客观好吧&#xff01;&#xff01; 虽然看起来程序员工资是不少&#xff0c;对比其他行业确实会高一些&#xff0c;但并不代表程序员这个岗位工资就要压到三千…

Elasticsearch:如何在 Elasticsearch 中正确使用同义词功能

同义词用于提高搜索质量并扩大匹配范围。 例如&#xff0c;搜索 England 的用户可能希望找到包含 British 或 UK 的文档&#xff0c;尽管这三个词完全不同。 Elasticsearch 中的同义词功能非常强大&#xff0c;如果实施得当&#xff0c;可以使你的搜索引擎更加健壮和强大。 在…

详解结构体内存对齐

目录 前言 一、结构体内存对齐规则 二、 offsetof 宏 三、结构体内存对齐的原因 四、 修改默认对齐数 前言 引入问题&#xff1a; #include <stdio.h>struct S {char c1;int i;char c2; };int main() {printf("%zd\n", sizeof(struct S));return 0; } 程…

干货 | 人脸识别技术的风险及应对方案

以下内容整理自清华大学《数智安全与标准化》课程大作业期末报告同学的汇报内容。第一部分&#xff1a;人脸识别技术概述人脸识别的发展阶段&#xff0c;主要分为三个阶段&#xff1a;起步阶段&#xff08;1950s-1980s&#xff09;&#xff0c;这一阶段的人脸识别只是作为一般性…

房产管理系统---系统安全性需求分析

数图互通高校房产管理系统是基于公司自主研发的FMCenterV5.0平台&#xff0c;是针对中国高校房产的管理特点和管理要求&#xff0c;研发的一套标准产品&#xff1b;通过在中国100多所高校的成功实施和迭代&#xff0c;形成了一套成熟、完善、全生命周期的房屋资源管理解决方案。…

Linux学习笔记——HBase集群安装部署

5.11、大数据NoSQL数据库HBase集群部署 5.11.1、简介 HBase是一种分布式、可扩展、支持海量数据存储的NoSQL数据库。 和Redis一样&#xff0c;HBase是一款KeyValue型存储的数据库。 不过和Redis设计方向不同&#xff1a; Redis设计为少量数据&#xff0c;超快检索HBase设计…

【部署】Docker容器

Docker 使用 Google 公司推出的 Go 语言进行开发实现&#xff0c;基于 Linux 内核的 cgroup、namespace 以及 OverlayFS 类的 Union FS 等技术&#xff0c;对进程进行封装隔离&#xff0c;属于操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程&#xff0…

算法刷题打卡第63天:对称二叉树

对称二叉树 难度&#xff1a;简单 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false…

BOM浏览器对象模型

文章目录一、BOM概述1、什么是BOM2、BOM的构成二、window 对象的常见事件1、窗口加载事件&#xff08;1&#xff09;window.onload&#xff08;3&#xff09;DOMContentLoaded2、调整窗口大小事件三、定时器1、两种定时器2、setTimeout()定时器3、停止 setTimeout() 定时器4、s…

如何使用CMD修复硬盘命令来解决硬盘问题?

随着计算机的越来越普及&#xff0c;现在在我们的日常生活中都会使用到计算机电脑。硬盘作为计算机电脑的主要存储设备&#xff0c;里面存储着我们平时使用的软件文件、文档资料、照片等重要的数据文件。一旦硬盘损坏会给我们带来许多不必要的麻烦&#xff0c;那硬盘损坏有哪些…

图解卡尔曼滤波(Kalman Filter)

背景关于滤波首先援引来自知乎大神的解释。“一位专业课的教授给我们上课的时候&#xff0c;曾谈到&#xff1a;filtering is weighting&#xff08;滤波即加权&#xff09;。滤波的作用就是给不同的信号分量不同的权重。最简单的loss pass filter&#xff0c; 就是直接把低频的…

【Linux操作系统】1. Linux操作系统简介、安装

前言 本系列是Linux操作系统的一些知识以及实践内容&#xff0c;Linux操作系统作为开发最常使用的操作系统&#xff0c;是必备的一门求职、提升技术。本文先介绍Linux操作系统&#xff0c;并安装一个Linux操作系统。 Linux操作系统简介 Linux&#xff0c;全称GNU/Linux&#…

Javadoc

Javadoc 在学习JavaSE时&#xff0c;我们知道Java支持三种注释方式&#xff1a; 单行注释多行注释文档注释 Javadoc是文档注释&#xff0c;用来对类或方法进行标准的注释&#xff0c;在开发中写好JavaDoc非常重要。 在调用方法时&#xff0c;你可能会看到这样的情景 这种注…

Unity - 搬砖日志 - 如何设置AssetDatabase.Create(“xxx.asset“, mesh) 的Read/Write=false

最近很忙&#xff0c;想写的 BLOG 都遗漏编写了 踩坑的时间比较多&#xff0c;充电的时间少了很多 为了减少以后自己填坑时间&#xff0c;随便简单的记录一下 搬砖日志 环境 unity : 2020.3.37f1 pipeline : brp 问题 因为之前搜索、购买、使用了各式各样的 LOD 插件、工具…

机器学习100天(三十一):031 K近邻回归算法

机器学习100天,今天讲的是:K 近邻回归算法! 《机器学习100天》完整目录:目录 一、理论介绍 我们之前讲了 K 近邻分类算法,用来处理分类问题。其实 K 近邻也可以用来处理回归问题。 如左图所示,K 近邻分类算法的思路是选取与测试样本距离最近的前 k 个训练样本。然后对…

回收租赁商城系统功能拆解07讲-订单列表

回收租赁系统适用于物品回收、物品租赁、二手买卖交易等三大场景。 可以快速帮助企业搭建类似闲鱼回收/爱回收/爱租机/人人租等回收租赁商城。 回收租赁系统支持智能评估回收价格&#xff0c;后台调整最终回收价&#xff0c;用户同意回收后系统即刻放款&#xff0c;用户微信零…

寒假题练——day(3)

题目1&#xff1a; 给定一个大小为 n 的数组 nums &#xff0c;返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的&#xff0c;并且给定的数组总是存在多数元素。 进阶&#xff1a;尝试设计时间复杂度为 O(n)、空间复杂度为…

58、正则表达式

目录 一、快速入门 二、正则表达式基本语法 1、基本介绍&#xff1a; 2、正则表达式底层实现 3、元字符&#xff08;Metacharacter&#xff09;- 转义号\\ &#xff08;1&#xff09;限定符 &#xff08;2&#xff09;选择匹配符 &#xff08;5&#xff09;字符匹配符…

FX5U DRVMUL指令多个轴的表格运行

1.简述该指令可以用GX Works3预先在表格数据中设定的控制方式的动作&#xff0c;执行多个轴的表格。 2.指令解释同时执行多个轴的表格。指令执行开始后&#xff0c;各轴独立进行动作&#xff0c;也可连续运行。但是&#xff0c;只可在同一模块内同时执行2.1 操作数n1在(n1)中指…