使用Python requests.get保存网页时未下载关联图片的问题咨询
为什么原代码保存的页面会出现图片失效
原逻辑仅抓取了主HTML文档的内容,没有处理HTML内部嵌套引用的图片、CSS等外部资源:这些资源的原始路径都是指向线上服务器的,当你把HTML存到本地后,相对路径找不到对应文件,自然就会出现裂链效果。要实现和浏览器右键「另存为-完整网页」等价的效果,需要补全三个核心动作:
- 解析HTML内的所有外部资源引用
- 批量下载对应资源到本地目录
- 将HTML内的资源引用路径替换为本地相对路径,保证本地打开时能正常加载
改造后的完整实现
前置依赖安装
需要搭配轻量的HTML解析库处理资源路径识别,安装命令:pip install requests beautifulsoup4 lxml
适配原有爬取逻辑的代码替换
原代码存在两处基础问题:一是文件关闭方法close()漏写括号会触发语法报错;二是完全缺失资源下载和路径替换的逻辑。改造后的逻辑完全复用你原本的遍历链接、请求页面的流程,补充全量资源存储能力:
- 为每个爬取的HTML页面单独创建同名资源目录,和浏览器的存储逻辑保持一致
- 自动识别HTML中所有
<img>、<link>、<script>标签内的资源引用 - 自动跳过内嵌
data:协议的资源,避免无效请求 - 已下载过的资源自动跳过,减少重复请求
- 路径拼接自动适配相对路径、绝对路径的场景,不会出现路径错位
import os import time import requests from bs4 import BeautifulSoup from urllib.parse import urljoin, urlparse # 定义通用资源下载函数 def download_asset(asset_url, save_dir): parsed_url = urlparse(asset_url) file_name = os.path.basename(parsed_url.path) # 跳过无有效文件名的空路径资源 if not file_name: return save_path = os.path.join(save_dir, file_name) # 已下载的资源直接跳过,避免重复请求 if os.path.exists(save_path): return save_path # 发起请求下载资源 res = requests.get(asset_url) res.raise_for_status() with open(save_path, 'wb') as f: f.write(res.content) return save_path base_url = "http://aosabook.org/en/" for link in aosa1: page_url = urljoin(base_url, link) # 请求主HTML页面 res = requests.get(page_url) print(res.status_code) print(len(res.text)) res.raise_for_status() # 处理页面存储命名 page_name = link.split("/")[-1] if not page_name.endswith(".html"): page_name += ".html" # 创建当前页面对应的资源存储目录 asset_dir = f"{os.path.splitext(page_name)[0]}_assets" os.makedirs(asset_dir, exist_ok=True) # 解析HTML内容 soup = BeautifulSoup(res.text, "lxml") # 处理所有带src属性的标签(图片、脚本等) for tag in soup.find_all(src=True): src_path = tag["src"] if src_path.startswith("data:"): continue asset_abs_url = urljoin(page_url, src_path) local_path = download_asset(asset_abs_url, asset_dir) if local_path: tag["src"] = local_path # 处理所有带href属性的标签(样式表、图标等) for tag in soup.find_all(href=True): href_path = tag["href"] if href_path.startswith("data:"): continue # 仅下载媒体类资源,跳过外站跳转链接 if not any(ext in href_path for ext in [".css", ".png", ".jpg", ".jpeg", ".gif", ".ico"]): continue asset_abs_url = urljoin(page_url, href_path) local_path = download_asset(asset_abs_url, asset_dir) if local_path: tag["href"] = local_path # 保存处理完成的HTML文件 with open(page_name, "wb") as f: f.write(soup.prettify("utf-8")) # 加延时避免给目标服务器造成过大压力 time.sleep(1)
注意事项
- 所有文件写入采用
with上下文管理器,避免文件句柄泄漏、写入内容不完整的问题 - 该逻辑完全匹配浏览器「另存为完整网页」的效果,本地打开保存的HTML时可以正常加载所有图片、样式资源,不会出现裂链
- 如果遇到跨域的资源路径,只需要在
download_asset函数中补全对应域的请求头配置即可正常下载
内容的提问来源于stack exchange,提问作者Fomorian
相关产品推荐
相关产品推荐

