mistpe commited on
Commit
1070b3e
·
verified ·
1 Parent(s): e089a38

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +170 -0
app.py ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from bs4 import BeautifulSoup
2
+ from flask import Flask, request, jsonify
3
+ import requests
4
+
5
+ from flask_cors import CORS
6
+ from apscheduler.schedulers.background import BackgroundScheduler
7
+ from datetime import datetime
8
+
9
+ app = Flask(__name__)
10
+ CORS(app)
11
+
12
+ # 缓存数据及更新时间
13
+ cached_results_soaring = []
14
+ cached_results_hot = []
15
+ cached_results_newSongs = []
16
+ cached_results_popular = []
17
+ last_update_time = None
18
+
19
+ def song(url):
20
+ """从 QQ 音乐榜单页面爬取歌曲信息"""
21
+
22
+ headers = {
23
+ "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",
24
+ "Referer": "https://y.qq.com/",
25
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
26
+ }
27
+
28
+ results = []
29
+ try:
30
+
31
+ # 发送请求
32
+ response = requests.get(url, headers=headers)
33
+ response.encoding = 'utf-8'
34
+
35
+ # 使用 BeautifulSoup 解析页面
36
+ soup = BeautifulSoup(response.text, 'html.parser')
37
+
38
+ # 查找所有歌曲列表项
39
+ song_items = soup.select("ul.songlist__list li")
40
+
41
+ for item in song_items[:10]:
42
+ try:
43
+ # 提取歌曲名称
44
+ song_name_span = item.select_one("span.songlist__songname_txt")
45
+ song_name = song_name_span.text.strip()
46
+
47
+ # 提取歌手名称
48
+ artist_div = item.select_one("div.songlist__artist")
49
+ artist_name = artist_div.text.strip()
50
+
51
+ # 提取 mid
52
+ song_link = song_name_span.find('a', class_='')
53
+
54
+ mid = "default_mid"
55
+ if song_link and song_link.get('href'):
56
+ mid = song_link['href'].split('/')[-1]
57
+
58
+ # 提取图片链接
59
+ img_link = song_name_span.find('a', class_='songlist__cover')
60
+ if img_link and img_link.get('href'):
61
+ imgsrc = img_link['href'].split('/')[-1]
62
+ img_url = f"https://y.qq.com/music/photo_new/T002R300x300M000{imgsrc}_1.jpg?max_age=2592000"
63
+
64
+ if song_name and artist_name:
65
+ results.append({
66
+ "muName": song_name,
67
+ "cover": img_url if img_url else "",
68
+ "mid": mid,
69
+ "id": mid,
70
+ "song": song_name,
71
+ "singer": artist_name,
72
+ "muLink": 'qqdg/?word',
73
+ "uname": 'QQ音乐',
74
+ "muId": 1
75
+ })
76
+ except Exception as e:
77
+ print(f"处理歌曲项时出错: {e}")
78
+ continue
79
+
80
+ except Exception as e:
81
+ print(f"爬取过程中出错: {e}")
82
+ return []
83
+
84
+ # 更新缓存数据及更新时间
85
+ if results:
86
+ print(f"数据已更新:{last_update_time}")
87
+ return results
88
+
89
+
90
+ def schedule_music_fetch():
91
+ """设置每天早上 8 点定时任务"""
92
+ scheduler = BackgroundScheduler()
93
+
94
+
95
+ def run_tasks():
96
+ global cached_results_soaring, cached_results_hot, cached_results_newSongs, cached_results_popular, last_update_time
97
+ # 依次运行每个任务
98
+ cached_results_soaring = song("https://y.qq.com/n/ryqq/toplist/62")
99
+ cached_results_hot = song("https://y.qq.com/n/ryqq/toplist/26")
100
+ cached_results_newSongs = song("https://y.qq.com/n/ryqq/toplist/27")
101
+ cached_results_popular = song("https://y.qq.com/n/ryqq/toplist/4")
102
+ last_update_time = datetime.now()
103
+
104
+
105
+ # 设置定时任务,每天 8 点执行 run_tasks
106
+ scheduler.add_job(run_tasks, 'cron', hour=8, minute=0)
107
+
108
+ scheduler.start()
109
+ print("定时任务已启动,爬取时间为每天早上 8 点。")
110
+
111
+ @app.route('/star')
112
+ def star():
113
+ global cached_results_soaring, cached_results_hot, cached_results_newSongs, cached_results_popular, last_update_time
114
+ cached_results_soaring = song("https://y.qq.com/n/ryqq/toplist/62")
115
+ cached_results_hot = song("https://y.qq.com/n/ryqq/toplist/26")
116
+ cached_results_newSongs = song("https://y.qq.com/n/ryqq/toplist/27")
117
+ cached_results_popular = song("https://y.qq.com/n/ryqq/toplist/4")
118
+ last_update_time = datetime.now()
119
+ return jsonify({
120
+ "data": "数据已更新",
121
+ "updata time": last_update_time
122
+ })
123
+
124
+ @app.route('/fetch_music_soaring', methods=['GET'])
125
+ def fetch_music_route_soaring():
126
+ """提供缓存的 QQ 音乐榜单数据"""
127
+ if not cached_results_soaring:
128
+ return jsonify({"message": "数据尚未准备好,请先访问/star 更新数据"}), 503
129
+
130
+ return jsonify({
131
+ "last_update_time": last_update_time.strftime("%Y-%m-%d %H:%M:%S"),
132
+ "data": cached_results_soaring
133
+ })
134
+
135
+ @app.route('/fetch_music_hot', methods=['GET'])
136
+ def fetch_music_route_hot():
137
+ """提供缓存的 QQ ���乐榜单数据"""
138
+ if not cached_results_hot:
139
+ return jsonify({"message": "数据尚未准备好,请先访问/star 更新数据"}), 503
140
+
141
+ return jsonify({
142
+ "last_update_time": last_update_time.strftime("%Y-%m-%d %H:%M:%S"),
143
+ "data": cached_results_hot
144
+ })
145
+
146
+ @app.route('/fetch_music_newSongs', methods=['GET'])
147
+ def fetch_music_route_newSongs():
148
+ """提供缓存的 QQ 音乐榜单数据"""
149
+ if not cached_results_newSongs:
150
+ return jsonify({"message": "数据尚未准备好,请先访问/star 更新数据"}), 503
151
+
152
+ return jsonify({
153
+ "last_update_time": last_update_time.strftime("%Y-%m-%d %H:%M:%S"),
154
+ "data": cached_results_newSongs
155
+ })
156
+
157
+ @app.route('/fetch_music_popular', methods=['GET'])
158
+ def fetch_music_route_popular():
159
+ """提供缓存的 QQ 音乐榜单数据"""
160
+ if not cached_results_popular:
161
+ return jsonify({"message": "数据尚未准备好,请先访问/star 更新数据"}), 503
162
+
163
+ return jsonify({
164
+ "last_update_time": last_update_time.strftime("%Y-%m-%d %H:%M:%S"),
165
+ "data": cached_results_popular
166
+ })
167
+ if __name__ == '__main__':
168
+ # 启动 Flask 应用时初始化定时任务
169
+ schedule_music_fetch()
170
+ app.run(debug=True,host='0.0.0.0',port=5734)