Scrapy 入门总览:用 runspider 命令快速编写并运行异步爬虫
【免费下载链接】scrapyScrapy, a fast high-level web crawling & scraping framework for Python.项目地址: https://gitcode.com/GitHub_Trending/sc/scrapy
本文基于 Scrapy 官方文档 Scrapy at a glance 展开,带你完整走查一个最小可用的 QuotesSpider 示例:从编写 Spider 类、用scrapy runspider命令无项目运行,到理解爬虫引擎如何处理异步请求、如何配置抓取礼貌性(下载延迟、并发限制),以及 Scrapy 内置的 Selector、Feed 导出、扩展与中间件等核心能力。读完后你可以直接复制示例代码运行出结果,并理解其背后的执行机制。
一、Scrapy 是什么
Scrapy(读音 /ˈskreɪpaɪ/)是一个用于爬取网站并提取结构化数据的应用框架,可支撑数据挖掘、信息处理、历史档案化等多种应用。虽然 Scrapy 最初是为网页抓取(web scraping)设计的,但官方文档 overview.rst 明确指出,它同样可以:
- 从 API 中提取数据(例如 Amazon Associates Web Services);
- 作为通用的 Web 爬虫(general purpose web crawler)使用。
其底层基于 Twisted 事件驱动网络框架构建,采用非阻塞(异步)代码实现并发——这一点会在下文“到底发生了什么”部分结合架构文档 architecture.rst 详细展开。
二、示例 Spider 完整走查
2.1 示例代码
以下是一个抓取 quotes.toscrape.com 名言站点、并跟随分页翻页的 Spider:
import scrapy class QuotesSpider(scrapy.Spider): name = "quotes" start_urls = [ "https://quotes.toscrape.com/tag/humor/", ] def parse(self, response): for quote in response.css("div.quote"): yield { "author": quote.xpath("span/small/text()").get(), "text": quote.css("span.text::text").get(), } next_page = response.css('li.next a::attr("href")').get() if next_page is not None: yield response.follow(next_page, self.parse)将这段代码保存为quotes_spider.py,然后使用runspider命令运行:
scrapy runspider quotes_spider.py -o quotes.jsonl运行结束后,quotes.jsonl文件会包含 JSON Lines 格式的名言列表(每行一个 JSON 对象,含text与author字段),内容形如:
{"author": "Jane Austen", "text": "\u201cThe person, be it gentleman or lady, who has not pleasure in a good novel, must be intolerably stupid.\u201d"} {"author": "Steve Martin", "text": "\u201cA day without sunshine is like, you know, night.\u201d"} {"author": "Garrison Keillor", "text": "\u201cAnyone who thinks sitting in church can make you a Christian must also think that sitting in a garage can make you a car.\u201d"} ...2.2 runspider 命令的源码解析
scrapy runspider是“无需项目即可运行 Spider 文件”的最简方式。从源码 runspider.py 可以看到它的完整处理流程:
- 校验文件存在性(
filename.exists(),否则抛出UsageError); - 通过
_import_file将.py文件作为模块导入(会临时把文件所在目录插入sys.path); - 用
iter_spider_classes(module)在模块中查找 Spider 类,找不到则报错; - 调用
crawler_process.crawl(...)创建爬虫并start()启动事件循环。
该命令默认设置中使用了DummySpiderLoader(SPIDER_LOADER_CLASS),这正是它“不需要项目目录结构”的原因——它不依赖项目级 Spider 加载器,而是直接从给定文件中解析 Spider 类。命令的官方描述为:
[options] <spider_file> Run a spider from a Python file, no project required2.3 关键元素在源码中的落点
start_urls:Spider 基类在 spiders/init.py 中将其声明为类属性。默认的start()协程(该版本新增,见源码 L89-L136)会遍历start_urls,为每个 URL 生成Request(url, dont_filter=True),即“爬取起点就是这些 URL 的初始请求”。parse回调:基类的parse方法默认抛出NotImplementedError(源码 L145-L164),Spider 必须自己实现。它是未指定callback的请求的默认回调,响应到达引擎后会被路由到这里。response.css(...)/quote.xpath(...):Selector 的统一实现在 unified.py,支持扩展的 CSS 选择器与 XPath 表达式,并附带正则提取等辅助方法,详见 selectors 文档。response.follow(next_page, self.parse):follow方法会把相对链接(如/tag/humor/page/2/)解析为绝对 URL 并生成以self.parse为回调的新请求,从而形成“抓一页 → 提取数据 → 发现下一页 → 再抓”的递归翻页循环。
三、到底发生了什么(What just happened?)
官方文档对这条命令的执行过程给出了清晰的分解:
- 查找 Spider:运行
scrapy runspider quotes_spider.py时,Scrapy 在文件中查找 Spider 定义,并把它交给爬虫引擎(crawler engine)执行; - 发起初始请求:爬取从访问
start_urls中定义的 URL 开始(本例仅humor分类的第一页),响应会作为参数传入默认回调parse; - 回调中处理:在
parse中,用 CSS Selector 循环遍历div.quote元素,yield一个包含名言文本和作者的 Python dict;同时用 CSS Selector 查找下一页链接,并用response.follow以同样的parse方法为回调调度新请求。
3.1 异步调度:Scrapy 的核心优势
文档特别强调:这里体现了 Scrapy 的主要优势之一——请求被异步地调度和处理。含义是:
- Scrapy 不需要等待某个请求完成并处理完,才能做别的事;它可以在等待期间发出另一个请求或执行其他操作;
- 即使某个请求失败或处理时发生错误,其他请求仍然可以继续推进(容错性)。
这一机制使 Scrapy 能够并发发送多个请求,实现又快又容错的抓取。其数据流由执行引擎控制,完整流程记录在 architecture.rst 中:Spider 产出初始 Request → Engine 交给 Scheduler 排队 → Engine 将 Request 经 Downloader Middleware 发给 Downloader → 下载完成后 Response 经 Middleware 回到 Engine → Engine 将 Response 经 Spider Middleware 交给 Spider 处理 → Spider 产出 items 与新 Request → items 进入 Item Pipeline、新 Request 回到 Scheduler,循环往复直到调度器中无请求为止。
3.2 礼貌性控制:并发与延迟设置
异步高速抓取的同时,Scrapy 通过设置项(settings)提供对抓取“礼貌程度”的控制。以下是 default_settings.py 中与之直接相关的默认值(以当前仓库源码为准):
| 设置项 | 默认值 | 作用 |
|---|---|---|
CONCURRENT_REQUESTS | 16 | 全局并发请求数上限 |
CONCURRENT_REQUESTS_PER_DOMAIN | 8 | 每个域名的最大并发请求数 |
CONCURRENT_ITEMS | 100 | 并发处理 item 的数量上限 |
DOWNLOAD_DELAY | 0 | 同一域名两次请求之间的下载延迟(秒),0 表示不延迟 |
RANDOMIZE_DOWNLOAD_DELAY | True | 在DOWNLOAD_DELAY基础上做随机化,避免固定节奏 |
AUTOTHROTTLE_ENABLED | False | 自动节流扩展开关 |
也就是说,若希望降低对目标站点的压力,可在运行参数或项目设置中调整DOWNLOAD_DELAY(例如设为 1 秒)并限制CONCURRENT_REQUESTS_PER_DOMAIN。完整的设置项参考见 settings 文档。
更进一步,Scrapy 内置了自动节流扩展(AutoThrottle):它会根据下载延迟等信号自动推断出合适的DOWNLOAD_DELAY与并发配置。从默认值看,AUTOTHROTTLE_ENABLED默认为False,另有关联的AUTOTHROTTLE_START_DELAY(默认 5.0 秒)、AUTOTHROTTLE_MAX_DELAY(默认 60.0 秒)和AUTOTHROTTLE_TARGET_CONCURRENCY(默认 1.0)可调节其行为。
3.3 Feed 导出:quotes.jsonl 是怎么来的
官方文档中的注释指出:上面的示例文件是用 **feed exports(Feed 导出)**机制生成的 JSON Lines 文件。-o quotes.jsonl会依据文件扩展名自动选择 JSON Lines 导出器。你可以:
- 轻松更换导出格式,如 XML 或 CSV(改一下输出文件名扩展名即可);
- 更换存储后端,如 FTP 或 Amazon S3;
- 编写 item pipeline 将 items 存入数据库。
更多细节见 feed-exports 文档。
四、What else?——Scrapy 还提供什么
官方文档在示例之后列出了 Scrapy 的核心能力清单,这里逐条说明并附上对应文档入口:
- 选择与提取:内置对 HTML/XML 源数据的选择支持,使用扩展的 CSS 选择器与 XPath 表达式,并提供正则提取辅助方法。见 selectors。
- 交互式 shell 控制台:IPython 感知(IPython aware)的 shell,用于在编写或调试 Spider 时快速试验 CSS/XPath 表达式。见 shell 文档。
- Feed 导出:支持多种格式(JSON、CSV、XML)与多种存储后端(FTP、S3、本地文件系统)。见 feed-exports。
- 健壮的编码支持与自动检测:可应对国外、非标准乃至损坏的编码声明。
- 强扩展性:通过 signals 和一套定义良好的 API(middlewares、extensions 与 pipelines)插入自定义功能。见 组件文档。
- 大量内置扩展与中间件,用于处理:
- cookies 与会话管理(对应 downloadermiddlewares/cookies.py);
- HTTP 压缩、认证、缓存等特性(如 httpcompression.py、httpauth.py、httpcache.py);
- User-Agent 伪装(useragent.py);
- robots.txt 遵守(robotstxt.py);
- 爬取深度限制(对应 spidermiddlewares/depth.py,由
DEPTH_LIMIT设置控制,默认 0 表示不限制)。
- Telnet 控制台:在 Scrapy 进程内部挂接一个 Python 控制台,用于内省与调试爬虫。从默认设置看
TELNETCONSOLE_ENABLED默认为开启(值为 1),可远程接入运行中的进程调试。见 telnetconsole 文档。 - 其他实用组件:
- 可复用的 Spider:
SitemapSpider抓取 Sitemap 站点、CSVFeedSpider/XMLFeedSpider抓取 XML/CSV feed——从 spiders/init.py 的__all__导出清单可确认这些可复用 Spider 均为框架内置; - 媒体管道:自动下载与抓取 item 关联的图片(或其他媒体),见 media-pipeline 文档;
- 带缓存的 DNS 解析器等。
- 可复用的 Spider:
五、下一步
按照官方文档 overview.rst 的指引,接下来的路线是:
- 安装 Scrapy:参考 install 文档(当前仓库亦提供 INSTALL.md);
- 跟做教程:通过 tutorial 学习如何创建一个完整的 Scrapy 项目(含
scrapy startproject、Spider 目录结构、item 定义等),而本文的runspider方式适合快速试验单个 Spider 文件; - 深入架构:若想了解数据流细节,阅读 Architecture overview,其中给出了 Engine、Scheduler、Downloader、Spider、Item Pipeline 及各类中间件之间的完整交互说明。
这样,从“一个 15 行的小 Spider + 一条命令行”到“完整项目 + 自定义中间件/管道/扩展”的成长路径就清晰了。
【免费下载链接】scrapyScrapy, a fast high-level web crawling & scraping framework for Python.项目地址: https://gitcode.com/GitHub_Trending/sc/scrapy
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考