File size: 6,248 Bytes
1070b3e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
from bs4 import BeautifulSoup
from flask import Flask, request, jsonify
import requests

from flask_cors import CORS 
from apscheduler.schedulers.background import BackgroundScheduler
from datetime import datetime

app = Flask(__name__)
CORS(app)  

# 缓存数据及更新时间
cached_results_soaring = []
cached_results_hot = []
cached_results_newSongs = []
cached_results_popular = []
last_update_time = None

def song(url):
    """从 QQ 音乐榜单页面爬取歌曲信息"""
    
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
        "Referer": "https://y.qq.com/",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
    }

    results = []
    try:
        
        # 发送请求
        response = requests.get(url, headers=headers)
        response.encoding = 'utf-8'
        
        # 使用 BeautifulSoup 解析页面
        soup = BeautifulSoup(response.text, 'html.parser')
        
        # 查找所有歌曲列表项
        song_items = soup.select("ul.songlist__list li")

        for item in song_items[:10]:
            try:
                # 提取歌曲名称
                song_name_span = item.select_one("span.songlist__songname_txt")
                song_name = song_name_span.text.strip()

                # 提取歌手名称
                artist_div = item.select_one("div.songlist__artist")
                artist_name = artist_div.text.strip()

                # 提取 mid
                song_link = song_name_span.find('a', class_='')
                
                mid = "default_mid"
                if song_link and song_link.get('href'):
                    mid = song_link['href'].split('/')[-1]

                # 提取图片链接
                img_link = song_name_span.find('a', class_='songlist__cover')
                if img_link and img_link.get('href'):
                    imgsrc = img_link['href'].split('/')[-1]
                img_url = f"https://y.qq.com/music/photo_new/T002R300x300M000{imgsrc}_1.jpg?max_age=2592000"

                if song_name and artist_name:
                    results.append({
                        "muName": song_name,
                        "cover": img_url if img_url else "",
                        "mid": mid,
                        "id": mid,
                        "song": song_name,
                        "singer": artist_name,
                        "muLink": 'qqdg/?word',
                        "uname": 'QQ音乐',
                        "muId": 1
                    })
            except Exception as e:
                print(f"处理歌曲项时出错: {e}")
                continue

    except Exception as e:
        print(f"爬取过程中出错: {e}")
        return []

    # 更新缓存数据及更新时间
    if results:
        print(f"数据已更新:{last_update_time}")   
    return results


def schedule_music_fetch():
    """设置每天早上 8 点定时任务"""
    scheduler = BackgroundScheduler()
    

    def run_tasks():
        global cached_results_soaring, cached_results_hot, cached_results_newSongs,  cached_results_popular, last_update_time
        # 依次运行每个任务
        cached_results_soaring = song("https://y.qq.com/n/ryqq/toplist/62")
        cached_results_hot = song("https://y.qq.com/n/ryqq/toplist/26")
        cached_results_newSongs = song("https://y.qq.com/n/ryqq/toplist/27")
        cached_results_popular = song("https://y.qq.com/n/ryqq/toplist/4")
        last_update_time =  datetime.now()


    # 设置定时任务,每天 8 点执行 run_tasks
    scheduler.add_job(run_tasks, 'cron', hour=8, minute=0)

    scheduler.start()
    print("定时任务已启动,爬取时间为每天早上 8 点。")

@app.route('/star')
def star():
    global cached_results_soaring, cached_results_hot, cached_results_newSongs,  cached_results_popular, last_update_time
    cached_results_soaring = song("https://y.qq.com/n/ryqq/toplist/62")
    cached_results_hot = song("https://y.qq.com/n/ryqq/toplist/26")
    cached_results_newSongs = song("https://y.qq.com/n/ryqq/toplist/27")
    cached_results_popular = song("https://y.qq.com/n/ryqq/toplist/4")
    last_update_time =  datetime.now()
    return jsonify({
        "data": "数据已更新",
        "updata time": last_update_time
    })

@app.route('/fetch_music_soaring', methods=['GET'])
def fetch_music_route_soaring():
    """提供缓存的 QQ 音乐榜单数据"""
    if not cached_results_soaring:
        return jsonify({"message": "数据尚未准备好,请先访问/star 更新数据"}), 503
    
    return jsonify({
        "last_update_time": last_update_time.strftime("%Y-%m-%d %H:%M:%S"),
        "data": cached_results_soaring
    })

@app.route('/fetch_music_hot', methods=['GET'])
def fetch_music_route_hot():
    """提供缓存的 QQ 音乐榜单数据"""
    if not cached_results_hot:
        return jsonify({"message": "数据尚未准备好,请先访问/star 更新数据"}), 503
    
    return jsonify({
        "last_update_time": last_update_time.strftime("%Y-%m-%d %H:%M:%S"),
        "data": cached_results_hot
    })

@app.route('/fetch_music_newSongs', methods=['GET'])
def fetch_music_route_newSongs():
    """提供缓存的 QQ 音乐榜单数据"""
    if not cached_results_newSongs:
        return jsonify({"message": "数据尚未准备好,请先访问/star 更新数据"}), 503
    
    return jsonify({
        "last_update_time": last_update_time.strftime("%Y-%m-%d %H:%M:%S"),
        "data": cached_results_newSongs
    })

@app.route('/fetch_music_popular', methods=['GET'])
def fetch_music_route_popular():
    """提供缓存的 QQ 音乐榜单数据"""
    if not cached_results_popular:
        return jsonify({"message": "数据尚未准备好,请先访问/star 更新数据"}), 503
    
    return jsonify({
        "last_update_time": last_update_time.strftime("%Y-%m-%d %H:%M:%S"),
        "data": cached_results_popular
    })
if __name__ == '__main__':
    # 启动 Flask 应用时初始化定时任务
    schedule_music_fetch()
    app.run(debug=True,host='0.0.0.0',port=5734)