thinkphp 5.1 中使用原生 swoole\process 实现多子进程并发网页采集,需禁用 opcache 保存注释、子进程重初始化应用并独立建库连接,通过自定义命令启动,错误日志按 pid 分离。

在 ThinkPHP 5.1 中通过 Swoole Process 启动多个独立子进程并发采集网页数据,避免单进程阻塞、提升抓取吞吐量,适用于中等规模的定向爬虫任务。
安装与环境准备
确认 PHP 已启用 Swoole 扩展(版本 ≥ 4.4.0),并在项目根目录执行:composer require topthink/think-swoole。该扩展提供 Process 封装支持,但本方案直接使用原生 Swoole\Process,不依赖其组件。
修改 public/index.php 入口文件顶部,添加 define('APP_PATH', __DIR__ . '/../application/'); 确保后续类加载路径正确。
【必须关闭 OPcache 的 opcache.save_comments = 0 设置】,否则匿名函数序列化失败会导致子进程启动报错。
创建进程管理器类
在 application/common/library/ 下新建 CrawlerProcessManager.php:
定义静态方法 start($urls, $callback),接收待采集 URL 数组和回调函数;内部调用 new Swoole\Process(...) 创建子进程,每个进程处理一个 URL;主进程用 pcntl_wait() 阻塞等待全部结束。
子进程内需重新初始化 ThinkPHP 应用实例:调用 require APP_PATH . 'init.php' 并手动触发 App::run()->send(),否则无法加载模型、配置和数据库连接。
编写采集逻辑回调
在 application/command/ 下新建 CrawlCommand.php,继承 think\Command:
重写 configure() 设置命令名为 crawl:multi;execute() 中构造 URL 列表,例如 $urls = ['https://example.com/1', 'https://example.com/2']。
定义匿名回调函数,参数为 $url 和 $pid,内部使用 curl_init() 或 file_get_contents() 获取页面内容,解析后写入数据库或本地文件;注意每个子进程必须独立建立数据库连接,不可复用父进程连接。
调用 CrawlerProcessManager::start($urls, $callback) 启动全部子进程。
启动爬虫命令
执行 php think crawl:multi 运行命令。
若出现 Segmentation fault,大概率是子进程中调用了未 fork 安全的扩展(如某些 Redis 扩展),需改用 phpredis 并在子进程内重新 connect。
子进程退出码非 0 时,主进程会记录错误日志到 runtime/log/crawl_error_日期.log,按 PID 区分错误来源。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











