wei/测试/crawler2.py

102 lines
3.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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'<li><a href="/song\?id=(\d+)">(.*?)</a>', 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("所有歌曲下载完成!")