引言
在网络上批量下载图片是一项常见的需求,无论是做图像数据集还是收集素材。百度图片作为中文搜索引擎之一,包含了海量的图片资源。通过 Python 爬虫技术,我们可以自动化地从百度图片中批量下载所需的图片。本教程将详细介绍如何使用 Python 爬虫来实现百度图片的批量下载,包括必要的环境配置、代码实现及相关注意事项。
环境配置
在开始之前,需要确保以下环境和工具已正确配置:
- Python:建议使用 Python 3.x 版本。
-
安装依赖库:我们将用到以下 Python 库:
-
requests
:发送 HTTP 请求,获取网页数据。 -
re
:正则表达式,用于解析网页内容。 -
os
:文件操作,创建文件夹,保存图片等。 -
Pillow
:用于处理图片,检测下载图片是否损坏(可选)。 -
beautifulsoup4
:解析 HTML 网页结构(如果需要更复杂的爬取策略,可选)。 -
lxml
:用于快速解析 HTML(可选,和beautifulsoup4
配合使用)。
-
安装依赖库
在命令行或终端中,运行以下命令来安装依赖的 Python 库:
pip install requests pillow beautifulsoup4 lxml
爬虫流程概述
我们可以通过以下几个步骤实现百度图片的批量下载:
- 访问百度图片的搜索结果页面。
- 分析网页结构,找到图片的 URL 地址。
- 解析并提取图片链接。
- 下载并保存图片到本地。
第一步:构造搜索请求
百度图片的搜索请求格式大致如下:
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,但为了更稳定,我们可以使用 beautifulsoup4
和 lxml
库来辅助解析。
代码示例:
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
会遍历文件夹中的所有图片,并删除那些损坏或无法打开的图片。
运行示例
- 运行完整代码,首先抓取指定关键词的图片 URL。
- 将图片批量下载到本地文件夹。
- (可选)检测下载的图片是否有损坏,并删除无效图片。
完整的示例代码如下:
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、批量下载图片,以及如何检测图片的完整性。