大家好,我是何三,80后老猿,独立开发者。

继续我们的"5分钟Python自动化"系列。今天我们来解决一个网络资源收集的刚需——批量下载网页图片

有这样的场景:你在做一个设计项目,需要大量参考图片;你在收集某个主题的资料,网页上有上百张相关图片;你想备份某个网站的所有产品图片;或者你看到了一个很棒的图片合集,想要全部保存到本地...

传统做法:右键另存为,一张一张保存,遇到几十上百张图片时,手指都要点抽筋,还容易出错漏掉。

Python做法:15行代码,3秒钟,自动识别网页所有图片,一键批量下载到本地!

今天,我就带你用5分钟,掌握这个让你成为"资源收割机"的神奇技能!

环境准备:两个命令搞定

在开始之前,你只需要:

  1. 安装Python(这个已经装好了)
  2. 安装必要的库:打开命令行,依次输入:
pip install requests
pip install beautifulsoup4

这两个库分别是: - requests:HTTP请求库,用来获取网页内容 - beautifulsoup4:HTML解析库,用来提取图片链接

核心代码:15行图片批量下载器

让我们先看看这个最简单的"图片收割机":

import requests
from bs4 import BeautifulSoup
import os

def download_images(url, save_folder='images'):
    """下载网页上的所有图片"""

    # 创建保存文件夹
    os.makedirs(save_folder, exist_ok=True)

    # 获取网页内容
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')

    # 查找所有图片标签
    img_tags = soup.find_all('img')

    # 下载每张图片
    for i, img in enumerate(img_tags):
        img_url = img.get('src')

        if img_url:  # 确保有图片链接
            # 补全相对链接
            if not img_url.startswith('http'):
                img_url = url + img_url if img_url.startswith('/') else url + '/' + img_url

            try:
                # 下载图片
                img_data = requests.get(img_url).content

                # 保存图片
                img_name = f'image_{i+1}.jpg'
                img_path = os.path.join(save_folder, img_name)

                with open(img_path, 'wb') as f:
                    f.write(img_data)

                print(f'已下载: {img_name}')
            except Exception as e:
                print(f'下载失败: {img_url} - {e}')

# 使用示例
download_images('https://www.h3blog.com')

逐行详解:理解图片下载的原理

第1-3行:导入核心工具箱

import requests
from bs4 import BeautifulSoup
import os
  • requests:负责网络请求,像浏览器一样获取网页数据
  • BeautifulSoup:负责解析HTML,像剪刀一样提取图片链接
  • os:负责文件操作,创建文件夹和保存文件

第5-9行:定义下载函数

def download_images(url, save_folder='images'):
    """下载网页上的所有图片"""

    # 创建保存文件夹
    os.makedirs(save_folder, exist_ok=True)
  • url:要下载图片的网页地址
  • save_folder:保存图片的文件夹名
  • os.makedirs():创建文件夹,exist_ok=True表示如果文件夹已存在也不报错

第11-15行:获取并解析网页

    # 获取网页内容
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')

    # 查找所有图片标签
    img_tags = soup.find_all('img')
  • requests.get(url):发送HTTP请求,获取网页源代码
  • BeautifulSoup(response.text, 'html.parser'):将网页源代码转换成可解析的对象
  • soup.find_all('img'):找到网页中所有的<img>标签

第17-35行:下载每张图片

    for i, img in enumerate(img_tags):
        img_url = img.get('src')

        if img_url:  # 确保有图片链接
            # 补全相对链接
            if not img_url.startswith('http'):
                img_url = url + img_url if img_url.startswith('/') else url + '/' + img_url

            try:
                # 下载图片
                img_data = requests.get(img_url).content

                # 保存图片
                img_name = f'image_{i+1}.jpg'
                img_path = os.path.join(save_folder, img_name)

                with open(img_path, 'wb') as f:
                    f.write(img_data)

                print(f'已下载: {img_name}')
            except Exception as e:
                print(f'下载失败: {img_url} - {e}')

关键步骤分解

  1. 提取图片链接img.get('src')获取<img>标签的src属性值
  2. 处理相对链接:如果是相对路径(如/images/pic.jpg),需要补全为完整URL
  3. 下载图片数据requests.get(img_url).content获取图片的二进制数据
  4. 保存到文件:以二进制写入模式('wb')保存图片
  5. 错误处理:使用try-except捕获下载失败的情况

实战演示:3秒批量下载图片

  1. 保存脚本:将上面的代码保存为download_images.py
  2. 修改URL:把https://example.com换成你想下载图片的网页地址
  3. 运行脚本:打开命令行,输入:
python download_images.py
  1. 查看结果:当前目录会创建一个images文件夹,里面就是下载的所有图片!

运行效果

已下载: image_1.jpg
已下载: image_2.jpg
已下载: image_3.jpg
...
下载失败: https://example.com/ad.jpg - 404 Not Found
总共下载了: 25张图片

举一反三:高级图片下载功能

案例1:下载特定尺寸的图片

def download_large_images(url, min_width=400, min_height=300):
    """只下载大尺寸图片"""

    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')

    for img in soup.find_all('img'):
        img_url = img.get('src')
        img_width = img.get('width')
        img_height = img.get('height')

        # 检查图片尺寸
        if img_width and img_height:
            if int(img_width) >= min_width and int(img_height) >= min_height:
                # 下载大图
                download_single_image(img_url)

案例2:按类别下载图片

def download_by_category(url, categories):
    """按类别下载图片"""

    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')

    for img in soup.find_all('img'):
        img_url = img.get('src')
        alt_text = img.get('alt', '').lower()  # 获取alt文本

        for category in categories:
            if category in alt_text or category in img_url:
                # 按类别创建文件夹
                category_folder = os.path.join('images', category)
                os.makedirs(category_folder, exist_ok=True)

                # 下载图片到对应文件夹
                download_to_folder(img_url, category_folder)
                break

案例3:从多个网页批量下载

def download_from_multiple_pages(base_url, page_count):
    """从多个页面下载图片"""

    all_images = []

    for page in range(1, page_count + 1):
        # 构造每个页面的URL
        page_url = f'{base_url}?page={page}'
        print(f'正在处理第 {page} 页...')

        # 获取当前页面的图片
        page_images = get_images_from_page(page_url)
        all_images.extend(page_images)

    # 下载所有图片
    for i, img_url in enumerate(all_images):
        download_single_image(img_url, f'image_{i+1}.jpg')
        print(f'进度: {i+1}/{len(all_images)}')

    print(f'下载完成!共下载了 {len(all_images)} 张图片')

案例4:下载高清原图

def download_hd_images(url):
    """下载高清原图(通常data-src属性存放原图)"""

    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')

    for img in soup.find_all('img'):
        # 优先使用data-src(通常是高清图)
        hd_url = img.get('data-src') or img.get('data-original')

        if hd_url:
            # 下载高清图
            download_single_image(hd_url, prefix='hd_')
        else:
            # 回退到普通src
            normal_url = img.get('src')
            if normal_url:
                download_single_image(normal_url)

进阶技巧:企业级图片下载系统

添加请求头模拟浏览器

def download_with_headers(url):
    """使用请求头模拟浏览器访问"""

    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
        'Accept-Encoding': 'gzip, deflate',
        'Connection': 'keep-alive',
    }

    # 使用请求头访问
    response = requests.get(url, headers=headers)
    # ... 后续处理

多线程加速下载

import threading
from concurrent.futures import ThreadPoolExecutor

def download_images_fast(url, max_workers=5):
    """多线程快速下载图片"""

    # 获取所有图片链接
    img_urls = get_all_image_urls(url)

    # 使用线程池并发下载
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        futures = []
        for i, img_url in enumerate(img_urls):
            future = executor.submit(download_single_image, img_url, f'image_{i+1}.jpg')
            futures.append(future)

        # 等待所有任务完成
        for future in futures:
            future.result()

    print(f'快速下载完成!共下载 {len(img_urls)} 张图片')

断点续传功能

def download_with_resume(url, filename):
    """支持断点续传的下载"""

    # 检查文件是否已部分下载
    if os.path.exists(filename):
        file_size = os.path.getsize(filename)
        headers = {'Range': f'bytes={file_size}-'}
    else:
        file_size = 0
        headers = {}

    # 从断点处继续下载
    response = requests.get(url, headers=headers, stream=True)

    with open(filename, 'ab' if file_size > 0 else 'wb') as f:
        for chunk in response.iter_content(chunk_size=8192):
            if chunk:
                f.write(chunk)

    print(f'下载完成: {filename}')

图片去重功能

import hashlib

def get_image_hash(img_data):
    """计算图片的哈希值(用于去重)"""
    return hashlib.md5(img_data).hexdigest()

def download_unique_images(url):
    """下载不重复的图片"""

    downloaded_hashes = set()  # 存储已下载图片的哈希值

    img_urls = get_all_image_urls(url)

    for img_url in img_urls:
        try:
            # 下载图片
            response = requests.get(img_url, timeout=10)
            img_data = response.content

            # 计算哈希值
            img_hash = get_image_hash(img_data)

            # 检查是否重复
            if img_hash not in downloaded_hashes:
                # 保存图片
                save_image(img_data, img_url)
                downloaded_hashes.add(img_hash)
                print(f'下载新图片: {img_url}')
            else:
                print(f'跳过重复图片: {img_url}')

        except Exception as e:
            print(f'下载失败: {img_url} - {e}')

实用场景:图片下载的多种应用

场景1:下载电商网站产品图

def download_product_images(shop_url, product_count=50):
    """下载电商网站产品图片"""

    # 模拟真实浏览器访问
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        'Referer': shop_url
    }

    # 分析网站结构,获取产品图片
    response = requests.get(shop_url, headers=headers)
    soup = BeautifulSoup(response.text, 'html.parser')

    # 根据网站结构选择正确的选择器
    product_images = []

    # 常见电商网站图片选择器
    selectors = [
        '.product-image img',
        '.goods-img',
        '.item-img',
        '[data-product-image]'
    ]

    for selector in selectors:
        images = soup.select(selector)
        if images:
            product_images.extend([img.get('src') for img in images])
            break

    # 下载产品图片
    for i, img_url in enumerate(product_images[:product_count]):
        # 通常产品图有高清版本
        hd_url = img_url.replace('thumbnail', 'original').replace('small', 'large')
        download_single_image(hd_url, f'product_{i+1}.jpg')

场景2:下载壁纸网站高清壁纸

def download_wallpapers(wallpaper_site, resolution='1920x1080'):
    """下载指定分辨率的壁纸"""

    # 构造壁纸下载URL(不同网站格式不同)
    if 'wallhaven' in wallpaper_site:
        # wallhaven.cc
        search_url = f'{wallpaper_site}/search?q=&resolutions={resolution}'
    elif 'unsplash' in wallpaper_site:
        # unsplash.com
        search_url = f'{wallpaper_site}/s/photos/desktop-wallpaper?orientation=landscape'

    # 获取壁纸链接
    response = requests.get(search_url)
    soup = BeautifulSoup(response.text, 'html.parser')

    # 下载壁纸
    wallpaper_count = 0
    for img in soup.find_all('img'):
        img_url = img.get('src')

        # 检查是否是壁纸图片
        if img_url and ('wallpaper' in img_url or resolution in img_url):
            download_single_image(img_url, f'wallpaper_{wallpaper_count+1}.jpg')
            wallpaper_count += 1

            if wallpaper_count >= 20:  # 限制下载数量
                break

    print(f'下载了 {wallpaper_count}{resolution} 壁纸')

场景3:批量下载社交媒体图片

def download_social_media_images(profile_url, platform='instagram'):
    """下载社交媒体图片"""

    # 不同平台需要不同的处理方法
    if platform == 'instagram':
        # Instagram图片通常在meta标签中
        response = requests.get(profile_url)

        # 使用正则表达式提取图片URL
        import re
        image_patterns = [
            r'"display_url":"([^"]+)"',  # Instagram JSON格式
            r'property="og:image" content="([^"]+)"'  # Open Graph
        ]

        all_images = []
        for pattern in image_patterns:
            matches = re.findall(pattern, response.text)
            all_images.extend(matches)

    elif platform == 'pinterest':
        # Pinterest使用不同的数据结构
        soup = BeautifulSoup(response.text, 'html.parser')
        all_images = []
        for img in soup.select('img[src*="pinimg.com"]'):
            img_url = img.get('src')
            # 获取原图(去除尺寸参数)
            original_url = img_url.split('?')[0]
            all_images.append(original_url)

    # 下载所有图片
    for i, img_url in enumerate(set(all_images)):  # 使用set去重
        download_single_image(img_url, f'{platform}_{i+1}.jpg')

注意事项与最佳实践

1. 遵守robots.txt和网站条款

def check_robots_txt(url):
    """检查robots.txt文件"""

    from urllib.parse import urlparse

    # 获取网站根域名
    parsed_url = urlparse(url)
    robots_url = f'{parsed_url.scheme}://{parsed_url.netloc}/robots.txt'

    try:
        response = requests.get(robots_url)
        print(f"robots.txt内容:\n{response.text[:500]}...")

        # 检查是否允许爬取
        if 'Disallow: /' in response.text:
            print("警告:该网站可能禁止爬取!")
    except:
        print("未找到robots.txt文件")

2. 添加延迟避免被封IP

import time
import random

def download_with_delay(url, delay_range=(1, 3)):
    """添加随机延迟下载"""

    img_urls = get_all_image_urls(url)

    for i, img_url in enumerate(img_urls):
        # 下载图片
        download_single_image(img_url)

        # 添加随机延迟
        delay = random.uniform(delay_range[0], delay_range[1])
        time.sleep(delay)

        print(f'进度: {i+1}/{len(img_urls)},等待 {delay:.1f} 秒')

3. 错误重试机制

def download_with_retry(img_url, max_retries=3):
    """带有重试机制的下载"""

    for attempt in range(max_retries):
        try:
            response = requests.get(img_url, timeout=10)
            response.raise_for_status()  # 检查HTTP错误

            # 保存图片
            with open(f'image.jpg', 'wb') as f:
                f.write(response.content)

            print(f'下载成功: {img_url}')
            return True

        except Exception as e:
            print(f'第 {attempt+1} 次尝试失败: {e}')
            if attempt < max_retries - 1:
                wait_time = 2 ** attempt  # 指数退避
                print(f'等待 {wait_time} 秒后重试...')
                time.sleep(wait_time)

    print(f'下载失败,已达到最大重试次数: {img_url}')
    return False

结语:让网络资源为你所用

恭喜!在又一个5分钟内,你掌握了一个强大的网络资源收集技能:

✅ 用15行代码批量下载网页图片
✅ 掌握requests和BeautifulSoup的基本使用
✅ 学会处理相对链接和错误情况
✅ 具备构建高级下载系统的能力

今天你学会的不仅仅是下载图片,而是掌握了自动化获取网络资源的方法论。

想象一下,你还可以: - 批量下载某个主题的所有参考图片 - 自动备份你喜欢的网站图片资源 - 为机器学习项目收集训练图片 - 监控竞争对手的产品图片更新 - 构建自己的图片素材库

信息时代,重要的不是拥有多少资源,而是知道如何快速获取需要的资源。

现在,就找一个你感兴趣的网站,试试批量下载它的图片吧!在评论区分享你下载了什么有趣的图片,或者遇到了什么挑战!

记得关注我,下一篇我们挑战更有趣的Python自动化技巧!