预览
migu.py
# -*- coding: utf-8 -*-import osimport threadingimport webbrowserimport requestsfrom flask import Flaskfrom flask import render_template, send_from_directoryfrom flask import requestfrom flask_cors import CORS# html同级app = Flask(__name__, template_folder=".")CORS(app, resources='/*')app.jinja_env.variable_start_string = '{['app.jinja_env.variable_end_string = ']}'def request_parse():    if request.method == 'POST' or request.method == 'PUT':        return request.json    elif request.method == 'GET' or request.method == 'DELETE':        return request.args@app.route('/getList', methods=['GET'])def getList():    # region 参数    data = request_parse()    pageNum = data.get("pageNum")    pageSize = data.get("pageSize")    keyword = data.get("keyword")    if not keyword:        return {            "resultCode": 400,            "msg": "未输入歌手|歌名"        }    params = {        'feature': '1111000000',        'isCopyright': 1,        'isCorrect': 1,        'pageIndex': pageNum,        'pageSize': pageSize,        'searchSwitch': '{"song":1,"album":0,"singer":0,"tagSong":1,"mvSong":0,"songlist":0,"bestShow":1,"lyricSong":0,"concert":0,"periodical":0,"ticket":0,"bit24":0,"verticalVideoTone":0}',        'sid': 'E02D5216B02446F0BB85363041291C22B8EAB6797442459B9C1C5B29DEED3612',        'sort': 0,        'text': keyword,        'uiVersion': 'I_music_3.0.2',    }    headers = {        "User-Agent": "MGMobileMusic/6.9.9 (iPhone; iOS 13.1.3; Scale/2.00)",        "version": "6.9.9",        "uiVersion": "I_music_3.0.2",        "timeStamp": "1605096959",        "sign": "8a560d2511c002186d2dfa0bac44b9b7",    }    resp = requests.get('http://jadeite.migu.cn:7090/music_search/v2/search/searchAll', params=params, headers=headers)    print(resp.url)    resultList = resp.json()["songResultData"]["resultList"]    resultNum = resp.json()["resultNum"]    result = []    for itemList in resultList:        for item in itemList:            singers = ','.join([singer.get("name", "") for singer in item.get('singers')])            song = {                'song_name': item.get('name'),  # 歌名                'singers': singers  # 歌手字符串集合            }            # rate_list = item.get('rateFormats', [])            rate_list = item.get('newRateFormats', [])            urls = {}            for x in rate_list:                if x.get('url', None):                    urls[x.get('formatType')] = x.get('url').replace('ftp://218.200.160.122:21',                                                                     'http://freetyst.nf.migu.cn')                    urls[x.get('formatType') + "_size"] = int(x.get('size')) / 1024 / 1024                    urls[x.get('formatType') + "_size"] = round(urls[x.get('formatType') + "_size"], 2)                else:                    format_type = x.get('formatType')                    if format_type == 'SQ':                        urls['SQ'] = x.get('androidUrl').replace('ftp://218.200.160.122:21',                                                                 'http://freetyst.nf.migu.cn')                        urls["SQ_size"] = int(x.get('androidSize')) / 1024 / 1024                        urls["SQ_size"] = round(urls["SQ_size"], 2)                    elif format_type == 'ZQ':                        urls['ZQ'] = x.get('androidUrl').replace('ftp://218.200.160.122:21',                                                                 'http://freetyst.nf.migu.cn')                        urls["ZQ_size"] = int(x.get('androidSize')) / 1024 / 1024                        urls["ZQ_size"] = round(urls["ZQ_size"], 2)                song['urls'] = urls            result.append(song)    return {        "resultCode": 200,        "total": resultNum,        "rows": result,    }@app.route('/downloadSong', methods=['GET'])def downloadSong():    data = request_parse()    singers = data.get("singers")    song_name = data.get("song_name").strip()    url = data.get("url")    size = data.get("size")    # static/down/歌曲名/大小/文件    dir_path = "static/down/" + song_name + "/" + size    if not os.path.exists(dir_path):        os.makedirs(dir_path)    file_name = singers + " - " + song_name + url[url.rfind("."):]  # 起风了.mp3    file_path = dir_path + "/" + file_name    if not os.path.exists(file_path):        print("开始下载...")        with open(file_path, mode="wb") as f:            f.write(requests.get(url).content)        print("下载成功:", file_path)    else:        print("文件存在,直接返回")    return send_from_directory(dir_path, file_name, as_attachment=True)@app.route("/")def index():    return render_template('index.html')def openUrl(port):    if os.path.exists("static/down"):        for root, dirs, files in os.walk("static/down"):            for file in files:                file_path = os.path.join(root, file)                if os.path.getsize(file_path) == 0:                    os.remove(file_path)                    print("清理空文件:", file_path)    webbrowser.open("http://127.0.0.1:{}".format(port), new=0)@app.errorhandler(Exception)def error_handler(e):    print("全局异常捕获: {}".format(e))    data = {        "resultCode": 500,        "msg": str(e)    }    return dataif __name__ == '__main__':    port = 777    if not os.environ.get('WERKZEUG_RUN_MAIN'):        th = threading.Thread(target=openUrl, args=(port,))        th.start()    else:        print("热加载\n")    app.run(host="0.0.0.0", port=port, debug=True)
index.html
<!DOCTYPE html><html lang="zh"><head>    <meta charset="UTF-8">    <title>咪咕音乐</title>    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">    <script src="https://unpkg.com/vue/dist/vue.js"></script>    <script src="https://unpkg.com/element-ui/lib/index.js"></script>    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>    <link rel="shortcut icon" href="static/favicon.ico" type="image/x-icon"/></head><style>    body {        width: 70%;        margin: auto;        margin-top: 20px;    }    ::-webkit-scrollbar {        width: 0;    }</style><body><div id="app">    <div class="app-container">        <el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px">            <el-form-item label="" prop="keyword">                <el-input                        v-model="queryParams.keyword"                        placeholder="请输入歌曲|歌手"                        clearable                        size="mini"                        @keyup.enter.native="handleQuery"/>            </el-form-item>            <el-form-item>                <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>            </el-form-item>            <el-form-item style="margin-top: 5px">                <el-pagination                        background                        :current-page.sync="queryParams.pageNum"                        :page-sizes="[10, 15, 20, 25]"                        :page-size.sync="queryParams.pageSize"                        layout="total, sizes, prev, pager, next"                        @size-change="getList"                        @current-change="getList"                        :total="total">                </el-pagination>            </el-form-item>        </el-form>        <el-table v-loading="loading" element-loading-text="正在进行中,请等待..." :data="songList">            <el-table-column label="歌名" align="center" prop="song_name"></el-table-column>            <el-table-column label="歌手" align="center" prop="singers"></el-table-column>            <el-table-column label="流畅" align="center">                <template slot-scope="scope" v-if="scope.row.urls && scope.row.urls.LQ">                    <el-link type="primary" :underline="false" target="_blank"                             :href="`/downloadSong?singers=${scope.row.singers}&size=${scope.row.urls.LQ_size}&song_name=${scope.row.song_name}&url=${scope.row.urls.LQ}`">                        {{scope.row.urls.LQ_size}}M                    </el-link>                </template>            </el-table-column>            <el-table-column label="普通" align="center">                <template slot-scope="scope" v-if="scope.row.urls && scope.row.urls.PQ">                    <el-link type="primary" :underline="false" target="_blank"                             :href="`/downloadSong?singers=${scope.row.singers}&size=${scope.row.urls.PQ_size}&song_name=${scope.row.song_name}&url=${scope.row.urls.PQ}`">                        {{scope.row.urls.PQ_size}}M                    </el-link>                </template>            </el-table-column>            <el-table-column label="高清" align="center">                <template slot-scope="scope" v-if="scope.row.urls && scope.row.urls.HQ">                    <el-link type="primary" :underline="false" target="_blank"                             :href="`/downloadSong?singers=${scope.row.singers}&size=${scope.row.urls.HQ_size}&song_name=${scope.row.song_name}&url=${scope.row.urls.HQ}`">                        {{scope.row.urls.HQ_size}}M                    </el-link>                </template>            </el-table-column>            <el-table-column label="无损" align="center">                <template slot-scope="scope" v-if="scope.row.urls && scope.row.urls.SQ">                    <el-link type="primary" :underline="false" target="_blank"                             :href="`/downloadSong?singers=${scope.row.singers}&size=${scope.row.urls.SQ_size}&song_name=${scope.row.song_name}&url=${scope.row.urls.SQ}`">                        {{scope.row.urls.SQ_size}}M                    </el-link>                </template>            </el-table-column>            <el-table-column label="至臻" align="center">                <template slot-scope="scope" v-if="scope.row.urls && scope.row.urls.ZQ">                    <el-link type="primary" :underline="false" target="_blank"                             :href="`/downloadSong?singers=${scope.row.singers}&size=${scope.row.urls.ZQ_size}&song_name=${scope.row.song_name}&url=${scope.row.urls.ZQ}`">                        {{scope.row.urls.ZQ_size}}M                    </el-link>                </template>            </el-table-column>        </el-table>    </div></div></body><script>    baseUrl = "http://127.0.0.1:777"    new Vue({        el: '#app',        data() {            return {                // 遮罩层                loading: false,                // 总条数                total: 0,                songList: [],                // 查询参数                queryParams: {                    pageNum: 1,                    pageSize: 10,                    keyword: "起风了",                },            };        },        created() {        },        methods: {            // 查询列表            getList() {                this.loading = true;                axios({                    method: 'get',                    url: baseUrl + '/getList',                    params: this.queryParams,                }).then(res => {                    const response = res.data;                    const resultCode = response.resultCode                    if (resultCode === 200) {                        this.songList = response.rows;                        this.total = response.total;                    } else {                        this.$message({                            message: '查询失败,' + response.msg,                            type: 'error'                        });                    }                    this.loading = false;                }).catch(function (error) {                    console.log(error);                });            },            /** 搜索按钮操作 */            handleQuery() {                this.queryParams.pageNum = 1;                this.getList();            },            downloadSong(singers, song_name, url) {                axios({                    method: 'get',                    url: baseUrl + '/downloadSong',                    params: {                        "singers": singers,                        "song_name": song_name,                        "url": url                    },                }).then(res => {                    /*const response = res.data;                    const resultCode = response.resultCode                    if (resultCode === 200) {                    } else {                        this.$message({                            message: '下载失败,' + response.msg,                            type: 'error'                        });                    }*/                }).catch(function (error) {                    console.log(error);                });            },            changeLink(link) {                window.location.href = link            }        }    })</script></html>