如何用Python从HTML中提取RAR文件链接并下载对应文件?
解析HTML中的.rar链接并下载文件的完整解决方案
我来帮你搞定这个需求,先梳理下你原代码里的几个小问题,再给你一套完整的实现方案:
原代码里的问题点
- 正则表达式写错了:
re.compile("$rar")应该是re.compile(r'\.rar$'),要匹配以.rar结尾的链接,点号需要转义,$放在结尾表示匹配字符串末尾。 - 缺少
re模块的导入,正则表达式没法正常使用。 - BeautifulSoup的导入建议更新为
from bs4 import BeautifulSoup(现在主流是这个版本,旧版的BeautifulSoup包已经停止维护了)。 - 循环语句末尾缺少冒号,会触发语法错误。
- 获取链接时应该用
link.get('href'),而不是直接写字符串'href'。 - 没有添加文件保存到本地的逻辑,下载后没法留存文件。
- 你创建了session对象
s,但后续请求没用到它,应该用s.get()来保持会话一致性(比如页面需要登录状态时)。
完善后的完整代码
import requests import re import random import os from bs4 import BeautifulSoup # 推荐使用新版BeautifulSoup # 用户代理列表 user_agent_list = [ # Windows 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Firefox/60.0', # Linux 'Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:60.0) Gecko/20100101 Firefox/60.0', ] # 目标URL和保存目录 url = 'http://example.com' save_dir = './rar_files' # 自定义保存目录,不存在则自动创建 if not os.path.exists(save_dir): os.makedirs(save_dir) # 建立会话,保持登录状态(如果headers里的账号密码有效) session = requests.session() user_agent = random.choice(user_agent_list) headers = { 'login_username': 'user', 'login_password': 'pass', 'User-Agent': user_agent } try: # 请求目标页面 response = session.get(url, headers=headers) response.raise_for_status() # 请求失败时抛出异常,避免静默报错 print("页面请求成功") # 解析HTML内容 soup = BeautifulSoup(response.content, 'html.parser') # 指定解析器,避免警告 # 筛选所有指向.rar文件的链接 rar_links = soup.find_all('a', attrs={'href': re.compile(r'\.rar$')}) print(f"找到 {len(rar_links)} 个.rar文件链接") # 遍历链接并下载文件 for link in rar_links: rar_url = link.get('href') # 处理相对链接(如果页面里有相对路径的话) if not rar_url.startswith('http'): rar_url = requests.compat.urljoin(url, rar_url) # 从URL中提取文件名 filename = os.path.basename(rar_url) save_path = os.path.join(save_dir, filename) print(f"正在下载: {rar_url}") try: # 分块下载大文件(避免内存占用过高) with session.get(rar_url, stream=True) as r: r.raise_for_status() with open(save_path, 'wb') as f: for chunk in r.iter_content(chunk_size=8192): f.write(chunk) print(f"下载完成: {filename}") except Exception as e: print(f"下载 {rar_url} 失败: {str(e)}") except Exception as e: print(f"页面请求失败: {str(e)}")
代码额外优化说明
- 自动创建目录:提前检查保存目录是否存在,不存在则自动创建,避免保存文件时出错。
- 会话保持:用
session.get()替代requests.get(),确保登录状态(如果你的headers账号密码有效的话)。 - 异常捕获:添加
raise_for_status()捕获请求失败的情况,不会默默忽略错误。 - 相对链接处理:用
requests.compat.urljoin()把相对链接转为绝对链接,避免下载错误地址。 - 分块下载:通过
stream=True和iter_content()分块写入文件,适合大文件下载,不会占满内存。
如果想加速下载,可以用多线程并行处理,比如把下载逻辑封装成函数后启动线程:
import threading # 定义下载函数 def download_rar(rar_url, save_path, session): try: print(f"正在下载: {rar_url}") with session.get(rar_url, stream=True) as r: r.raise_for_status() with open(save_path, 'wb') as f: for chunk in r.iter_content(chunk_size=8192): f.write(chunk) print(f"下载完成: {os.path.basename(save_path)}") except Exception as e: print(f"下载 {rar_url} 失败: {str(e)}") # 遍历链接并启动线程 threads = [] for link in rar_links: rar_url = link.get('href') if not rar_url.startswith('http'): rar_url = requests.compat.urljoin(url, rar_url) filename = os.path.basename(rar_url) save_path = os.path.join(save_dir, filename) thread = threading.Thread(target=download_rar, args=(rar_url, save_path, session)) threads.append(thread) thread.start() # 等待所有线程完成 for thread in threads: thread.join()
这样就能同时下载多个文件,提升下载效率啦!
内容的提问来源于stack exchange,提问作者weepkt
相关产品推荐
相关产品推荐

