import re import os import requests import time # 修改存储目录为 F:\测试 filename = r'F:\测试\音乐\\' # 如果没有则创建文件夹 if not os.path.exists(filename): os.makedirs(filename) # 请求网址 url = 'https://music.163.com/playlist?id=3778678' # 伪造请求头 headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36' } # 发送请求 print("正在获取列表...") response = requests.get(url, headers=headers) # 提取数据 html_data = re.findall(r'
  • (.*?)', response.text) # 限速设置:30mbps = 30 * 1024 * 1024 / 8 = 3932160 字节/秒 MAX_SPEED_BPS = 30 * 1024 * 1024 // 8 # 约3.75MB/s # 下载 for i, (num_id, title) in enumerate(html_data, 1): try: # 方法1:替换所有Windows文件名中的非法字符 # Windows文件名不能包含的字符: \ / : * ? " < > | clean_title = re.sub(r'[\\/*?:"<>|]', '', title) # 方法2:更严格的清理,只保留字母、数字、中文、空格和一些常用标点 # clean_title = re.sub(r'[^a-zA-Z0-9\u4e00-\u9fa5\s\-_\(\)\[\]\.]', '', title) # 如果清理后文件名为空,使用歌曲ID作为文件名 if not clean_title.strip(): clean_title = f"song_{num_id}" # 检查文件是否已存在 file_path = os.path.join(filename, clean_title + '.mp3') if os.path.exists(file_path): print(f"跳过已存在的文件: {clean_title}") continue print(f"正在下载 ({i}/{len(html_data)}): {clean_title} (原标题: {title})") # 调用接口 music_url = f'https://music.163.com/song/media/outer/url?id={num_id}.mp3' # 发送请求获取响应(使用流模式) with requests.get(music_url, headers=headers, stream=True) as response: response.raise_for_status() # 获取文件大小 total_size = int(response.headers.get('content-length', 0)) # 保存文件 start_time = time.time() downloaded_size = 0 with open(file_path, 'wb') as f: for chunk in response.iter_content(chunk_size=8192): # 8KB chunks if chunk: f.write(chunk) downloaded_size += len(chunk) # 计算当前速度 elapsed_time = time.time() - start_time if elapsed_time > 0: current_speed = downloaded_size / elapsed_time # 字节/秒 # 如果速度超过限制,则等待 if current_speed > MAX_SPEED_BPS and downloaded_size < total_size: expected_time = downloaded_size / MAX_SPEED_BPS sleep_time = expected_time - elapsed_time if sleep_time > 0: time.sleep(sleep_time) # 显示进度 if total_size > 0: percent = downloaded_size / total_size * 100 print(f"\r进度: {percent:.1f}% ({downloaded_size//1024}KB/{total_size//1024}KB)", end='') print() # 换行 print(f"完成: {clean_title}") except Exception as e: print(f"下载失败 {title}: {str(e)}") # 如果下载失败,删除可能不完整的文件 if 'file_path' in locals() and os.path.exists(file_path): os.remove(file_path) # 添加短暂延迟,避免请求过快 time.sleep(0.5) print("所有歌曲下载完成!")