位置: 文档库 > Python > python爬取百度美女图片

python爬取百度美女图片

江山如画 上传于 2023-01-15 05:31

《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 常见反爬策略

User-Agent检测

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爬虫初学者和进阶开发者学习参考。