《Python爬取百度美女图片》
在互联网数据爆炸的时代,如何高效获取特定类型的图片资源成为开发者关注的焦点。本文将以爬取百度图片搜索结果中的"美女"类图片为例,系统讲解Python爬虫的完整实现流程,涵盖网络请求、数据解析、文件存储等核心技术点,同时深入探讨反爬机制应对策略。
一、环境准备与基础配置
1.1 开发环境搭建
# 创建虚拟环境(推荐)
python -m venv baidu_spider_env
source baidu_spider_env/bin/activate # Linux/Mac
.\baidu_spider_env\Scripts\activate # Windows
# 安装必要库
pip install requests beautifulsoup4 lxml pillow fake_useragent
1.2 核心库功能说明
requests:处理HTTP请求
BeautifulSoup4:HTML解析
lxml:加速解析过程
Pillow:图片处理
fake_useragent:生成随机User-Agent
二、网络请求实现
2.1 基础请求构造
import requests
from fake_useragent import UserAgent
def get_html(url):
headers = {
'User-Agent': UserAgent().random,
'Referer': 'https://image.baidu.com/'
}
try:
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
return response.text
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
return None
2.2 参数化搜索接口
百度图片搜索采用动态URL参数,关键参数包括:
word:搜索关键词(需URL编码)
pn:偏移量(每页30张图片)
rn:返回数量
from urllib.parse import quote
def build_search_url(keyword, page):
base_url = "https://image.baidu.com/search/acjson"
params = {
'tn': 'resultjson_com',
'ipn': 'rj',
'ct': 201326592,
'is': '',
'fp': 'result',
'queryWord': quote(keyword),
'cl': 2,
'lm': -1,
'ie': 'utf-8',
'oe': 'utf-8',
'adpicid': '',
'st': -1,
'z': '',
'ic': '',
'word': quote(keyword),
's': '',
'se': '',
'tab': '',
'width': '',
'height': '',
'face': 0,
'istype': 2,
'qc': '',
'nc': 1,
'fr': '',
'pn': page * 30,
'rn': 30
}
return f"{base_url}?{'&'.join([f'{k}={v}' for k, v in params.items()])}"
三、数据解析与提取
3.1 JSON格式响应处理
百度图片搜索返回JSONP格式数据,需截取有效部分:
import json
import re
def parse_json_response(html):
# 提取JSON部分(去除前缀和后缀)
json_str = re.search(r'\(({.*?})\)', html).group(1)
try:
data = json.loads(json_str)
return data['data']
except (KeyError, json.JSONDecodeError) as e:
print(f"JSON解析错误: {e}")
return []
3.2 图片信息提取
每张图片包含多个尺寸版本,优先获取大图URL:
def extract_image_info(item):
if not item or 'thumbURL' not in item:
return None
image_info = {
'thumb_url': item['thumbURL'],
'middle_url': item.get('middleURL', ''),
'large_url': '',
'width': item.get('width', 0),
'height': item.get('height', 0),
'obj_url': ''
}
# 从hoverURL中提取高清图地址
if 'hoverURL' in item and item['hoverURL']:
hover_data = item['hoverURL'].split('?')[0]
if hover_data.endswith('.jpg') or hover_data.endswith('.png'):
image_info['large_url'] = hover_data
# 备用方案:从middleURL构造
if not image_info['large_url'] and image_info['middle_url']:
image_info['large_url'] = image_info['middle_url'].replace('thumb', 'large')
return image_info
四、图片下载与存储
4.1 下载函数实现
import os
from PIL import Image
from io import BytesIO
import time
def download_image(url, save_dir, filename):
if not url or not save_dir:
return False
try:
# 创建保存目录
os.makedirs(save_dir, exist_ok=True)
# 添加随机延迟避免被封
time.sleep(0.5 + random.random())
response = requests.get(url, stream=True, timeout=15)
response.raise_for_status()
# 验证图片格式
img = Image.open(BytesIO(response.content))
if img.format not in ['JPEG', 'PNG']:
print(f"不支持的图片格式: {url}")
return False
# 保存图片
save_path = os.path.join(save_dir, filename)
img.save(save_path)
return True
except Exception as e:
print(f"下载失败 {url}: {e}")
return False
4.2 批量下载实现
import random
def batch_download(keyword, max_pages=5, save_root='images'):
for page in range(max_pages):
url = build_search_url(keyword, page)
html = get_html(url)
if not html:
continue
items = parse_json_response(html)
for idx, item in enumerate(items, 1):
img_info = extract_image_info(item)
if not img_info:
continue
# 优先使用高清图
download_url = img_info['large_url'] or img_info['middle_url'] or img_info['thumb_url']
if not download_url:
continue
# 生成文件名
ext = os.path.splitext(download_url)[1] or '.jpg'
filename = f"{keyword}_{page}_{idx}{ext}"
# 创建分类目录
category_dir = os.path.join(save_root, keyword)
download_image(download_url, category_dir, filename)
五、反爬机制应对
5.1 常见反爬策略
IP频率限制
Referer验证
Cookie跟踪
5.2 增强版请求头
def get_enhanced_headers():
ua = UserAgent()
return {
'User-Agent': ua.random,
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Accept-Encoding': 'gzip, deflate, br',
'Referer': 'https://image.baidu.com/search/index?tn=baiduimage&word=' + quote('美女'),
'DNT': '1',
'Connection': 'keep-alive'
}
5.3 IP代理池实现
import random
class ProxyPool:
def __init__(self):
self.proxies = [
{'http': 'http://110.73.45.78:8123'},
{'http': 'http://183.148.154.42:9999'},
# 添加更多可用代理
]
def get_proxy(self):
return random.choice(self.proxies)
# 使用示例
def get_html_with_proxy(url):
proxy = ProxyPool().get_proxy()
try:
return requests.get(url, headers=get_enhanced_headers(),
proxies=proxy, timeout=15)
except:
return get_html(url) # 回退到无代理请求
六、完整项目实现
6.1 主程序入口
import os
import random
import time
class BaiduImageSpider:
def __init__(self):
self.save_root = 'downloaded_images'
os.makedirs(self.save_root, exist_ok=True)
def run(self, keyword, max_pages=3):
print(f"开始爬取关键词: {keyword}")
for page in range(max_pages):
print(f"正在处理第 {page+1} 页...")
url = build_search_url(keyword, page)
html = get_html(url)
if not html:
continue
items = parse_json_response(html)
for idx, item in enumerate(items, 1):
img_info = extract_image_info(item)
if not img_info:
continue
download_url = img_info['large_url'] or img_info['middle_url']
if not download_url:
continue
ext = os.path.splitext(download_url)[1] or '.jpg'
filename = f"{keyword}_{page}_{idx}{ext}"
category_dir = os.path.join(self.save_root, keyword)
if download_image(download_url, category_dir, filename):
print(f"下载成功: {filename}")
else:
print(f"下载失败: {filename}")
# 随机延迟避免被封
time.sleep(2 + random.random() * 3)
if __name__ == '__main__':
spider = BaiduImageSpider()
spider.run('美女', max_pages=2)
6.2 扩展功能建议
添加多线程下载
实现断点续传
增加图片去重功能
开发图形界面
七、法律与道德考量
7.1 合法使用指南
仅用于个人学习研究
遵守robots.txt协议
不进行商业用途
7.2 道德规范建议
设置合理爬取频率
尊重网站服务条款
避免对服务器造成过大压力
关键词:Python爬虫、百度图片、反爬机制、数据解析、图片下载、网络请求、BeautifulSoup、requests库、代理IP、User-Agent
简介:本文详细介绍使用Python爬取百度图片搜索结果中"美女"类图片的完整实现过程,涵盖网络请求构造、JSON数据解析、图片下载存储等核心技术,同时深入探讨反爬机制应对策略,提供从环境搭建到完整项目实现的分步指导,适合Python爬虫初学者和进阶开发者学习参考。