Scrapy 框架基础知识
Scrapy 是一个适合大规模结构化数据提取的 Python 爬虫框架。与手写 requests 循环不同,Scrapy 提供了并发请求、自动重试、失败重试、数据管道、中间件等机制,适合需要稳定抓取、数据清洗和维护的生产项目。
适用场景
- 需要抓取大量页面,希望自动处理并发和延迟
- 需要把解析逻辑和数据清洗、存储分离维护
- 需要将抓取结果写入 CSV、JSON、MySQL、MongoDB 等
核心概念
- Spider:定义从哪开始抓、怎么解析、怎么跟进链接
- Request / Response:请求与响应对象,Scrapy 自动管理调度
- Item:定义需要提取的数据字段
- Pipeline:负责清洗、校验、存储数据
- Settings:配置延迟、请求头、Pipeline 开关等
- Middleware:扩展请求/响应处理过程
快速开始
安装与创建项目
pip install scrapy
scrapy startproject quotes_crawler
cd quotes_crawler
scrapy genspider quotes quotes.toscrape.com生成的项目结构:
quotes_crawler/
scrapy.cfg
quotes_crawler/
__init__.py
items.py
middlewares.py
pipelines.py
settings.py
spiders/
__init__.py
quotes.py定义 Item
编辑 items.py:
import scrapy
class QuoteItem(scrapy.Item):
text = scrapy.Field()
author = scrapy.Field()
tags = scrapy.Field()编写 Spider
编辑 spiders/quotes.py:
import scrapy
from quotes_crawler.items import QuoteItem
class QuotesSpider(scrapy.Spider):
name = "quotes"
allowed_domains = ["quotes.toscrape.com"]
start_urls = ["https://quotes.toscrape.com/"]
def parse(self, response):
for quote in response.css(".quote"):
item = QuoteItem()
item["text"] = quote.css(".text::text").get()
item["author"] = quote.css(".author::text").get()
item["tags"] = quote.css(".tags .tag::text").getall()
yield item
next_page = response.css("li.next a::attr(href)").get()
if next_page:
yield response.follow(next_page, callback=self.parse)CSS 选择器说明
response.css(".quote") # 选取所有 class="quote" 的元素
quote.css(".text::text").get() # 提取文本
quote.css(".tags .tag::text").getall() # 提取所有标签文本
response.css("li.next a::attr(href)").get() # 提取属性值运行爬虫
scrapy crawl quotes # 运行
scrapy crawl quotes -O quotes.json # 输出 JSON
scrapy crawl quotes -O quotes.csv # 输出 CSV使用 Pipeline
编辑 pipelines.py:
import json
class JsonLinesPipeline:
def open_spider(self, spider):
self.file = open("quotes.jl", "w", encoding="utf-8")
def close_spider(self, spider):
self.file.close()
def process_item(self, item, spider):
line = json.dumps(dict(item), ensure_ascii=False)
self.file.write(line + "\n")
return item在 settings.py 中启用:
ITEM_PIPELINES = {
"quotes_crawler.pipelines.JsonLinesPipeline": 300,
}常用配置
ROBOTSTXT_OBEY = True
DOWNLOAD_DELAY = 0.5
CONCURRENT_REQUESTS = 16
CONCURRENT_REQUESTS_PER_DOMAIN = 8
DEFAULT_REQUEST_HEADERS = {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
}常见问题
- 页面无内容:检查是否被 JS 渲染,尝试寻找接口或使用 Playwright
- 只有第一页:确认
next_page选择器正确 - 中文乱码:输出时指定
-s FEED_EXPORT_ENCODING=utf-8或 Pipeline 中指定编码
总结
一个典型的 Scrapy 项目结构:
- Spider 负责抓取和解析
- Item 定义数据字段
- Pipeline 负责清洗和保存
- Settings 控制并发、延迟和扩展