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) |