怎样用脚本自动下载网页中的所有资源?

wen 实用脚本 4

本文目录导读:

怎样用脚本自动下载网页中的所有资源?

  1. 使用 wget(最简单)
  2. 使用 Python + requests + BeautifulSoup
  3. 使用 selenium(处理JavaScript动态加载)
  4. 使用专业工具 - HTTrack
  5. 完整的批量下载脚本
  6. 使用建议
  7. 注意事项

要自动下载网页中的所有资源,可以使用多种方法,我推荐几种实用方案:

使用 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()

使用建议

  1. 简单场景:使用 wget 命令
  2. 需要解析:使用 Python + BeautifulSoup
  3. 动态网站:使用 Selenium
  4. 完整镜像:使用 HTTrack
  5. 高效下载:使用异步脚本

注意事项

  • 尊重网站的 robots.txt 和使用条款
  • 注意不要对服务器造成过大压力(限制并发数)
  • 有些资源可能需要处理反爬虫机制
  • 动态加载的内容需要更复杂的处理

选择哪种方法取决于你的具体需求和网页的复杂度。

抱歉,评论功能暂时关闭!