Webman 与 Scrapy 无法直接集成,只能通过进程间协作:Webman 用 proc_open 调用 Scrapy 命令,Scrapy 在 Pipeline 中直连数据库写入数据,并通过 spider_logs 表反馈执行状态。

Webman 和 Scrapy 不能直接集成运行 —— 它们属于完全不同的运行时环境:Webman 是 PHP 框架(常驻内存、基于 Swoole),Scrapy 是 Python 框架(基于 Twisted/asyncio)。两者无法共进程、不共享内存、不兼容解释器。所谓“集成”,实际只能是「进程间协作」,核心思路是让 Webman 触发 Scrapy 爬虫任务,并接收其结果写入数据库。
Webman 怎么调用 Scrapy 爬虫?用 shell_exec 或 proc_open
Webman 的控制器里不能 import Scrapy 模块,但可以执行外部命令。最常用方式是通过 PHP 的 shell_exec 启动 Scrapy 项目:
- 确保服务器已安装 Python 3.8+、Scrapy、以及爬虫项目依赖(如
clickhouse-driver或pymysql) - Scrapy 项目需支持命令行参数传入起始 URL 或配置项,例如:
scrapy crawl news_spider -a url=https://example.com/feed - 在 Webman 的 Controller 中,用
shell_exec执行该命令,并捕获输出(注意超时和权限):
public function runSpider(Request $request) {
$url = $request->input('url', 'https://example.com');
$cmd = "cd /path/to/scrapy_project && scrapy crawl news_spider -a url={$url} 2>&1";
$output = shell_exec($cmd);
return json(['status' => 'done', 'output' => $output]);
}
⚠️ 注意:shell_exec 在生产环境常被禁用;更稳妥的方式是用 proc_open 控制 stdin/stdout/stderr,并设置 timeout 防止爬虫卡死。
Scrapy 怎么把数据交给 Webman?别“交”,直接写库
不要试图让 Scrapy 把数据“返回”给 Webman —— HTTP 回调、Redis 中转、临时文件都增加复杂度且易出错。正确做法是:Scrapy 自己完成入库。
- 在 Scrapy 的
pipelines.py中,直接连接目标数据库(MySQL/ClickHouse/PostgreSQL) - 使用对应 Python 客户端,例如写 ClickHouse 推荐
clickhouse-driver,写 MySQL 推荐pymysql或sqlalchemy - 避免在 Pipeline 中做耗时操作(如网络请求、复杂计算),否则会阻塞 Scrapy 的异步调度
- 务必开启批量写入:ClickHouse 建议每批 1000–10000 行,MySQL 建议用
executemany替代循环execute
示例(ClickHouse 写入):
from clickhouse_driver import Client
class ClickHousePipeline:
def open_spider(self, spider):
self.client = Client(host='127.0.0.1', port=9000, database='default')
def process_item(self, item, spider):
self.client.execute(
"INSERT INTO news (title, url, pub_time) VALUES",
[[item['title'], item['url'], item['pub_time']]]
)
return item
为什么不用 Webman 接收 Scrapy 的 JSON 输出?
常见误区是让 Scrapy 把数据 dump 成 JSON,再由 Webman file_get_contents 读取。这看似“解耦”,实则埋坑:
- 文件路径权限问题:Webman 进程用户和 Scrapy 进程用户可能不同,写入失败静默
- 竞态条件:多个爬虫并发写同一文件,内容覆盖或解析失败
- 无状态残留:JSON 文件未及时清理,磁盘占满
- 性能瓶颈:大体积 JSON 解析 + 插入,比原生数据库驱动慢 3–5 倍
- 错误难定位:Scrapy 写失败,Webman 读不到,但日志分散在两边
真正需要“Webman 接收数据”的场景极少,仅适用于调试或极低频小数据量。生产环境一律走 Scrapy 直连数据库。
如何让 Webman 知道爬虫是否成功?靠日志 + 状态表
Webman 调用 scrapy crawl 后,不能靠命令返回码 0/1 判断业务成功 —— Scrapy 即使抓取失败也可能退出码为 0(比如部分请求超时但 pipeline 正常结束)。
- 在 Scrapy 的
close_spider方法中,写一条状态记录到数据库(如spider_logs表),含spider_name、start_time、item_count、error_count、finish_time - Webman 调用完后,查这张表的最新记录,判断
item_count > 0且error_count == 0 - 加个简单重试逻辑:若首次查不到记录,sleep 1s 后再查,最多 3 次
这个状态表是整个链路可观测性的基础,比任何 stdout 解析都可靠。
真正的难点不在调用方式,而在于 Scrapy Pipeline 的异常恢复能力 —— 比如 ClickHouse 写入中途断连、MySQL 主键冲突、字段类型不匹配。这些必须在 process_item 里显式 try/catch 并记录错误 item,否则整条流水线就静默丢数据了。


















