使用 Python 爬虫批量下载百度图片的详细教程

时间:2024-10-14 07:07:56

引言

在网络上批量下载图片是一项常见的需求,无论是做图像数据集还是收集素材。百度图片作为中文搜索引擎之一,包含了海量的图片资源。通过 Python 爬虫技术,我们可以自动化地从百度图片中批量下载所需的图片。本教程将详细介绍如何使用 Python 爬虫来实现百度图片的批量下载,包括必要的环境配置、代码实现及相关注意事项。

环境配置

在开始之前,需要确保以下环境和工具已正确配置:

  1. Python:建议使用 Python 3.x 版本。
  2. 安装依赖库:我们将用到以下 Python 库:
    • requests:发送 HTTP 请求,获取网页数据。
    • re:正则表达式,用于解析网页内容。
    • os:文件操作,创建文件夹,保存图片等。
    • Pillow:用于处理图片,检测下载图片是否损坏(可选)。
    • beautifulsoup4:解析 HTML 网页结构(如果需要更复杂的爬取策略,可选)。
    • lxml:用于快速解析 HTML(可选,和 beautifulsoup4 配合使用)。

安装依赖库

在命令行或终端中,运行以下命令来安装依赖的 Python 库:

pip install requests pillow beautifulsoup4 lxml

爬虫流程概述

我们可以通过以下几个步骤实现百度图片的批量下载:

  1. 访问百度图片的搜索结果页面。
  2. 分析网页结构,找到图片的 URL 地址。
  3. 解析并提取图片链接。
  4. 下载并保存图片到本地。

第一步:构造搜索请求

百度图片的搜索请求格式大致如下:

https://image.baidu.com/search/index?tn=baiduimage&word=关键词

其中,word 是你要搜索的图片关键词。为了确保编码正确,我们需要将关键词进行 URL 编码。Python 中可以通过 urllib.parse.quote 来实现。

代码示例:

import requests
from urllib.parse import quote

# 百度图片的搜索 URL
def get_baidu_image_search_url(keyword):
    base_url = "https://image.baidu.com/search/index?tn=baiduimage&word="
    keyword_encoded = quote(keyword)
    return base_url + keyword_encoded

# 示例:搜索“猫咪”相关图片
search_url = get_baidu_image_search_url("猫咪")
print(search_url)

第二步:解析网页,提取图片链接

百度图片搜索结果的页面结构中包含了很多信息,但我们只需要其中的图片 URL。通常图片 URL 会出现在 HTML 的 <img> 标签或 JavaScript 代码中。

我们可以使用正则表达式来解析图片 URL,但为了更稳定,我们可以使用 beautifulsoup4lxml 库来辅助解析。

代码示例:

import requests
import re

# 获取网页内容
def get_image_urls_from_baidu(keyword, num_images=10):
    search_url = get_baidu_image_search_url(keyword)
    response = requests.get(search_url)
    
    # 检查请求是否成功
    if response.status_code != 200:
        print("Failed to retrieve search results.")
        return []
    
    html_content = response.text
    
    # 使用正则表达式查找图片的 URL
    image_urls = re.findall('"thumbURL":"(.*?)"', html_content)
    
    # 限制获取到的图片数量
    return image_urls[:num_images]

# 示例:获取猫咪图片的前10个 URL
image_urls = get_image_urls_from_baidu("猫咪", 10)
print(image_urls)

第三步:下载图片并保存到本地

接下来,我们将提取到的图片 URL 进行下载,并保存到本地文件夹中。我们将使用 os 模块来创建文件夹,并使用 requests 库的 get 方法来下载图片。

代码示例:

import os

# 创建存储图片的文件夹
def create_folder(folder_name):
    if not os.path.exists(folder_name):
        os.makedirs(folder_name)

# 下载并保存图片
def download_images(image_urls, folder_name):
    create_folder(folder_name)
    for idx, url in enumerate(image_urls):
        try:
            print(f"Downloading image {idx + 1} from {url}")
            response = requests.get(url, timeout=10)
            if response.status_code == 200:
                # 保存图片
                with open(f"{folder_name}/{idx + 1}.jpg", 'wb') as f:
                    f.write(response.content)
            else:
                print(f"Failed to download image {idx + 1}")
        except Exception as e:
            print(f"Error downloading image {idx + 1}: {e}")

# 示例:下载猫咪图片到 "cat_images" 文件夹
download_images(image_urls, "cat_images")

输出说明:

  • create_folder 函数用于创建存储图片的文件夹。
  • download_images 函数会依次访问图片链接并将图片保存到指定的文件夹中。

第四步:检测图片完整性(可选)

有时候下载的图片可能损坏或者格式不正确。我们可以通过 Pillow 库检测图片是否能被正常打开,从而筛选掉损坏的文件。

代码示例:

from PIL import Image

# 检查图片是否损坏
def is_image_valid(image_path):
    try:
        with Image.open(image_path) as img:
            img.verify()
        return True
    except (IOError, SyntaxError) as e:
        print(f"Invalid image file: {image_path}")
        return False

# 检查下载的图片是否有效
def validate_images(folder_name):
    for img_name in os.listdir(folder_name):
        img_path = os.path.join(folder_name, img_name)
        if not is_image_valid(img_path):
            os.remove(img_path)
            print(f"Removed invalid image: {img_name}")

# 示例:验证下载到的图片是否有效
validate_images("cat_images")

输出说明:

  • is_image_valid 函数会尝试打开图片,判断其是否有效。
  • validate_images 会遍历文件夹中的所有图片,并删除那些损坏或无法打开的图片。

运行示例

  1. 运行完整代码,首先抓取指定关键词的图片 URL。
  2. 将图片批量下载到本地文件夹。
  3. (可选)检测下载的图片是否有损坏,并删除无效图片。

完整的示例代码如下:

import requests
import re
import os
from urllib.parse import quote
from PIL import Image

# 构建百度图片搜索URL
def get_baidu_image_search_url(keyword):
    base_url = "https://image.baidu.com/search/index?tn=baiduimage&word="
    keyword_encoded = quote(keyword)
    return base_url + keyword_encoded

# 获取图片 URL
def get_image_urls_from_baidu(keyword, num_images=10):
    search_url = get_baidu_image_search_url(keyword)
    response = requests.get(search_url)
    if response.status_code != 200:
        print("Failed to retrieve search results.")
        return []
    html_content = response.text
    image_urls = re.findall('"thumbURL":"(.*?)"', html_content)
    return image_urls[:num_images]

# 创建文件夹
def create_folder(folder_name):
    if not os.path.exists(folder_name):
        os.makedirs(folder_name)

# 下载图片
def download_images(image_urls, folder_name):
    create_folder(folder_name)
    for idx, url in enumerate(image_urls):
        try:
            print(f"Downloading image {idx + 1} from {url}")
            response = requests.get(url, timeout=10)
            if response.status_code == 200:
                with open(f"{folder_name}/{idx + 1}.jpg", 'wb') as f:
                    f.write(response.content)
            else:
                print(f"Failed to download image {idx + 1}")
        except Exception as e:
            print(f"Error downloading image {idx + 1}: {e}")

# 检查图片是否损坏
def is_image_valid(image_path):
    try:
        with Image.open(image_path) as img:
            img.verify()
        return True
    except (IOError, SyntaxError) as e:
        print(f"Invalid image file: {image_path}")
        return False

# 验证图片
def validate_images(folder_name):
    for img_name in os.listdir(folder_name):
        img_path = os.path.join(folder_name, img_name)
        if not is_image_valid(img_path):
            os.remove(img_path)
            print(f"Removed invalid image: {img_name}")

# 主程序
if __name__ == "__main__":
    keyword = "猫咪"
    image_urls = get_image_urls_from_baidu(keyword, 10)
    download_images(image_urls, "cat_images")
    validate_images("cat_images")

结论

通过本教程,我们使用 Python 实现了从百度图片批量下载图片的爬虫程序。我们学习了如何构造请求、解析图片 URL、批量下载图片,以及如何检测图片的完整性。