
Scrapy 命令行工具完全解析scrapy.cfg 配置、全部内置命令与自定义命令实现【免费下载链接】scrapyScrapy, a fast high-level web crawling scraping framework for Python.项目地址: https://gitcode.com/GitHub_Trending/sc/scrapyScrapy 的几乎所有操作都通过scrapy命令行工具完成创建项目、生成爬虫、启动抓取、调试页面、查看配置、运行基准测试。本文以官方文档 Command line tool 为主线完整覆盖scrapy工具的配置加载机制、项目目录结构、全部 14 个内置命令全局命令与项目命令的参数用法并结合 scrapy/cmdline.py 与 scrapy/commands 目录下的源码剖析命令的发现、解析与执行流程以及ScrapyCommand基类如何支撑自定义命令扩展。读完后你可以独立完成从scrapy startproject到scrapy crawl的完整工作流并能编写项目级自定义命令。scrapy.cfg 配置体系与查找顺序scrapy工具启动后首先会按固定优先级在标准位置查找 ini 风格的scrapy.cfg文件/etc/scrapy.cfg或c:\scrapy\scrapy.cfg系统级全机器生效~/.config/scrapy.cfg即$XDG_CONFIG_HOME与~/.scrapy.cfg即$HOME用于全局用户级配置Scrapy 项目根目录内的scrapy.cfg。三者按上述顺序合并用户自定义值优先于系统级默认值而项目级配置一旦定义则覆盖其余两者。项目级scrapy.cfg的最小内容形如[settings] default myproject.settings其中default指定了项目的 settings 模块路径。这个机制的模板来源是 scrapy/templates/project/scrapy.cfgscrapy startproject创建项目时渲染的就是它。除scrapy.cfg外Scrapy 还通过三个环境变量接受配置环境变量作用SCRAPY_SETTINGS_MODULE指定 settings 模块见 settings 文档SCRAPY_PROJECT指定使用哪个项目别名详见下文“多项目共享根目录”SCRAPY_PYTHON_SHELL指定scrapy shell使用的交互式 shell见 shell 文档多项目共享同一根目录一个包含scrapy.cfg的项目根目录可以被多个 Scrapy 项目共享每个项目拥有独立的 settings 模块。此时需要在scrapy.cfg的[settings]段中为各 settings 模块定义别名[settings] default myproject1.settings project1 myproject1.settings project2 myproject2.settings默认情况下scrapy使用default指向的设置通过SCRAPY_PROJECT环境变量可以切换到其他项目$ scrapy settings --get BOT_NAME Project 1 Bot $ export SCRAPY_PROJECTproject2 $ scrapy settings --get BOT_NAME Project 2 BotScrapy 项目的默认目录结构在深入各子命令之前先明确项目结构。Scrapy 项目默认结构如下scrapy.cfg myproject/ __init__.py items.py middlewares.py pipelines.py settings.py spiders/ __init__.py spider1.py spider2.py ...scrapy.cfg所在目录称为项目根目录project root directory许多命令“必须在项目内运行”正是以该目录为判定基准——这一点在 scrapy/cmdline.py 的execute()中由inside_project()函数实现命令是否可用requires_project就取决于此。几个容易混淆的命名关系值得注意SPIDER_MODULES和NEWSPIDER_MODULE默认引用项目模块本身因此必须与其实际位置匹配scrapy list、scrapy genspider、scrapy crawl都依赖它们来定位爬虫BOT_NAME默认与项目同名但它只是一个标识符不要求等于模块名middlewares.py、pipelines.py中类名使用“大写项目名”作前缀如MyprojectDownloaderMiddleware仅是命名约定与模块名是否一致无关。上述结构由 scrapy/templates/project 模板目录生成其中settings.py.tmpl、items.py.tmpl、pipelines.py.tmpl、middlewares.py.tmpl在创建项目时被逐一渲染见 scrapy/commands/startproject.py 中的TEMPLATES_TO_RENDER。使用 scrapy 工具帮助输出与全局选项不带任何参数运行scrapy会打印版本、当前激活的项目、用法说明和可用命令列表Scrapy X.Y - no active project Usage: scrapy command [options] [args] Available commands: fetch Fetch a URL using the Scrapy downloader runspider Run a spider from a Python file, no project required [...]第一行若在项目内运行会显示Scrapy X.Y - project: myproject。这一输出由 scrapy/cmdline.py 中的_print_header()与_print_commands()生成项目外运行时还会额外提示[ more ] More commands available when run from project directory。查看单个命令的完整帮助scrapy command -h查看所有命令scrapy -h从源码看每个命令在scrapy command -h时都会注册一组全局选项定义于 scrapy/commands/init.py 的ScrapyCommand.add_options()它们对所有内置命令统一可用选项作用--logfile FILE指定日志文件省略时写 stderr-L, --loglevel LEVEL设置日志级别默认取LOG_LEVEL设置值--nolog完全禁用日志--profile FILE将 cProfile 性能统计写入文件见 scrapy/cmdline.py 的_run_command_profiled--pidfile FILE将当前进程 PID 写入文件-s, --set NAMEVALUE设置/覆盖设置项可重复使用--pdb出错时进入 pdb 调试若安装了 ipdb 则用 ipdb-s选项以prioritycmdline写入 settings即优先级高于项目与爬虫级别的设置解析逻辑在ScrapyCommand.process_options()见 scrapy/commands/init.py。创建与操控项目startproject创建项目语法scrapy startproject project_name [project_dir]全局命令无需项目。在project_dir下创建名为project_name的项目若未指定project_dir则与project_name同名。$ scrapy startproject myproject cd myproject创建完成即可在该目录中使用scrapy命令管理项目。源码层面scrapy/commands/startproject.py还有几条约束项目名必须匹配^[_a-zA-Z]\w*$即“以字母开头只含字母、数字、下划线”否则报错退出同名模块已可导入时find_spec探测会被拒绝目标目录已存在scrapy.cfg时直接报错退出码为 1。命令成功结束时会提示下一步操作cd project_dir后运行scrapy genspider example example.com。genspider基于模板生成爬虫语法scrapy genspider [-t template] name domain or URL全局命令。在当前目录项目外或项目spiders/目录项目内创建新爬虫。name成为爬虫的name属性domain or URL用于生成allowed_domains和start_urls属性$ scrapy genspider -l Available templates: basic crawl csvfeed xmlfeed $ scrapy genspider example example.com Created spider example using template basic $ scrapy genspider -t crawl scrapyorg scrapy.org Created spider scrapyorg using template crawl默认模板basic的内容见 scrapy/templates/spiders/basic.tmpl渲染后的爬虫形如import scrapy class $classname(scrapy.Spider): name $name allowed_domains [$domain] start_urls [$url] def parse(self, response): pass这是最方便的爬虫脚手架但不是唯一方式——完全可以手写爬虫源码文件。scrapy genspider除-l列出模板、-t指定模板外源码中还提供以下选项见 scrapy/commands/genspider.py-e/--edit创建后立即编辑、-d TEMPLATE将模板内容打印到标准输出、--force爬虫已存在时强制覆盖。自定义爬虫模板有两种方式提供自定义模板将TEMPLATES_DIR设置指向一个包含spiders子目录的目录为每个模板写一个{name}.tmpl文件name即传给-t的值。自定义模板会整体替换内置模板——内置模板位于scrapy包内的templates目录默认值见 scrapy/settings/default_settings.pyTEMPLATES_DIR str((Path(__file__).parent / .. / templates).resolve())想保留哪个就复制哪个过去给-t直接传一个.tmpl文件的路径无需改动TEMPLATES_DIR查找顺序是“相对路径 →TEMPLATES_DIR/spiders”见 genspider.py 的_find_template()。模板使用string.Template渲染$variable与${variable}会被替换$$渲染为单个$正则表达式中常用。除下列变量外的任何变量都会导致渲染失败name传给命令的爬虫名module将name规范化为合法模块名连字符、点号替换为下划线非字母开头时加前缀a见 genspider.py 的sanitize_module_name()同时用作生成文件文件名classnamemodule的驼峰形式加Spider后缀url传入的 URL无协议时自动补httpsdomainurl的域名urlparse(url).netlocproject_nameBOT_NAMEProjectNameproject_name的驼峰形式。变量构造逻辑可对照 genspider.py 的_generate_template_variables()。可用命令总览命令分为两类判定标准是requires_project类属性见 scrapy/cmdline.py 的_get_commands_from_module()全局命令无项目也可运行startproject、genspider、settings、runspider、shell、fetch、view、version、bench仅项目内命令crawl、check、list、edit、parse注意全局命令在项目内运行时行为可能略有不同——它们会使用项目的设置。例如fetch在被抓 URL 关联到某个爬虫时会应用该爬虫的覆盖行为如custom_settings属性这是有意设计因为fetch的用途就是验证爬虫实际如何下载页面。逐命令详解crawl语法scrapy crawl spider需要项目是以list报告中的某个爬虫name启动抓取要运行文件中的爬虫请用runspider。支持的选项-h, --help显示帮助并退出-a NAMEVALUE设置爬虫参数可重复--output FILE/-o FILE把抓到的 item追加到 FILE 末尾-表示标准输出在 URI 末尾加冒号指定格式如-o FILE:FORMAT--overwrite-output FILE/-O FILE把 item 写入 FILE 并覆盖已有内容格式用法同上。$ scrapy crawl myspider [ ... myspider starts crawling ... ] $ scrapy crawl -o myfile:csv myspider [ ... 抓取并追加结果到 myfilecsv 格式... ] $ scrapy crawl -O myfile:json myspider [ ... 抓取并以 json 格式覆盖写入 myfile ... ]源码实现见 scrapy/commands/crawl.py一次只能传一个爬虫名超过一个会UsageError-o/-O由公共基类 BaseRunSpiderCommand 解析为FEEDS设置feed_process_params_from_cli因此输出走的是 Feed Export 机制若FeedExporter扩展被禁用engine 启动时会收到“配置了 FEEDS 但不会导出”的告警。check语法scrapy check [-l] spider需要项目是运行契约contract检查。$ scrapy check -l first_spider * parse * parse_item second_spider * parse * parse_item $ scrapy check F.F. FAIL: [first_spider] parse (returns post-hook) ---------------------------------------------------------------------- Traceback (most recent call last): ... scrapy.exceptions.ContractFail: Returned 92 requests, expected 0..4 FAIL: [first_spider] parse_item (scrapes post-hook) ---------------------------------------------------------------------- Traceback (most recent call last): ... scrapy.exceptions.ContractFail: Missing fields: RetailPricex ---------------------------------------------------------------------- Ran 4 contracts in 0.174s FAILED (failures2)-l只列出各爬虫中带契约的方法而不执行不带-l时对指定爬虫或全部爬虫真实发起请求并校验。实现见 scrapy/commands/check.py其process_options()会主动清空ITEM_PIPELINES与FEEDS契约会丢弃回调输出避免 pipeline 产生副作用测试报告格式沿用unittest.TextTestRunner。list语法scrapy list需要项目是列出当前项目全部可用爬虫每个一行$ scrapy list spider1 spider2实现很简单通过get_spider_loader(self.settings)加载爬虫后打印sorted(spider_loader.list())见 scrapy/commands/list.py。edit语法scrapy edit spider需要项目是用EDITOR环境变量未设置时取EDITOR设置项定义的编辑器打开指定爬虫文件。注意 scrapy/cmdline.py 中execute()会把环境变量EDITOR优先写入 settings即环境变量优先于设置项。这只是一个最常用场景的快捷方式开发者当然可以用任意工具或 IDE。$ scrapy edit spider1EDITOR的值可包含参数如code -wedit.py 会用shlex.split拆分后以子进程调用不经过 shell。fetch语法scrapy fetch url需要项目否用 Scrapy 的 downloader 下载给定 URL并把响应内容写到标准输出。它的价值在于“以爬虫的方式下载页面”例如爬虫若通过USER_AGENT属性覆盖了 User Agentfetch就会使用那个值——用它来“看清”爬虫实际会拿到什么。项目外使用时不应用任何爬虫级行为仅用 Scrapy 默认下载设置。支持的选项--spiderSPIDER跳过爬虫自动探测强制使用指定爬虫--headers打印请求与响应的 HTTP 头替代响应体--no-redirect不跟随 HTTP 3xx 重定向默认跟随。$ scrapy fetch --nolog http://www.example.com/some/page.html [ ... html content here ... ] $ scrapy fetch --nolog --headers http://www.example.com/ Accept: text/html,application/xhtmlxml,application/xml;q0.9,*/*;q0.8 Accept-Language: en User-Agent: Scrapy/X.Y (https://scrapy.org) Accept-Encoding: gzip, deflate, br, zstd Date: ... Content-Type: text/html Server: ...从源码看scrapy/commands/fetch.pyfetch会构造一个只包含单个Request的爬虫回调里打印响应--no-redirect通过handle_httpstatus_all True实现“连 3xx 也原样打印”而默认行为则是用SequenceExclude(range(300, 400))让框架正常处理 3xx。view语法scrapy view url需要项目否像爬虫“看到”的那样在浏览器中打开 URL。有时爬虫看到的页面与普通用户不同view可用于确认爬虫所见是否符合预期。支持的选项--spiderSPIDER绕过自动探测强制使用指定爬虫--no-redirect不跟随 HTTP 3xx 重定向默认跟随。$ scrapy view http://www.example.com/some/page.html [ ... browser starts ... ]实现上 view.py 直接继承fetch.Command把“打印响应体”替换为对TextResponse调用open_in_browser()非文本响应会报错“Cannot view a non-text response”。shell语法scrapy shell [url]需要项目否为给定 URL可省略启动 Scrapy 交互 shell详见 shell 文档。还支持 UNIX 风格的本地文件路径——相对路径带./或../前缀或绝对路径。支持的选项--spiderSPIDER绕过自动探测强制使用指定爬虫-c code在 shell 中执行代码、打印结果并退出--no-redirect不跟随命令行参数 URL 的 HTTP 3xx 重定向默认跟随注意这只影响命令行传入的 URL进入 shell 后fetch(url)默认仍会跟随重定向。$ scrapy shell http://www.example.com/some/page.html [ ... scrapy shell starts ... ] $ scrapy shell --nolog http://www.example.com/ -c (response.status, response.url) (200, http://www.example.com/) # shell 默认跟随重定向 $ scrapy shell --nolog http://httpbin.org/redirect-to?urlhttp%3A%2F%2Fexample.com%2F -c (response.status, response.url) (200, http://example.com/) # 可用 --no-redirect 关闭仅针对命令行参数 URL $ scrapy shell --no-redirect --nolog http://httpbin.org/redirect-to?urlhttp%3A%2F%2Fexample.com%2F -c (response.status, response.url) (302, http://httpbin.org/redirect-to?urlhttp%3A%2F%2Fexample.com%2F)源码中shell命令声明了default_settings见 scrapy/commands/shell.pyDUPEFILTER_CLASS指向BaseDupeFilter不记录去重状态、LOGSTATS_INTERVAL 0不输出周期统计、REMOTE_CONTROL_ENABLED False不启用 telnet 远程控制——这些都是为交互式调试做的轻量化处理。parse语法scrapy parse url [options]需要项目是抓取给定 URL并用处理该 URL 的爬虫解析它回调方法由--callback指定缺省为parse。支持的选项--spiderSPIDER绕过自动探测强制使用指定爬虫-a NAMEVALUE设置爬虫参数可重复--callback/-c解析响应所用的爬虫方法--meta/-m附加到回调请求的 request meta必须是合法 JSON 字符串如--meta{foo : bar}--cbkwargs附加到回调的 kwargs必须是合法 JSON 字符串如--cbkwargs{foo : bar}--pipelines让 item 经过 item pipeline 处理--rules/-r用CrawlSpider的 rules 发现解析响应所用的回调方法--noitems不显示抓到的 item--nolinks不显示提取出的链接--nocolour不使用 pygments 着色--depth/-d递归跟随请求的深度默认 1--verbose/-v显示每一深度层级的信息--output/-o把抓到的 item 转储到文件。$ scrapy parse http://www.example.com/ -c parse_item [ ... scrapy log lines crawling example.com spider ... ] STATUS DEPTH LEVEL 1 # Scraped Items ------------------------------------------------------------ [{name: Example item, category: Furniture, length: 12 cm}] # Requests ----------------------------------------------------------------- []settings语法scrapy settings [options]需要项目否查看设置项的值。项目内使用时显示项目设置值否则显示 Scrapy 默认值$ scrapy settings --get BOT_NAME scrapybot $ scrapy settings --get DOWNLOAD_DELAY 0源码 settings.py 中还提供了类型化的读取选项--getbool SETTING、--getint SETTING、--getfloat SETTING、--getlist SETTING分别按布尔/整数/浮点/列表解释并打印。runspider语法scrapy runspider spider_file.py需要项目否运行给定 Python 文件中定义的爬虫无需项目。支持的选项与crawl相同二者共用BaseRunSpiderCommand基类。$ scrapy runspider myspider.py [ ... spider starts crawling ... ]实现细节scrapy/commands/runspider.py临时把文件所在目录插入sys.path头部导入该文件要求文件中至少有一个Spider子类取第一个其default_settings将SPIDER_LOADER_CLASS设为DummySpiderLoader即不加载任何项目爬虫。version语法scrapy version [-v]需要项目否打印 Scrapy 版本加-v同时打印 Python、Twisted 和平台信息提交 bug 报告时有用$ scrapy version -v Scrapy : 2.x.y Python : 3.x.z ... Twisted : ...bench语法scrapy bench需要项目否运行一个快速基准测试详见 benchmarking 文档。从 scrapy/commands/bench.py 可以看到其工作方式用subprocess启动本地基准服务器scrapy.utils.benchserver监听http://localhost:8998然后运行内置的_BenchSpider抓取total100000个页面统计抓取速率——这是验证本机 Scrapy 运行环境性能的标准手段。需要启动爬取的命令CrawlerProcess 的选择机制以下命令都需要以某种方式运行一次抓取用户爬虫或内部特殊爬虫bench、check、crawl、fetch、parse、runspider、shell、view。它们内部使用scrapy.crawler.AsyncCrawlerProcess或scrapy.crawler.CrawlerProcess的一个实例。大多数情况下这个细节对用户无关紧要但当你需要非默认 Twisted reactor时它就很重要了。Scrapy 的选择规则见 scrapy/cmdline.py 的execute()TWISTED_REACTOR_ENABLED为False时使用AsyncCrawlerProcess否则若TWISTED_REACTOR为默认值twisted.internet.asyncioreactor.AsyncioSelectorReactor同样使用AsyncCrawlerProcess其余情况使用CrawlerProcess。爬虫级设置不参与该决策——它在这个决定做出之后才加载。因此如果项目级设置是 asyncio reactor显式设置或 Scrapy 默认而被运行爬虫的设置却改为其他 reactorAsyncCrawlerProcess会因只支持 asyncio reactor 而报错。此时的解决办法是把FORCE_CRAWLER_PROCESS设置为True项目级或在命令行传入强制 Scrapy 使用支持所有 reactor 的CrawlerProcess。相关设置的默认值可见 scrapy/settings/default_settings.pyFORCE_CRAWLER_PROCESS False与 asyncio 文档。自定义项目命令通过 COMMANDS_MODULE 注册借助COMMANDS_MODULE设置可以为项目添加专属命令它们会被自动发现并经scrapy工具暴露出来。COMMANDS_MODULE 设置默认值为空字符串见 default_settings.py。指向一个用于查找自定义命令的模块例如COMMANDS_MODULE mybot.commands创建自定义命令继承scrapy.commands.ScrapyCommand并实现必需方法即可为命令行界面扩展项目专属功能如数据处理工具、部署辅助。行为由类属性与重写方法共同决定。可设置的属性requires_projectbool为True时命令只能在项目内运行默认Falserequires_crawler_processbool为True时 Scrapy 会在命令运行前创建AsyncCrawlerProcess或CrawlerProcess实例并挂到crawler_process属性上默认Truedefault_settingsdict该命令运行时覆盖默认设置的字典默认{}exitcodeint命令完成时设置的进程退出码默认0。必须重写的方法short_desc()返回命令的简短描述run(args, opts)命令执行的主入口。可以重写的方法syntax()返回命令语法建议单行、不含命令名long_desc()返回详细描述add_options(parser)向参数解析器添加命令专属选项process_options(args, opts)处理命令行选项、在crawler_process实例化之前设置 settings。一个完整示例from scrapy.commands import ScrapyCommand import argparse class MyCustomCommand(ScrapyCommand): requires_project True def syntax(self): return [options] spider_name def short_desc(self): return Run my custom command def add_options(self, parser): super().add_options(parser) parser.add_argument(--my-option, helpMy custom option) def run(self, args, opts): # Command implementation here spider_name args[0] if args else None print(fRunning custom command for spider: {spider_name})真实示例可参考 scrapy/commands 目录下的全部内置命令。ScrapyCommand类属性与requires_project/requires_crawler_process的默认值见 scrapy/commands/init.py。命令发现流程本身由 scrapy/cmdline.py 的_get_commands_dict()完成先扫描内置scrapy.commands模块再合并 entry points 与COMMANDS_MODULE中找到的命令类。注意COMMANDS_MODULE属于 pre-crawler 设置在创建爬虫进程之前就已生效。通过 setup.py entry points 注册供外部库使用外部库也可以在库的setup.py或等价打包配置的 entry points 中添加scrapy.commands段来注册命令。例如添加my_command命令from setuptools import setup, find_packages setup( namescrapy-mymodule, entry_points{ scrapy.commands: [ my_commandmy_scrapy_module.commands:MyCommand, ], }, )该机制在 scrapy/cmdline.py 中实现_get_commands_from_entry_points()通过importlib.metadata.entry_points(groupscrapy.commands)加载所有已安装库注册的命令并与内置命令合并。附注deploy 命令的历史沿革早期的scrapy deploy命令已在 1.0 中移除被独立的scrapyd-deploy工具取代。部署相关需求请参考 Deploying your project 文档。小结scrapy命令行工具是 Scrapy 的总入口scrapy.cfg三级合并加环境变量决定了“在哪个项目、用哪套设置”下工作14 个内置命令覆盖了从startproject建项、genspider生成爬虫到crawl/runspider运行、fetch/view/shell/parse调试、settings/version/bench运维辅助的完整生命周期而ScrapyCommand基类、COMMANDS_MODULE与scrapy.commandsentry points 三条扩展路径使团队可以无缝地把私有工具接入scrapy命令空间。遇到行为疑问时scrapy command -h加上 scrapy/commands 与 scrapy/cmdline.py 源码是最快的定位路径。【免费下载链接】scrapyScrapy, a fast high-level web crawling scraping framework for Python.项目地址: https://gitcode.com/GitHub_Trending/sc/scrapy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考