本文目录导读:

- 使用 wget(最简单)
- 使用 Python + requests + BeautifulSoup
- 使用 selenium(处理JavaScript动态加载)
- 使用专业工具 - HTTrack
- 完整的批量下载脚本
- 使用建议
- 注意事项
要自动下载网页中的所有资源,可以使用多种方法,我推荐几种实用方案:
使用 wget(最简单)
# 下载整个网站(递归) wget -r -np -k https://example.com # 常用参数说明 wget \ -r \ # 递归下载 -np \ # 不追溯上级目录 -k \ # 转换链接为本地可用 -p \ # 下载页面所需的所有资源 -nc \ # 避免重复下载 -e robots=off \ # 忽略robots.txt -U "Mozilla/5.0" \ # 设置User-Agent -P ./download_dir \ # 指定下载目录 https://example.com
使用 Python + requests + BeautifulSoup
import requests
from bs4 import BeautifulSoup
import os
from urllib.parse import urljoin, urlparse
import re
def download_all_resources(url, output_dir="downloaded_site"):
# 创建目录
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# 下载页面
response = requests.get(url, headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
})
soup = BeautifulSoup(response.text, 'html.parser')
# 保存HTML
with open(f"{output_dir}/index.html", "w", encoding="utf-8") as f:
f.write(response.text)
# 提取并下载各种资源
resource_tags = {
'img': 'src',
'link': 'href', # CSS, favicon
'script': 'src',
'source': 'src', # video, audio
'video': 'src',
'audio': 'src',
'iframe': 'src',
'object': 'data',
'embed': 'src'
}
downloaded = set()
for tag_name, attr in resource_tags.items():
for tag in soup.find_all(tag_name):
src = tag.get(attr)
if src and not src.startswith('data:'):
# 处理相对路径
full_url = urljoin(url, src)
if full_url not in downloaded:
try:
# 下载资源
file_response = requests.get(full_url, timeout=10)
# 生成保存路径
parsed = urlparse(full_url)
file_path = parsed.path.lstrip('/')
if not file_path:
file_path = f"resource_{len(downloaded)}"
full_path = os.path.join(output_dir, file_path)
os.makedirs(os.path.dirname(full_path), exist_ok=True)
# 保存文件
with open(full_path, 'wb') as f:
f.write(file_response.content)
downloaded.add(full_url)
print(f"下载成功: {file_path}")
except Exception as e:
print(f"下载失败 {full_url}: {str(e)}")
# 使用示例
download_all_resources("https://example.com")
使用 selenium(处理JavaScript动态加载)
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import requests
import os
from urllib.parse import urljoin, urlparse
def download_dynamic_page(url, output_dir="downloaded_dynamic"):
# 设置无头浏览器
chrome_options = Options()
chrome_options.add_argument('--headless')
driver = webdriver.Chrome(options=chrome_options)
# 加载页面
driver.get(url)
# 等待JavaScript执行
driver.implicitly_wait(5)
# 获取所有资源
resources = driver.execute_script("""
var resources = [];
var elements = document.querySelectorAll('img, link[rel="stylesheet"], script[src], source, video, audio');
elements.forEach(function(elem) {
var src = elem.src || elem.href;
if (src) resources.push(src);
});
return resources;
""")
# 下载资源(同上)
# ...
driver.quit()
使用专业工具 - HTTrack
# 安装 # macOS: brew install httrack # Ubuntu: apt-get install httrack # 下载网站 httrack https://example.com -O ./mysite -%v # 或使用图形界面 httrack
完整的批量下载脚本
#!/usr/bin/env python3
import argparse
import asyncio
import aiohttp
from bs4 import BeautifulSoup
import os
from urllib.parse import urljoin, urlparse
import re
class WebResourceDownloader:
def __init__(self, max_concurrent=10):
self.semaphore = asyncio.Semaphore(max_concurrent)
self.downloaded = set()
async def download_resource(self, session, url, output_dir):
async with self.semaphore:
if url in self.downloaded:
return
self.downloaded.add(url)
try:
async with session.get(url, timeout=aiohttp.ClientTimeout(total=30)) as response:
if response.status == 200:
# 生成保存路径
parsed = urlparse(url)
file_path = parsed.path.lstrip('/')
if not file_path or file_path.endswith('/'):
file_path = f"index_{len(self.downloaded)}"
# 保存文件
full_path = os.path.join(output_dir, file_path)
os.makedirs(os.path.dirname(full_path), exist_ok=True)
content = await response.read()
with open(full_path, 'wb') as f:
f.write(content)
return file_path, content
except Exception as e:
print(f"下载失败 {url}: {e}")
return None, None
async def download_page(self, url, output_dir, depth=0, max_depth=3):
if depth > max_depth:
return
async with aiohttp.ClientSession() as session:
# 下载页面
file_path, content = await self.download_resource(session, url, output_dir)
if not content:
return
# 解析HTML
soup = BeautifulSoup(content, 'html.parser')
# 提取链接
links = set()
for tag in ['img', 'script', 'link', 'source', 'video', 'audio']:
for element in soup.find_all(tag):
src = element.get('src') or element.get('href')
if src:
full_url = urljoin(url, src)
links.add(full_url)
# 并发下载
tasks = []
for link in links:
if link not in self.downloaded:
tasks.append(self.download_resource(session, link, output_dir))
results = await asyncio.gather(*tasks)
# 递归下载子页面(可选)
for a_tag in soup.find_all('a', href=True):
href = a_tag['href']
if href.startswith('http') or href.startswith('/'):
full_url = urljoin(url, href)
if urlparse(full_url).netloc == urlparse(url).netloc: # 同域名
tasks.append(self.download_page(full_url, output_dir, depth+1, max_depth))
def main():
parser = argparse.ArgumentParser(description='下载网页所有资源')
parser.add_argument('url', help='目标URL')
parser.add_argument('-o', '--output', default='downloaded', help='输出目录')
parser.add_argument('-c', '--concurrent', type=int, default=10, help='并发数')
parser.add_argument('-d', '--depth', type=int, default=2, help='递归深度')
args = parser.parse_args()
downloader = WebResourceDownloader(args.concurrent)
asyncio.run(downloader.download_page(args.url, args.output, max_depth=args.depth))
if __name__ == '__main__':
main()
使用建议
- 简单场景:使用
wget命令 - 需要解析:使用 Python + BeautifulSoup
- 动态网站:使用 Selenium
- 完整镜像:使用 HTTrack
- 高效下载:使用异步脚本
注意事项
- 尊重网站的 robots.txt 和使用条款
- 注意不要对服务器造成过大压力(限制并发数)
- 有些资源可能需要处理反爬虫机制
- 动态加载的内容需要更复杂的处理
选择哪种方法取决于你的具体需求和网页的复杂度。