Python爬虫框架Scrapy实战:从入门到分布式抓取
2026/7/21 13:25:55 网站建设 项目流程

1. Scrapy框架概述与核心价值

Scrapy是一个基于Python的高性能网络爬虫框架,专为大规模数据抓取而设计。不同于简单的requests+BeautifulSoup组合,Scrapy提供了完整的爬虫开发生命周期管理,包括请求调度、数据提取、持久化存储等模块化组件。我在实际项目中多次使用Scrapy处理千万级数据抓取任务,其异步处理机制能轻松实现单机日抓取百万页面。

框架的核心优势在于其"Batteries included"设计理念:

  • 内置CSS选择器和XPath解析器
  • 自动的请求去重与优先级队列
  • 完善的中间件扩展机制
  • 支持分布式爬取和增量抓取
  • 丰富的导出格式(JSON/CSV/XML等)

注意:Scrapy最新稳定版(2.11+)要求Python 3.8+环境,与部分旧版扩展插件可能存在兼容性问题。

2. 环境配置与项目初始化

2.1 基础环境准备

推荐使用conda创建独立Python环境(避免包冲突):

conda create -n scrapy_env python=3.10 conda activate scrapy_env pip install scrapy

验证安装:

scrapy version # 应输出类似:Scrapy 2.11.0

2.2 创建第一个爬虫项目

执行项目生成命令:

scrapy startproject lagou_jobs cd lagou_jobs scrapy genspider lagou www.lagou.com

生成的项目结构解析:

lagou_jobs/ ├── scrapy.cfg # 部署配置文件 └── lagou_jobs/ # 项目主目录 ├── __init__.py ├── items.py # 数据模型定义 ├── middlewares.py # 中间件配置 ├── pipelines.py # 数据处理管道 ├── settings.py # 爬虫配置 └── spiders/ # 爬虫代码目录 ├── __init__.py └── lagou.py # 生成的爬虫模板

3. 核心组件深度解析

3.1 数据模型定义(items.py)

以拉勾网职位数据为例:

import scrapy class LagouJobItem(scrapy.Item): position = scrapy.Field() # 职位名称 salary = scrapy.Field() # 薪资范围 company = scrapy.Field() # 公司名称 experience = scrapy.Field() # 经验要求 education = scrapy.Field() # 学历要求 skills = scrapy.Field() # 技能标签 pub_date = scrapy.Field() # 发布日期 job_url = scrapy.Field() # 职位链接

经验提示:字段命名建议采用全小写下划线风格,与后续数据库存储字段保持一致。

3.2 爬虫逻辑实现(spiders/lagou.py)

import scrapy from lagou_jobs.items import LagouJobItem class LagouSpider(scrapy.Spider): name = "lagou" allowed_domains = ["www.lagou.com"] start_urls = ["https://www.lagou.com/zhaopin/Python/"] custom_settings = { 'DOWNLOAD_DELAY': 2, # 爬取间隔(秒) 'CONCURRENT_REQUESTS': 8 # 并发请求数 } def parse(self, response): jobs = response.css('.item__10RTO') for job in jobs: item = LagouJobItem() item['position'] = job.css('h3::text').get().strip() item['salary'] = job.css('.money__3Lkgq::text').get() yield item # 翻页处理 next_page = response.css('.next::attr(href)').get() if next_page: yield response.follow(next_page, self.parse)

3.3 数据处理管道(pipelines.py)

典型的数据清洗与存储实现:

import pymongo from itemadapter import ItemAdapter class LagouJobsPipeline: def __init__(self, mongo_uri, mongo_db): self.mongo_uri = mongo_uri self.mongo_db = mongo_db @classmethod def from_crawler(cls, crawler): return cls( mongo_uri=crawler.settings.get('MONGO_URI'), mongo_db=crawler.settings.get('MONGO_DATABASE') ) def open_spider(self, spider): self.client = pymongo.MongoClient(self.mongo_uri) self.db = self.client[self.mongo_db] def close_spider(self, spider): self.client.close() def process_item(self, item, spider): # 薪资范围标准化处理 if 'salary' in item: item['salary'] = self._normalize_salary(item['salary']) self.db['jobs'].insert_one(ItemAdapter(item).asdict()) return item def _normalize_salary(self, salary_str): # 实现薪资字符串的标准化逻辑 pass

4. 高级配置与优化技巧

4.1 反爬策略应对方案

在settings.py中配置:

DOWNLOADER_MIDDLEWARES = { 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None, 'scrapy_user_agents.middlewares.RandomUserAgentMiddleware': 400, 'scrapy.downloadermiddlewares.retry.RetryMiddleware': 500, } RETRY_TIMES = 3 RETRY_HTTP_CODES = [500, 502, 503, 504, 522, 524, 408, 429] DOWNLOAD_DELAY = 3 AUTOTHROTTLE_ENABLED = True

4.2 分布式爬虫实现

使用scrapy-redis组件:

  1. 安装依赖:
pip install scrapy-redis
  1. 修改爬虫继承类:
from scrapy_redis.spiders import RedisSpider class LagouRedisSpider(RedisSpider): name = 'lagou_redis' redis_key = 'lagou:start_urls'
  1. 配置Redis连接:
SCHEDULER = "scrapy_redis.scheduler.Scheduler" DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" REDIS_URL = 'redis://:password@localhost:6379/0'

5. 数据分析实战案例

5.1 数据清洗与转换

使用Pandas进行数据分析:

import pandas as pd from pymongo import MongoClient client = MongoClient('mongodb://localhost:27017/') db = client['lagou'] df = pd.DataFrame(list(db.jobs.find())) # 薪资分析 df['min_salary'] = df['salary'].str.extract(r'(\d+)k-').astype(float) df['max_salary'] = df['salary'].str.extract(r'-(\d+)k').astype(float) df['avg_salary'] = (df['min_salary'] + df['max_salary']) / 2 # 热门技能统计 skills_count = pd.Series( sum([s.split(',') for s in df['skills'].dropna()], []) ).value_counts()

5.2 可视化展示

使用Matplotlib生成图表:

import matplotlib.pyplot as plt plt.figure(figsize=(12,6)) skills_count[:10].plot(kind='barh') plt.title('Top 10 Required Skills for Python Jobs') plt.xlabel('Count') plt.tight_layout() plt.savefig('skills_distribution.png')

6. 常见问题排查手册

问题现象可能原因解决方案
返回403错误被目标网站封禁1. 增加DOWNLOAD_DELAY
2. 使用代理中间件
3. 更换User-Agent
数据提取为空页面结构变更1. 更新CSS/XPath选择器
2. 检查JavaScript渲染需求
MongoDB连接失败认证配置错误1. 检查MONGO_URI格式
2. 确认服务已启动
内存占用过高未及时清理缓存1. 调整CONCURRENT_REQUESTS
2. 启用AUTOTHROTTLE

实战经验:遇到页面解析问题时,建议先用scrapy shell命令交互式调试:

scrapy shell 'https://www.lagou.com/zhaopin/Python/' # 然后在交互环境中测试选择器 response.css('h3::text').get()

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询