ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

pyspider 快速上手与架构解析:用 Python 编写脚本驱动的高性能爬虫系统

2026/9/21 16:21:17 拓冰建站 浏览量
pyspider 快速上手与架构解析:用 Python 编写脚本驱动的高性能爬虫系统 pyspider 快速上手与架构解析用 Python 编写脚本驱动的高性能爬虫系统【免费下载链接】pyspiderA Powerful Spider(Web Crawler) System in Python.项目地址: https://gitcode.com/gh_mirrors/py/pyspiderpyspider 是一个用 Python 编写的强大爬虫Web Crawler系统它通过消息队列把调度、抓取、解析与结果存储解耦为可独立扩展的组件并自带集成了脚本编辑器、任务监控、项目管理与结果查看的 WebUI。阅读本文后你将掌握 pyspider 的安装启动方式、基于BaseHandler编写爬虫脚本的核心 API 用法以及其分布式架构与存储/消息队列选型背后的设计原理。项目概览pyspider 是什么pyspider 定位为 A Powerful Spider(Web Crawler) System in Python是一套完整的爬虫解决方案而非单纯的抓取库。它在单一进程内串联了调度Scheduler、抓取Fetcher、解析Processor、结果落地Result Worker与可视化控制台WebUI等组件让用户可以用极少的代码管理成百上千个站点的采集任务。从仓库根目录的 README.md 可以看到pyspider 的核心卖点包括用 Python 编写脚本解析逻辑是普通的 Python 代码配合 PyQuery 等库即可完成页面提取强大的 WebUI内置脚本编辑器、任务监控、项目管理与结果查看器甚至支持逐步调试脚本多样化的存储后端MySQL、MongoDB、Redis、SQLite、Elasticsearch以及通过 SQLAlchemy 接入的 PostgreSQL多样化的消息队列RabbitMQ、Redis 与 Kombu也支持内置的进程内队列丰富的任务语义任务优先级priority、失败重试retry、定时周期任务periodical、按过期时间重爬recrawl by age等分布式与动态渲染组件间通过消息队列解耦、可多实例横向扩展并支持抓取 JavaScript 渲染的页面。当前仓库中的版本号为0.4.0见 pyspider/init.py入口命令由 pyspider/run.py 提供。快速安装与启动README 给出的安装与启动方式极其简单pip install pyspider pyspider执行pyspider命令后所有组件会以默认配置在本地启动随后访问http://localhost:5000/即可进入 WebUI。安全警告务必配置访问认证这是 README 中特别强调的一点也是实际部署中最容易踩的坑WARNING:WebUI is open to the public by default, it can be used to execute any command which may harm your system. Please use it in an internal network or [enableneed-authfor webui].也就是说WebUI 默认是公开可访问的它不仅能管理任务还能在服务器上执行任意命令可能危害你的系统。因此要么只在内网使用要么显式开启认证。开启方式是在启动参数或配置文件中设置--need-auth并配合--username/--password仓库根目录的 config_example.json 给出了完整示例{ taskdb: couchdbtaskdb://user:passwordcouchdb:5984, projectdb: couchdbprojectdb://user:passwordcouchdb:5984, resultdb: couchdbresultdb://user:passwordcouchdb:5984, message_queue: amqp://rabbitmq:5672/%2F, webui: { username: username, password: password, need-auth: true, scheduler-rpc: http://scheduler:23333, fetcher-rpc: http://fetcher:24444 } }配置文件通过-c/--config传入pyspider -c config.json其内容以 JSON 形式为各子命令提供默认值。认证逻辑可以在 pyspider/webui/login.pyapp.config.get(need_auth, False)与 pyspider/webui/webdav.py 中看到实际生效点。各组件与all模式不带子命令直接运行pyspider时等价于执行pyspider all——把所有组件以子进程Windows 上为线程的方式一次性拉起见 pyspider/run.py 中all命令的实现。其中fetcher_num、processor_num、result_worker_num分别控制抓取器、处理器与结果工作者的实例数量默认均为 1pyspider all --fetcher-num 2 --processor-num 4 --result-worker-num 1后续的 命令行参考 一节会给出各子命令的完整参数说明。用 BaseHandler 编写你的第一个爬虫README 给出了一个可直接运行的示例脚本它涵盖了 pyspider 脚本的核心骨架定时入口、页面解析、链接提取与结果返回。from pyspider.libs.base_handler import * class Handler(BaseHandler): crawl_config { } every(minutes24 * 60) def on_start(self): self.crawl(http://scrapy.org/, callbackself.index_page) config(age10 * 24 * 60 * 60) def index_page(self, response): for each in response.doc(a[href^http]).items(): self.crawl(each.attr.href, callbackself.detail_page) def detail_page(self, response): return { url: response.url, title: response.doc(title).text(), }下面逐段拆解这段脚本的语义并结合 pyspider/libs/base_handler.py 的源码说明其底层机制。入口方法on_start与every每个项目的起点是名为on_start的回调。在 WebUI 中点击项目的Run按钮时系统会生成一个on_start任务交给调度器作为项目任务流的入口。every(minutes24 * 60)装饰器表示让该方法周期性执行——这里是每 24 小时触发一次非常适合作为入口不断刷新首页、发现新链接。从源码看every装饰器会为函数打上is_cronjobTrue标记并计算tick统一换算成秒BaseHandlerMeta元类则收集所有 cronjob并求其间隔的最大公约数min_tick。调度器只需每min_tick秒下发一次_on_cronjob任务再在处理器侧按各函数的tick判断是否真正执行从而显著减少定时任务的数量对应实现见 base_handler.py 中every与BaseHandlerMeta的注释。提取链接与response.docresponse.doc(...)返回的是一个 PyQuery 对象底层是 lxml因此你可以用 CSS 选择器选取元素。示例中a[href^http]选取所有以http开头的超链接each.attr.href取出链接地址再通过self.crawl(each.attr.href, callbackself.detail_page)生成新的抓取任务——这是典型的广度优先爬取模式由入口页发现列表页再由列表页发现详情页。config与按年龄重爬config(age10 * 24 * 60 * 60)的含义是该回调产出的新任务在10 天后会被视为过期需要重新抓取。从源码看config装饰器把配置写入函数的_config属性_crawl在为任务组装schedule字段时会读取它。实际上BaseHandler把任务参数划分成了三组见 base_handler.py 中的schedule_fields、fetch_fields、process_fields调度相关priority优先级、retries重试次数、exetime定时执行时间、age过期重爬、itag、auto_recrawl、cancel等抓取相关method、headers、user_agent、data、timeout、allow_redirects、cookies、proxy、etag、last_modified、save以及js_run_at、js_script、load_images等 JavaScript 渲染参数处理相关callback、process_time_limit。每个任务还会以md5(url)生成全局唯一的taskid对应get_taskid方法调度器据此判断任务是全新的、需要重爬还是可以跳过。返回结果与on_resultdetail_page返回一个字典处理器会把它交给on_result回调见 base_handler.py 的on_result实现若当前不在调试器环境且配置了result_queue结果会被放入结果队列由 Result Worker 写入resultdb。也就是说回调函数的返回值就是一条结果pyspider 负责完成从解析到入库的整条链路你还可以覆写on_result来对接自己的业务系统。分布式架构消息队列连接的六大组件README 强调 pyspider 采用分布式架构其本质在于所有组件通过消息队列相互连接每个组件包括消息队列本身都运行在独立的进程/线程中并且是可替换的。这意味着当解析成为瓶颈时你可以启动多个 Processor 实例充分利用多核 CPU甚至把组件部署到多台机器上。完整的组件职责与数据流设计可以进一步阅读 docs/Architecture.md下图是其架构总览各组件职责如下组件职责Scheduler从newtask_queue接收新任务判定是新任务还是需要重爬按优先级排序并通过令牌桶token bucket算法做流量控制后交给 Fetcher负责定时任务、丢失任务与失败任务的延迟重试。注意当前实现只允许一个 Scheduler 实例。Fetcher负责实际抓取网页并送回 Processor支持 Data URI 与 JavaScript 渲染页面通过 phantomjs抓取方法、headers、cookies、proxy、etag 等均可由脚本控制。Phantomjs Fetcher以代理形式工作接入通用 Fetcher负责渲染启用 JavaScript 的页面后输出普通 HTML 回传给 Fetcher。Processor运行用户编写的解析脚本捕获异常与日志向 Scheduler 回传任务状态track与新任务并把结果发给 Result Worker。Result Worker可选从 Processor 接收结果并写入resultdb内置实现可直接使用也支持覆写以满足自定义落地需求。WebUI一切的可视化前端脚本编辑器与调试器、项目管理、任务监控、结果查看与导出。典型的数据流是在 WebUI 点击Run向 Scheduler 提交on_start任务作为项目入口Scheduler 把on_start任务以 Data URI 的形式分发给 Fetcher对 Data URI 会构造一个假的请求/响应但流程与普通任务无异Fetcher 发出请求得到响应交给 ProcessorProcessor 调用on_start产生一批新 URL通过消息队列把任务完成状态与新任务发回 SchedulerScheduler 查库判定新任务是否需要抓取按序调度循环往复直到所有任务完成Scheduler 还会周期性检查定时任务以持续抓取最新数据。从 pyspider/run.py 可以看到消息队列的真实连接细节系统维护newtask_queue、status_queue、scheduler2fetcher、fetcher2processor、processor2result五条队列默认使用内置的multiprocessing.Queue一旦指定了--message-queue则全部替换为外部队列实现。存储后端与消息队列选型pyspider 将数据分为三类数据库分别对应三条独立的连接 URLtaskdb任务状态库projectdb项目脚本配置库resultdb结果库。默认情况下未指定任何 URL三者都会以 SQLite 形式落在--data-path默认./data目录下。若想接入其他后端参考 docs/Command-Line.md 中的 URL 格式mysql: mysqltype://user:passwdhost:port/database sqlite: sqlitetype:///path/to/database.db # 相对路径 sqlitetype:////path/to/database.db # 绝对路径 sqlitetype:// # 内存数据库 mongodb: mongodbtype://[username:password]host1[:port1][,...] couchdb: couchdbtype://[username:password]host[:port] sqlalchemy: sqlalchemypostgresqltype://user:passwdhost:port/database local: localprojectdb://filepath,filepath其中type必须是taskdb、projectdb、resultdb三者之一。对应实现分散在 pyspider/database 目录下支持 mysql、mongodb、redis、sqlite、elasticsearch、couchdb、sqlalchemy 与 local 等子包。消息队列的 URL 格式同样重要rabbitmq: amqp://username:passwordhost:5672/%2F redis: redis://host:6379/db Redis 3.x 集群模式可用逗号分隔多节点 kombu: kombutransport://userid:passwordhostname:port/virtual_host builtin: 默认进程内队列对应实现见 pyspider/message_queue 目录下的kombu_queue.py、rabbitmq.py与redis_queue.py。依赖清单见仓库根目录的 requirements.txt 与 setup.pyextras_require[all]汇总了各存储/队列的可选依赖。此外pyspider/run.py 中还兼容了 Docker 部署环境变量当检测到MYSQL_NAME、MONGODB_NAME、COUCHDB_NAME、RABBITMQ_NAME等环境变量时会自动从*_PORT_*_TCP_ADDR形式的地址拼接数据库或队列连接串——这也是 docker-compose.yaml 与 Dockerfile 能够开箱即用的原因。任务能力优先级、重试与按龄重爬README 提到的 Task priority, retry, periodical, recrawl by age 等能力全部通过self.crawl的调度参数暴露即前文schedule_fields对应的字段priority任务优先级Scheduler 按优先级排序出队retries失败重试次数exetime定时执行时间Unix 时间戳用于推迟到某个时刻再抓age任务有效期超过该秒数即视为过期并重新抓取这是保持数据新鲜度的关键itag内容标记用于按内容判断是否需要重抓auto_recrawl是否自动重爬cancel取消任务。定时周期任务则由every装饰器与 Scheduler 的_on_cronjob机制配合实现详见 pyspider/scheduler/scheduler.py 与 base_handler.py 中的_on_cronjob。更完整的任务状态机说明可以阅读 docs/About-Tasks.md。渲染 JavaScript 页面针对依赖 JavaScript 动态渲染的站点pyspider 提供了两种无头浏览器接入方式phantomjs通过pyspider phantomjs启动独立的 phantomjs 代理服务默认端口 25555再用--phantomjs-proxy接入all模式默认会自动尝试拉起puppeteer通过pyspider puppeteer启动默认端口 22222脚本位于 pyspider/fetcher/puppeteer_fetcher.js另有splash接入--splash-endpoint脚本见 pyspider/fetcher/splash_fetcher.lua。脚本侧通过fetch_type、js_script、js_run_at、js_viewport_width/height、load_images等抓取参数控制渲染行为。入门教程可以参考 docs/tutorial/Render-with-PhantomJS.md更多抓取参数见 docs/apis/self.crawl.md。命令行参考所有命令的帮助都可以通过pyspider --help与pyspider 子命令 --help获取。全局选项适用于所有子命令以下为 docs/Command-Line.md 与 pyspider/run.py 中整理出的完整列表Usage: pyspider [OPTIONS] COMMAND [ARGS]... A powerful spider system in python. Options: -c, --config FILENAME a json file with default values for subcommands. --logging-config TEXT logging config file for built-in python logging module --debug debug mode --queue-maxsize INTEGER maxsize of queue0 表示不限制 --taskdb TEXT database url for taskdb, default: sqlite --projectdb TEXT database url for projectdb, default: sqlite --resultdb TEXT database url for resultdb, default: sqlite --message-queue TEXT connection url to message queue, default: builtin multiprocessing.Queue --amqp-url TEXT [deprecated] amqp url for rabbitmq请改用 --message-queue --beanstalk TEXT [deprecated] beanstalk 配置请改用 --message-queue --phantomjs-proxy TEXT phantomjs proxy ip:port --puppeteer-proxy TEXT puppeteer proxy ip:port --data-path TEXT data dir pathSQLite 数据库与 counter dump 文件保存路径 --version Show the version and exit.各子命令要点如下pyspider all以子进程/线程方式运行全部组件可选--fetcher-num、--processor-num、--result-worker-num、--run-in [subprocess|thread]Windows 上始终用线程pyspider one [SCRIPTS]...单进程调试模式所有组件跑在同一个进程的 tornado.ioloop 上此模式不启动 WebUI结果默认输出到 stdout可用pyspider one result.txt重定向脚本路径可直接作为参数传入此时项目状态为 RUNNING可通过脚本注释# rate: 1.0、# burst: 3设置抓取速率-i/--interactive开启交互控制台提供crawl(url, projectNone, **kwargs)、quit_interactive()、quit_pyspider()等命令pyspider bench基准测试模式使用内存 SQLite 数据库替代磁盘数据库可选--total、--show等参数pyspider scheduler仅运行调度器只允许一个实例可选--inqueue-limit每个项目任务队列大小上限溢出忽略、--delete-time、--active-tasks、--loop-limit、--fail-pause-num连续失败 N 个任务后自动暂停项目0 表示禁用、--scheduler-cls等pyspider fetcher仅运行抓取器可选--poolsize最大并发抓取数默认 100、--proxy、--user-agent、--timeout、--phantomjs-endpoint、--puppeteer-endpoint、--splash-endpoint、--fetcher-cls等pyspider processor仅运行处理器可选--process-time-limit脚本处理时间上限默认 30 秒、--processor-clspyspider result_worker仅运行结果工作者可选--result-clspyspider webui仅运行 WebUI可选--host默认 0.0.0.0、--port默认 5000、--cdnJS/CSS CDN 服务需兼容 cdnjs、--scheduler-rpc、--fetcher-rpc、--max-rate/--max-burst、--username/--password、--need-auth、--webui-instance等pyspider phantomjs/pyspider puppeteer启动无头浏览器抓取服务支持--auto-restart崩溃自重启。全局选项也支持通过环境变量注入例如TASKDB、PROJECTDB、RESULTDB、AMQP_URL、WEBUI_HOST、WEBUI_PORT、DEBUG等见 pyspider/run.py 中各个envvar声明。快速开始与延伸阅读官方教程入口docs/tutorial/index.mdHTML/CSS 选择器、AJAX 与 HTTP 进阶、PhantomJS 渲染等快速上手docs/Quickstart.md项目与任务模型docs/About-Projects.md、docs/About-Tasks.mdAPI 参考docs/apis/index.mdself.crawl、self.send_message、Response等部署方案docs/Deployment.md、docs/Deployment-demo.pyspider.org.md、docs/Running-pyspider-with-Docker.md仓库根目录同时提供了 Dockerfile 与 docker-compose.yaml命令行详解docs/Command-Line.md。贡献与 LicenseREADME 建议的参与方式包括实际使用它、在 Issue 中反馈问题并提交 PR、加入用户组参与讨论。当前版本v0.4.0的 TODO 中列出的方向是可视化抓取界面类似 portia。项目采用 Apache License, Version 2.0 开源协议见 LICENSE仓库内还附带 tox.ini 与 tests 目录下的完整测试套件便于开发者理解各模块行为并贡献代码。【免费下载链接】pyspiderA Powerful Spider(Web Crawler) System in Python.项目地址: https://gitcode.com/gh_mirrors/py/pyspider创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考