[Python]编写一个简易爬虫模型——爬取百度百科图片链接

[Python]编写一个简易爬虫模型——爬取百度百科图片链接

一、背景与问题

在互联网数据挖掘领域,爬虫技术是获取结构化数据的核心手段之一。百度百科作为中文百科全书的重要载体,其词条页面中包含大量图片资源。在实际开发中,我们可能需要批量获取特定分类下的图片资源用于知识图谱构建、多媒体数据库建设等场景。

传统方式需要手动下载图片,但面对成千上万的词条时,这种效率显然无法满足需求。本项目将构建一个基于Python的简易爬虫模型,重点探讨HTTP协议、HTML解析、反爬机制处理等关键技术点。

二、基本原理

1. HTTP协议基础

爬虫工作基于HTTP协议,通过发送GET/POST请求获取网页内容。百度百科使用的是标准的HTTP/1.1协议,每个请求需要包含:

  • User-Agent头(模拟浏览器)
  • Accept-Language头(指定语言)
  • Referer头(防止CSRF攻击)

2. HTML解析机制

网页内容为HTML文档,需要使用解析器提取所需数据。BeautifulSoup库通过以下步骤完成解析:

  1. 使用requests获取原始HTML
  2. 通过BeautifulSoup(html, 'html.parser')创建解析对象
  3. 使用CSS选择器或XPath定位目标元素
  4. 提取img标签的src属性

3. 反爬机制应对

百度百科主要采用以下反爬策略:

  • 验证码识别(需额外OCR服务)
  • IP封禁(使用代理IP池)
  • 请求频率限制(需添加延时)
  • 防止重复请求(需记录请求日志)

三、环境准备

pip install requests beautifulsoup4

需要配置的环境变量:

import os
os.environ['USER_AGENT'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4443.116 Safari/537.36'

四、核心实现

1. 基础请求模块

import requests

def fetch_page(url):
    headers = {
        'User-Agent': 'Mozilla/5.0',
        'Accept-Language': 'zh-CN,zh;q=0.9',
        'Referer': 'https://www.baidu.com/'
    }
    try:
        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status()
        return response.text
    except requests.RequestException as e:
        print(f"请求失败: {e}")
        return None

关键点解释:

  • 使用headers模拟浏览器行为
  • 添加超时机制防止死锁
  • 异常处理确保程序健壮性

2. HTML解析模块

from bs4 import BeautifulSoup

def parse_page(html):
    soup = BeautifulSoup(html, 'html.parser')
    img_tags = soup.select('img[src]')
    return [img['src'] for img in img_tags if 'src' in img.attrs]

关键点解释:

  • 使用html.parser解析器处理中文字符
  • 通过CSS选择器定位所有图片标签
  • 过滤无效属性确保数据质量

3. 反爬机制处理模块

import time
import random

def get_random_proxy():
    # 模拟代理IP池获取
    return '127.0.0.1:8080'

def safe_request(url):
    proxy = get_random_proxy()
    headers = {
        'User-Agent': 'Mozilla/5.0',
        'Accept-Language': 'zh-CN,zh;q=0.9',
        'Referer': 'https://www.baidu.com/',
        'X-Forwarded-For': '192.168.1.100'
    }
    try:
        response = requests.get(url, headers=headers, proxies={'http': proxy}, timeout=10)
        response.raise_for_status()
        return response.text
    except requests.RequestException as e:
        print(f"请求失败: {e}")
        return None
    finally:
        time.sleep(random.uniform(1, 3))  # 随机延时防止触发反爬

关键点解释:

  • 使用代理IP池应对IP封禁
  • 添加随机延时防止请求频率过高
  • 设置X-Forwarded-For头伪装来源

五、完整案例

1. 爬取"Python"词条图片

def main():
    url = 'https://baike.baidu.com/item/Python'
    html = safe_request(url)
    if html:
        img_urls = parse_page(html)
        print(f"共找到{len(img_urls)}张图片:")
        for i, img_url in enumerate(img_urls):
            print(f"{i+1}. {img_url}")

运行结果示例:

共找到12张图片:
1. https://bkimg.izhao.com/...
2. https://image.baike.com/...
...
12. https://www.baidu.com/img/...

2. 数据存储优化

import json

def save_to_file(data, filename):
    with open(filename, 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=2)

3. 异常处理增强

def fetch_page_with_retry(url, max_retries=3):
    for attempt in range(max_retries):
        html = safe_request(url)
        if html:
            return html
        print(f"第{attempt+1}次尝试失败,10秒后重试...")
        time.sleep(10)
    return None

六、源码解析

1. 请求处理流程

def safe_request(url):
    # 1. 获取代理IP
    proxy = get_random_proxy()
    # 2. 构造请求头
    headers = {
        'User-Agent': 'Mozilla/5.0',
        'Accept-Language': 'zh-CN,zh;q=0.9',
        'Referer': 'https://www.baidu.com/',
        'X-Forwarded-For': '192.168.1.100'
    }
    # 3. 发送请求
    response = requests.get(url, headers=headers, proxies={'http': proxy}, timeout=10)
    # 4. 异常处理
    response.raise_for_status()
    # 5. 随机延时
    time.sleep(random.uniform(1, 3))
    return response.text

2. 解析逻辑分析

def parse_page(html):
    soup = BeautifulSoup(html, 'html.parser')
    # 使用CSS选择器定位所有图片标签
    img_tags = soup.select('img[src]')
    # 筛选有效URL
    return [img['src'] for img in img_tags if 'src' in img.attrs]

七、进阶使用

1. 多线程优化

from concurrent.futures import ThreadPoolExecutor

def batch_fetch(urls, max_workers=5):
    results = []
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        for url in urls:
            result = executor.submit(fetch_page, url)
            results.append(result)
    return [r.result() for r in results]

2. 数据持久化方案

import sqlite3

def save_to_db(img_urls):
    conn = sqlite3.connect('baidu_images.db')
    c = conn.cursor()
    c.execute('CREATE TABLE IF NOT EXISTS images (url TEXT PRIMARY KEY)')
    c.executemany('INSERT OR IGNORE INTO images (url) VALUES (?)', [(u,) for u in img_urls])
    conn.commit()
    conn.close()

3. 分页处理方案

def get_page_urls(base_url, page_size=20):
    page_urls = []
    for i in range(1, 6):  # 爬取前5页
        page_urls.append(f"{base_url}?pn={i}")
    return page_urls

八、性能与工程实践

1. 性能优化策略

优化措施效果实现方式
随机延时避免触发反爬time.sleep()
代理IP池应对IP封禁随机获取代理
缓存机制减少重复请求使用Redis缓存
并发控制提高效率多线程/异步IO

2. 异常处理规范

def safe_request(url):
    try:
        # 请求逻辑
    except requests.Timeout:
        print("请求超时")
    except requests.TooManyRedirects:
        print("重定向过多")
    except requests.ConnectionError:
        print("网络连接失败")
    except Exception as e:
        print(f"未知错误: {e}")

3. 安全风险分析

  • robots.txt规则:百度百科robots.txt禁止爬虫访问
  • 验证码识别:部分词条包含验证码图片
  • 法律风险:需遵守《计算机软件保护条例》
  • 数据滥用:需确保图片使用符合授权协议

九、常见问题与踩坑

1. 常见错误示例

# 错误示例:未处理异常
def bad_request(url):
    response = requests.get(url)
    return response.text

问题分析:

  • 缺少异常处理导致程序崩溃
  • 未设置User-Agent触发反爬
  • 未处理超时请求

2. 解决方案

# 改进版
def safe_request(url):
    try:
        response = requests.get(url, timeout=10)
        response.raise_for_status()
        return response.text
    except requests.RequestException as e:
        print(f"请求失败: {e}")
        return None

3. 常见陷阱

陷阱类型解决方案
IP被封使用代理池并定期更换
验证码集成OCR服务或人工处理
网络波动添加重试机制
数据不一致使用缓存策略

十、最佳实践

1. 开发规范

  • 使用requests.Session()保持会话
  • 实现请求重试机制
  • 使用logging模块替代print
  • 添加请求日志记录功能

2. 代码组织建议

baidu_crawler/
│
├── main.py              # 入口文件
├── utils/
│   ├── request.py       # 请求处理模块
│   └── parser.py        # 解析模块
├── config/
│   └── settings.py      # 配置文件
└── data/
    └── images.json      # 存储结果

3. 可维护性建议

  • 使用配置文件管理参数
  • 将核心逻辑封装成函数
  • 添加单元测试用例
  • 使用版本控制管理代码

十一、总结

本项目构建了一个完整的爬虫系统,涵盖从请求发送到数据提取的全流程。通过分析百度百科的反爬机制,我们探讨了请求头配置、代理IP池、随机延时等关键技术点。在实际开发中,这种方案适用于:

  • 知识图谱构建
  • 多媒体数据库建设
  • 网络数据采集
  • 历史数据存档

但需注意:

  • 避免大规模采集敏感数据
  • 遵守网站robots.txt规则
  • 定期更新反爬策略
  • 遵守相关法律法规

对于高并发场景,建议采用分布式爬虫架构,结合消息队列和数据库分库分表策略。在实施过程中,需要根据具体业务需求调整爬虫策略,确保在效率与合规性之间取得平衡。

最后修改于:2026年09月19日 05:19

评论已关闭

推荐阅读

AIGC实战——Transformer模型
2024年12月01日
Socket TCP 和 UDP 编程基础(Python)
2024年11月30日
python , tcp , udp
如何使用 ChatGPT 进行学术润色?你需要这些指令
2024年12月01日
AI
最新 Python 调用 OpenAi 详细教程实现问答、图像合成、图像理解、语音合成、语音识别(详细教程)
2024年11月24日
ChatGPT 和 DALL·E 2 配合生成故事绘本
2024年12月01日
omegaconf,一个超强的 Python 库!
2024年11月24日
【视觉AIGC识别】误差特征、人脸伪造检测、其他类型假图检测
2024年12月01日
[超级详细]如何在深度学习训练模型过程中使用 GPU 加速
2024年11月29日
Python 物理引擎pymunk最完整教程
2024年11月27日
MediaPipe 人体姿态与手指关键点检测教程
2024年11月27日
深入了解 Taipy:Python 打造 Web 应用的全面教程
2024年11月26日
基于Transformer的时间序列预测模型
2024年11月25日
Python在金融大数据分析中的AI应用(股价分析、量化交易)实战
2024年11月25日
AIGC Gradio系列学习教程之Components
2024年12月01日
Python3 `asyncio` — 异步 I/O,事件循环和并发工具
2024年11月30日
llama-factory SFT系列教程:大模型在自定义数据集 LoRA 训练与部署
2024年12月01日
Python 多线程和多进程用法
2024年11月24日
Python socket详解,全网最全教程
2024年11月27日
python之plot()和subplot()画图
2024年11月26日
理解 DALL·E 2、Stable Diffusion 和 Midjourney 工作原理
2024年12月01日