Scrapy 框架基础知识

发布于:2026-06-11 #Scrapy#Python#爬虫 共 604 字 约 2 分钟

Scrapy 是一个适合大规模结构化数据提取的 Python 爬虫框架。与手写 requests 循环不同,Scrapy 提供了并发请求、自动重试、失败重试、数据管道、中间件等机制,适合需要稳定抓取、数据清洗和维护的生产项目。

适用场景

  • 需要抓取大量页面,希望自动处理并发和延迟
  • 需要把解析逻辑和数据清洗、存储分离维护
  • 需要将抓取结果写入 CSV、JSON、MySQL、MongoDB 等

核心概念

  • Spider:定义从哪开始抓、怎么解析、怎么跟进链接
  • Request / Response:请求与响应对象,Scrapy 自动管理调度
  • Item:定义需要提取的数据字段
  • Pipeline:负责清洗、校验、存储数据
  • Settings:配置延迟、请求头、Pipeline 开关等
  • Middleware:扩展请求/响应处理过程

快速开始

安装与创建项目

Bash
UTF-8|4 Lines|
pip install scrapy
scrapy startproject quotes_crawler
cd quotes_crawler
scrapy genspider quotes quotes.toscrape.com

生成的项目结构:

plaintext
UTF-8|11 Lines|
quotes_crawler/
  scrapy.cfg
  quotes_crawler/
    __init__.py
    items.py
    middlewares.py
    pipelines.py
    settings.py
    spiders/
      __init__.py
      quotes.py

定义 Item

编辑 items.py

Python
UTF-8|6 Lines|
import scrapy

class QuoteItem(scrapy.Item):
    text = scrapy.Field()
    author = scrapy.Field()
    tags = scrapy.Field()

编写 Spider

编辑 spiders/quotes.py

Python
UTF-8|19 Lines|
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 选择器说明

Python
UTF-8|4 Lines|
response.css(".quote")               # 选取所有 class="quote" 的元素
quote.css(".text::text").get()       # 提取文本
quote.css(".tags .tag::text").getall() # 提取所有标签文本
response.css("li.next a::attr(href)").get() # 提取属性值

运行爬虫

Bash
UTF-8|3 Lines|
scrapy crawl quotes                     # 运行
scrapy crawl quotes -O quotes.json      # 输出 JSON
scrapy crawl quotes -O quotes.csv       # 输出 CSV

使用 Pipeline

编辑 pipelines.py

Python
UTF-8|13 Lines|
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 中启用:

Python
UTF-8|3 Lines|
ITEM_PIPELINES = {
    "quotes_crawler.pipelines.JsonLinesPipeline": 300,
}

常用配置

Python
UTF-8|8 Lines|
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 项目结构:

  1. Spider 负责抓取和解析
  2. Item 定义数据字段
  3. Pipeline 负责清洗和保存
  4. Settings 控制并发、延迟和扩展