如何批量下载网站所有专辑歌曲?Python代码报TypeError求解
报错原因
urllib.request.Request 仅用于构造请求配置对象,不会主动发起网络请求拉取目标页面内容,直接遍历该对象就会触发 TypeError: 'Request' object is not iterable 报错。
基础报错修复
要正常获取页面内容,需要调用 urllib.request.urlopen() 传入构造好的请求对象,拿到实际响应结果后才能读取、遍历内容,修复后的基础请求代码如下:
import urllib.request tar_url = "https://your-target-site/songs-download" # 替换为实际目标地址 # 构造请求时加User-Agent避免被站点默认反爬拦截 req = urllib.request.Request( tar_url, 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"} ) # 发起请求拿到响应 with urllib.request.urlopen(req, timeout=15) as resp: # 遍历响应内容,解码后输出 for line in resp: print(line.decode("utf-8", errors="ignore"))
批量下载专辑完整实现方案
手动逐页点击下载效率太低,可以通过「爬取专辑列表→提取专辑详情页链接→提取歌曲下载直链→批量保存到本地」的流程实现自动化下载,具体步骤如下:
- 安装依赖:执行
pip install beautifulsoup4安装HTML解析库,不用手写正则匹配链接,适配效率更高。 - 先请求专辑总列表页,解析提取所有专辑的详情页地址。
- 逐个请求专辑详情页,提取页内所有歌曲的下载直链、对应歌曲名称。
- 逐个下载歌曲文件到本地按专辑分类的目录,请求间隔加延时避免触发站点反爬被封IP。
完整可参考的实现代码:
import time import os import urllib.request from urllib.parse import urljoin from bs4 import BeautifulSoup # 配置项,根据实际情况修改 BASE_ALBUM_LIST_URL = "https://your-target-site/songs-download" # 专辑列表页地址 SAVE_ROOT_PATH = "./downloaded_songs" # 本地文件保存根目录 REQUEST_DELAY = 2 # 每次请求间隔秒数,不要设太小避免被封 COMMON_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" } def get_page_content(url): """请求指定url返回页面文本内容""" req = urllib.request.Request(url, headers=COMMON_HEADERS) with urllib.request.urlopen(req, timeout=15) as resp: return resp.read().decode("utf-8", errors="ignore") def save_file_from_url(url, save_full_path): """下载网络文件到指定本地路径""" req = urllib.request.Request(url, headers=COMMON_HEADERS) with urllib.request.urlopen(req, timeout=60) as resp: with open(save_full_path, "wb") as f: f.write(resp.read()) if __name__ == "__main__": # 初始化保存目录 os.makedirs(SAVE_ROOT_PATH, exist_ok=True) # 第一步:拉取专辑列表页,提取所有专辑链接 list_page_content = get_page_content(BASE_ALBUM_LIST_URL) list_soup = BeautifulSoup(list_page_content, "html.parser") album_info_list = [] for a_tag in list_soup.find_all("a", href=True): tag_text = a_tag.get_text(strip=True) # 过滤专辑链接,可根据目标站点实际规则调整判断条件 if "专辑" in tag_text: album_full_url = urljoin(BASE_ALBUM_LIST_URL, a_tag["href"]) album_info_list.append((tag_text, album_full_url)) print(f"识别到共{len(album_info_list)}个专辑") # 第二步:遍历每个专辑,提取歌曲下载链接并下载 for album_name, album_url in album_info_list: # 处理专辑名里的非法文件名字符 valid_album_name = album_name.replace("/", "_").replace("\\", "_").replace(":", "_") album_save_dir = os.path.join(SAVE_ROOT_PATH, valid_album_name) os.makedirs(album_save_dir, exist_ok=True) print(f"开始处理专辑:{album_name}") try: album_page_content = get_page_content(album_url) album_soup = BeautifulSoup(album_page_content, "html.parser") # 提取页内所有下载链接 for a_tag in album_soup.find_all("a", href=True): tag_text = a_tag.get_text(strip=True) tag_href = a_tag["href"] # 过滤歌曲下载链接,可根据目标站点实际规则调整判断条件 if "下载" in tag_text or tag_href.endswith((".mp3", ".flac", ".wav", ".m4a")): song_name = tag_text.replace("下载", "").strip() # 补全文件名后缀 if not song_name.endswith((".mp3", ".flac", ".wav", ".m4a")): song_name += ".mp3" valid_song_name = song_name.replace("/", "_").replace("\\", "_").replace(":", "_") song_save_path = os.path.join(album_save_dir, valid_song_name) # 跳过已经下载过的文件 if os.path.exists(song_save_path): print(f"跳过已下载文件:{song_name}") continue song_download_url = urljoin(album_url, tag_href) print(f"正在下载:{song_name}") save_file_from_url(song_download_url, song_save_path) time.sleep(REQUEST_DELAY) except Exception as e: print(f"处理专辑{album_name}时出错,跳过:{str(e)}") continue time.sleep(REQUEST_DELAY)
注意:上述代码里的链接过滤规则是通用示例,你需要打开目标站点按F12查看实际HTML结构,修改专辑链接、歌曲下载链接的匹配规则,才能适配对应站点。如果站点有登录校验、动态渲染内容等反爬机制,需要对应在请求头中补充cookie信息,或者替换为支持JS渲染的请求工具获取页面内容。
内容的提问来源于stack exchange,提问作者Mainland
相关产品推荐
相关产品推荐

