零基础快速入门 Scrapy 爬虫:核心用法与实战案例(含源码)
在数据采集领域,Scrapy 作为 Python 生态中最强大的爬虫框架,以 “高性能、模块化、可扩展性强” 著称,能轻松应对静态网页、动态接口等各类数据采集场景。相比 Requests+BeautifulSoup 的手动拼接模式,Scrapy 内置了请求调度、数据解析、异步下载等核心功能,让开发者专注于数据提取逻辑。本文针对零基础学习者,从环境搭建、核心概念、实战爬取案例、避坑指南四个维度,手把手教你快速入门 Scrapy,附精简源码,30 分钟即可实现第一个爬虫项目。
一、核心优势与环境准备
1. Scrapy 核心优势
- 异步高效:基于 Twisted 异步框架,支持并发请求,爬取速度远超同步爬虫;
- 功能完备:内置请求去重、Cookie 管理、代理配置、数据存储(JSON/CSV/ 数据库)等功能;
- 灵活扩展:支持中间件、管道、信号等自定义扩展,可应对反爬、动态渲染等复杂场景;
- 语法简洁:通过 XPath/CSS 选择器快速提取数据,无需手动解析 HTML。
2. 环境说明
- 运行环境:Python 3.8+(Scrapy 2.0+ 兼容 Python 3.6+,推荐 3.8+ 稳定版本);
- 依赖框架:Scrapy(核心爬虫框架)、parsel(数据解析依赖,Scrapy 内置)。
3. 环境搭建步骤
(1)安装 Python(已安装可跳过)
从 Python 官网 下载对应系统版本(Windows/Mac/Linux),安装时勾选 “Add Python to PATH”(自动配置环境变量)。
验证安装:打开终端执行以下命令,输出版本号则成功:
python --version # 或 python3 --version(Mac/Linux)
# 输出示例:Python 3.9.10
(2)安装 Scrapy
通过 pip 命令全局安装 Scrapy(推荐使用虚拟环境,避免依赖冲突):
# 全局安装(简单快捷)
pip install scrapy
# 验证安装(输出版本号则成功)
scrapy version
# 输出示例:Scrapy 2.11.0
(3)解决安装报错(常见问题)
- Windows 报错 “缺少 twisted 依赖”:手动安装 twisted 轮子文件,从 Unofficial Windows Binaries 下载对应 Python 版本的 twisted‑xxx‑cp3x‑cp3x‑win_amd64.whl,执行 pip install 文件名.whl;
- Mac 报错 “缺少 openssl”:执行 brew install openssl(需先安装 Homebrew),再重新安装 Scrapy;
- Linux 报错 “缺少依赖”:Ubuntu 执行 sudo apt-get install python3-dev libssl-dev libffi-dev,CentOS 执行 yum install python3-devel openssl-devel。
二、Scrapy 核心概念(必懂基础)
在编写爬虫前,需先理解 Scrapy 的核心组件与工作流程,避免盲目编码:
1. 核心组件
|
组件名称 |
作用描述 |
|
Scrapy 项目 |
爬虫的容器,包含所有配置、爬虫、管道等文件 |
|
Spider(爬虫) |
核心业务逻辑所在,定义爬取目标 URL、数据提取规则、请求调度逻辑 |
|
Item(数据模型) |
定义待爬取的数据结构(类似实体类),用于规范数据格式 |
|
Pipeline(管道) |
处理爬取到的 Item 数据(如去重、清洗、存储到文件 / 数据库) |
|
Downloader(下载器) |
负责下载网页内容,支持异步、代理、Cookie 管理 |
|
Settings(配置) |
项目全局配置(如并发数、请求延迟、User-Agent、管道优先级等) |
2. 工作流程
三、实战案例:爬取豆瓣电影 Top250(零基础入门)
以爬取豆瓣电影 Top250(https://movie.douban.com/top250)为例,完整演示 Scrapy 爬虫的创建、编写、运行全流程,目标提取 “电影名称、评分、导演、简介” 等数据。
步骤 1:创建 Scrapy 项目
打开终端,进入目标文件夹(如 Desktop),执行以下命令创建项目(项目名 douban_spider):
scrapy startproject douban_spider
执行成功后,生成的项目目录结构如下:
douban_spider/
├── douban_spider/ # 项目核心目录
│ ├── __init__.py
│ ├── items.py # 数据模型定义
│ ├── middlewares.py # 中间件(反爬、代理等)
│ ├── pipelines.py # 数据处理管道
│ ├── settings.py # 全局配置
│ └── spiders/ # 爬虫脚本目录
│ └── __init__.py
└── scrapy.cfg # 项目配置文件(无需修改)
步骤 2:定义数据模型(items.py)
打开 douban_spider/items.py,定义 MovieItem 类,规范待爬取的数据字段:
# douban_spider/items.py
import scrapy
class MovieItem(scrapy.Item):
# 电影名称
title = scrapy.Field()
# 评分
score = scrapy.Field()
# 导演(含主演)
director = scrapy.Field()
# 简介
intro = scrapy.Field()
# 电影详情页 URL
detail_url = scrapy.Field()
- scrapy.Field() 用于定义字段,无需指定数据类型,Scrapy 自动适配字符串、数字等类型。
步骤 3:创建爬虫脚本(核心逻辑)
进入 douban_spider/spiders 目录,执行以下命令创建爬虫(爬虫名 movie_spider,爬取域名 douban.com):
cd douban_spider/douban_spider/spiders
scrapy genspider movie_spider douban.com
执行后,自动生成 movie_spider.py 文件,修改该文件编写爬取逻辑:
# douban_spider/spiders/movie_spider.py
import scrapy
from douban_spider.items import MovieItem # 导入数据模型
class MovieSpider(scrapy.Spider):
# 爬虫名称(唯一,运行时需指定)
name = 'movie_spider'
# 允许爬取的域名(防止爬取到其他网站)
allowed_domains = ['douban.com']
# 初始爬取 URL(豆瓣 Top250 第一页)
start_urls = ['https://movie.douban.com/top250']
def parse(self, response):
"""
解析网页响应,提取数据和新 URL
:param response: 下载器返回的网页响应对象
"""
# 1. 提取当前页电影数据(通过 XPath 选择器)
movie_list = response.xpath('//ol[@class="grid_view"]/li') # 电影列表节点
for movie in movie_list:
item = MovieItem() # 实例化数据模型
# 提取电影名称(XPath 语法://标签[@属性="值"]/子标签/text())
item['title'] = movie.xpath('.//span[@class="title"][1]/text()').extract_first()
# 提取评分(extract_first() 获取第一个匹配结果,避免返回列表)
item['score'] = movie.xpath('.//span[@class="rating_num"]/text()').extract_first()
# 提取导演和主演(split 分割字符串,取前半部分)
director_str = movie.xpath('.//div[@class="bd"]/p[1]/text()').extract_first().strip()
item['director'] = director_str.split('主演')[0].strip()
# 提取简介(存在为空的情况,用 or '' 避免 None)
item['intro'] = movie.xpath('.//span[@class="inq"]/text()').extract_first() or '无简介'
# 提取详情页 URL
item['detail_url'] = movie.xpath('.//a/@href').extract_first()
# 将 item 提交到管道(后续由 pipelines 处理)
yield item
# 2. 翻页逻辑(提取下一页 URL 并继续爬取)
next_page = response.xpath('//span[@class="next"]/a/@href').extract_first()
if next_page:
# 拼接完整 URL(response.urljoin 自动补全域名)
next_url = response.urljoin(next_page)
# 发起下一页请求,回调 parse 方法继续解析
yield scrapy.Request(url=next_url, callback=self.parse)
关键语法说明:
- XPath 选择器:用于定位网页元素,核心语法:
-
- //标签名:从根节点查找所有匹配标签;
-
- @属性:选择元素的属性(如 @class、@href);
-
- text():提取元素文本内容;
-
- extract_first():获取第一个匹配结果(推荐,避免返回列表);
- yield 关键字:将 Item 提交到管道,或生成新的请求(Scrapy 自动异步处理);
- 翻页逻辑:通过提取 “下一页” 链接,递归调用 parse 方法,实现全量爬取。

步骤 4:配置项目(settings.py)
打开 douban_spider/settings.py,修改以下配置(避免被豆瓣反爬,优化爬取效果):
# douban_spider/settings.py
# 1. 伪装浏览器 User-Agent(关键!避免被识别为爬虫)
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
# 2. 开启遵守 robots.txt 协议(默认开启,豆瓣允许爬取 Top250,可保持开启)
ROBOTSTXT_OBEY = True
# 3. 设置请求延迟(单位:秒,避免请求过快被封 IP)
DOWNLOAD_DELAY = 1 # 每 1 秒发送一个请求
# 4. 开启管道(默认注释,取消注释即可启用,数字越小优先级越高)
ITEM_PIPELINES = {
'douban_spider.pipelines.DoubanSpiderPipeline': 300,
}
# 5. 关闭 Cookie(可选,豆瓣无需登录即可爬取 Top250)
COOKIES_ENABLED = False
步骤 5:编写管道(存储数据到 CSV/JSON)
打开 douban_spider/pipelines.py,修改 DoubanSpiderPipeline 类,实现数据存储逻辑(支持 CSV、JSON 两种格式,任选其一):
# douban_spider/pipelines.py
import csv
import json
class DoubanSpiderPipeline:
# 爬虫启动时执行(初始化文件)
def open_spider(self, spider):
# 方式 1:存储到 CSV 文件(推荐,Excel 可直接打开)
self.csv_file = open('douban_top250.csv', 'w', encoding='utf-8-sig', newline='')
self.csv_writer = csv.DictWriter(
self.csv_file,
fieldnames=['title', 'score', 'director', 'intro', 'detail_url'] # 与 Item 字段一致
)
self.csv_writer.writeheader() # 写入表头
# 方式 2:存储到 JSON 文件(可选,注释方式 1 即可启用)
# self.json_file = open('douban_top250.json', 'w', encoding='utf-8')
# self.json_file.write('[') # JSON 数组开始
# 处理每个 Item 数据(爬虫爬取到一条数据就执行一次)
def process_item(self, item, spider):
# 方式 1:写入 CSV
self.csv_writer.writerow(dict(item)) # Item 转换为字典写入
# 方式 2:写入 JSON
# json.dump(dict(item), self.json_file, ensure_ascii=False, indent=2)
# self.json_file.write(',') # 分隔多个 JSON 对象
return item # 必须返回 item,供后续管道处理(若有多个管道)
# 爬虫关闭时执行(关闭文件)
def close_spider(self, spider):
# 方式 1:关闭 CSV 文件
self.csv_file.close()
# 方式 2:关闭 JSON 文件
# self.json_file.seek(-1, 2) # 移除最后一个逗号
# self.json_file.write(']') # JSON 数组结束
# self.json_file.close()
步骤 6:运行爬虫,查看结果
在项目根目录(douban_spider 目录,含 scrapy.cfg 文件)打开终端,执行以下命令运行爬虫:
scrapy crawl movie_spider
运行成功日志:
2024-05-20 15:30:00 [scrapy.core.engine] INFO: Spider opened
2024-05-20 15:30:01 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://movie.douban.com/top250>
2024-05-20 15:30:02 [scrapy.core.scraper] DEBUG: Scraped from <200 https://movie.douban.com/top250>
{'title': '肖申克的救赎', 'score': '9.7', 'director': '导演: 弗兰克·德拉邦特 Frank Darabont', 'intro': '希望让人自由。', 'detail_url': 'https://movie.douban.com/subject/1292052/'}
...
2024-05-20 15:35:00 [scrapy.core.engine] INFO: Closing spider (finished)
查看爬取结果:
项目根目录会生成 douban_top250.csv 文件,用 Excel 或文本编辑器打开,可看到完整的 250 部电影数据,格式规范、无乱码。
四、进阶技巧:解决常见问题与扩展功能
1. 数据去重(管道实现)
若爬取过程中存在重复数据(如翻页链接重复),可在管道中添加去重逻辑:
# pipelines.py 中修改 DoubanSpiderPipeline 类
def open_spider(self, spider):
self.csv_file = open('douban_top250.csv', 'w', encoding='utf-8-sig', newline='')
self.csv_writer = csv.DictWriter(self.csv_file, fieldnames=['title', 'score', 'director', 'intro', 'detail_url'])
self.csv_writer.writeheader()
self.seen_titles = set() # 用集合存储已爬取的电影名称(去重)
def process_item(self, item, spider):
# 按电影名称去重
if item['title'] not in self.seen_titles:
self.seen_titles.add(item['title'])
self.csv_writer.writerow(dict(item))
return item
2. 应对反爬:配置代理 IP
若爬取时出现 403 禁止访问(IP 被封),可在 settings.py 中配置代理:
# settings.py 新增代理配置
DOWNLOADER_MIDDLEWARES = {
'douban_spider.middlewares.ProxyMiddleware': 543, # 自定义代理中间件
}
# middlewares.py 中新增 ProxyMiddleware 类
class ProxyMiddleware:
def process_request(self, request, spider):
# 免费代理 IP(推荐使用付费代理池,免费代理稳定性差)
request.meta['proxy'] = 'http://123.45.67.89:8080' # 替换为实际代理
3. 爬取动态网页(JavaScript 渲染)
更多推荐



所有评论(0)