从零开始的 Python 爬虫速成指南_py爬虫速成

'# 从零开始的 Python 爬虫速成指南

一、背景与问题

在数据驱动的时代,爬虫技术已成为获取公开数据的重要手段。但传统爬虫技术存在诸多挑战:如何处理动态加载内容?如何应对反爬机制?如何保证数据可靠性?本文将深入解析 Python 爬虫的核心原理,通过三个代码示例和一个完整案例,带你掌握现代爬虫技术的精髓。

二、基本原理

爬虫的本质是模拟人类浏览器行为,通过 HTTP 协议获取目标网页内容。核心流程包含三个阶段:

  1. 请求阶段:构建 HTTP 请求,发送到目标服务器
  2. 响应阶段:接收服务器返回的 HTTP 响应
  3. 解析阶段:提取需要的数据

现代爬虫面临两个关键挑战:

  • 动态内容处理:JavaScript 渲染的页面需要使用 Selenium 等工具
  • 反爬机制对抗:需要处理 IP 封禁、验证码、请求头验证等

三、环境准备

pip install requests beautifulsoup4 lxml selenium playwright

环境说明:

  • requests:基础 HTTP 请求
  • beautifulsoup4:HTML 解析
  • lxml:高性能 XML/HTML 解析器
  • selenium:自动化浏览器
  • playwright:现代浏览器自动化工具

四、核心实现

1. 基础爬虫实现

import requests
from bs4 import BeautifulSoup

def fetch_page(url):
    headers = {
        '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'
    }
    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

def parse_page(html):
    soup = BeautifulSoup(html, 'lxml')
    # 假设目标页面是豆瓣电影top250
    items = soup.find_all('div', class_='item')
    for item in items:
        title = item.find('span', class_='title').text
        rating = item.find('div', class_='star').find('span', class_='rating_num').text
        print(f"{title}: {rating}")

if __name__ == '__main__':
    url = 'https://movie.douban.com/top250'
    html = fetch_page(url)
    if html:
        parse_page(html)

关键代码解释:

  1. headers 字段模拟浏览器请求,避免被识别为爬虫
  2. timeout 参数防止请求阻塞
  3. raise_for_status() 检查 HTTP 状态码
  4. lxml 解析器比 html.parser 更快更稳定
  5. 假设的 title 和 rating 提取逻辑需要根据实际页面结构调整

2. 处理动态内容(Selenium 示例)

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

def get_dynamic_content():
    chrome_options = Options()
    chrome_options.add_argument('--headless')  # 无头模式
    chrome_options.add_argument('--disable-gpu')
    driver = webdriver.Chrome(options=chrome_options)
    
    try:
        driver.get('https://example.com/dynamic-content')
        # 等待动态内容加载
        driver.implicitly_wait(10)
        content = driver.find_element_by_css_selector('#dynamic-content').text
        print(content)
    finally:
        driver.quit()

get_dynamic_content()

关键点分析:

  • 使用 Selenium 模拟浏览器行为
  • implicitly_wait 设置隐式等待时间
  • 需要安装 ChromeDriver 并配置环境变量
  • 无头模式适合批量爬取,但可能被反爬机制识别

3. 异步爬虫(aiohttp 示例)

import aiohttp
import asyncio

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    async with aiohttp.ClientSession() as session:
        html = await fetch(session, 'https://example.com')
        print(html)

asyncio.run(main())

性能优势:

  • 单线程处理多个请求
  • 更适合高并发场景
  • 需配合异步解析库(如 aioscrapy)

五、完整案例:爬取豆瓣电影TOP250

import requests
from bs4 import BeautifulSoup
import json
import time
import os

# 保存数据到文件
def save_data(data, filename):
    with open(filename, 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=4)

# 获取单页数据
def get_page_data(page):
    url = f'https://movie.douban.com/top250?start={page*25}&filter='
    headers = {
        'User-Agent': 'Mozilla/5.0',
        'Referer': 'https://movie.douban.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

# 解析单页数据
def parse_page(html):
    soup = BeautifulSoup(html, 'lxml')
    items = soup.find_all('div', class_='item')
    data = []
    for item in items:
        title = item.find('span', class_='title').text.strip()
        rating = item.find('div', class_='star').find('span', class_='rating_num').text
        comment = item.find('p', class_='').text.strip() if item.find('p', class_='') else ''
        data.append({
            'title': title,
            'rating': rating,
            'comment': comment
        })
    return data

# 主程序
def main():
    all_data = []
    for page in range(0, 10):  # 爬取前10页
        html = get_page_data(page)
        if html:
            data = parse_page(html)
            all_data.extend(data)
            time.sleep(1)  # 避免请求过快
    save_data(all_data, 'douban_movies.json')
    print(f"共爬取{len(all_data)}条数据")

if __name__ == '__main__':
    main()

完整案例说明:

  • 分页爬取10页数据
  • 使用 time.sleep(1) 避免触发反爬机制
  • 保存为 JSON 文件便于后续处理
  • 实际使用需处理分页边界和异常情况

六、源码解析

  1. 请求处理:requests.get() 构建 HTTP 请求,headers 设置用户代理和来源
  2. 异常处理:try-except 捕获网络异常,raise_for_status() 检查响应状态码
  3. 解析逻辑:使用 BeautifulSoup 的 find_all 和 find 方法提取数据
  4. 数据保存:使用 json.dump 保存结构化数据,ensure_ascii=False 保留中文

七、进阶使用

1. 处理反爬机制

# 使用代理IP
proxies = {
    'http': 'http://10.10.1.10:3128',
    'https': 'http://10.10.1.10:1080'
}
response = requests.get(url, proxies=proxies)

# 使用 cookies
cookies = {
    'sessionid': '123456789'
}
response = requests.get(url, cookies=cookies)

2. 处理验证码

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 等待验证码出现
wait = WebDriverWait(driver, 10)
captcha = wait.until(EC.presence_of_element_located((By.ID, 'captcha')))
# 通过第三方服务识别验证码

3. 使用 Scrapy 框架

import scrapy

class DoubanSpider(scrapy.Spider):
    name = 'douban'
    start_urls = ['https://movie.douban.com/top250']

    def parse(self, response):
        for item in response.css('div.item'):
            yield {
                'title': item.css('span.title::text').get(),
                'rating': item.css('span.rating_num::text').get()
            }
        next_page = response.css('span.next a::attr(href)').get()
        if next_page:
            yield response.follow(next_page, self.parse)

八、性能与工程实践

1. 性能优化策略

方法说明适用场景
异步请求使用 aiohttp高并发场景
并行请求多线程/进程非阻塞任务
缓存机制使用 Redis 缓存高频访问数据
分页控制控制请求频率避免触发反爬

2. 异常处理设计

class RequestException(Exception):
    def __init__(self, message, status_code=None):
        super().__init__(message)
        self.status_code = status_code

3. 安全实践

  • 遵守 robots.txt 规则
  • 设置合理的请求间隔
  • 使用 HTTPS 协议
  • 避免敏感信息泄露

九、常见问题与踩坑

1. 常见错误及解决方案

错误类型表现解决方案
超时错误ReadTimeout增加 timeout 参数
被封IP频繁请求使用代理IP池
数据解析失败无法提取数据检查页面结构变化
验证码识别失败无法通过验证使用第三方识别服务

2. 实际开发陷阱

  • 过度依赖单线程:导致请求队列积压
  • 忽略响应状态码:可能遗漏错误处理
  • 未处理分页边界:导致数据不完整
  • 未处理 cookies 丢失:导致会话中断

十、最佳实践

  1. 请求控制:每次请求间隔1-3秒
  2. 数据验证:校验提取数据的完整性
  3. 日志记录:记录关键操作和错误信息
  4. 资源管理:及时关闭连接和释放资源
  5. 安全防护:使用 HTTPS,避免敏感信息明文传输
  6. 模块化设计:将请求、解析、保存分离

十一、总结

Python 爬虫技术已从简单的数据抓取发展为复杂的系统工程。本文深入解析了爬虫的核心原理,通过三个代码示例和一个完整案例,展示了从基础请求到动态内容处理的完整流程。在实际应用中,需要根据场景选择合适的技术方案:简单场景使用 requests + BeautifulSoup,复杂场景使用 Selenium 或 Playwright,高并发场景采用异步框架。同时要时刻注意反爬机制和安全风险,遵守网络规范,才能在合法合规的前提下高效获取数据。记住:爬虫技术的终极目标是解决问题,而不是单纯追求数据获取。

最后修改于:2026年10月01日 15:20

评论已关闭

推荐阅读

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日