在数据采集领域,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 渲染)

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐