如何通过Celery运行Scrapy Spider并解决任务意外中断问题
核心问题根因
你当前任务静默中断无报错的核心原因是os.system调用不会捕获Scrapy子进程的标准输出与错误输出,且字符串拼接命令存在语法风险,一旦运行出错就会直接退出无日志。
解决方案
1. 先捕获错误日志定位问题
将Celery任务中的os.system替换为subprocess调用,主动捕获所有输出写入日志,即可明确中断原因:
import subprocess import logging from pathlib import Path logger = logging.getLogger(__name__) @shared_task def task_scrape_from_author(author_name): """Scrape quotes from author""" django_path = Path(__file__).resolve().parent.parent scraper_dir = str(django_path / "scraper") # 用列表形式传参数,自动处理转义,避免命令注入/语法错误 cmd = [ "scrapy", "crawl", "some-quotes", "-a", f"author={author_name}" ] result = subprocess.run( cmd, cwd=scraper_dir, capture_output=True, text=True ) # 输出日志到Celery日志中 logger.info(f"Scrapy运行输出:{result.stdout}") if result.returncode != 0: logger.error(f"Scrapy运行失败,错误信息:{result.stderr}") raise RuntimeError(f"爬虫执行失败,返回码{result.returncode}")
修改后重启Celery worker,再触发任务即可从Celery日志中看到Scrapy的具体报错。
2. 更稳定的调用方案:直接使用Scrapy API
不需要通过Shell启动子进程,直接在Celery任务内调用Scrapy内置的CrawlerProcess运行爬虫,错误会直接抛出到Celery日志,运行效率更高也更稳定:
import os from pathlib import Path from scrapy.crawler import CrawlerProcess from scrapy.utils.project import get_project_settings # 导入你自己的爬虫类,路径按实际项目结构调整 from scraper.spiders.your_spider_file import SpecificAuthorQuotesSpider @shared_task def task_scrape_from_author(author_name): """Scrape quotes from author""" django_path = Path(__file__).resolve().parent.parent os.chdir(str(django_path / "scraper")) process = CrawlerProcess(get_project_settings()) # 直接传参数给爬虫类 process.crawl(SpecificAuthorQuotesSpider, author=author_name) # 阻塞运行直到爬虫结束 process.start()
3. 额外排查方向
如果按上面方法还是没有明确报错,可检查以下配置:
- 确认Celery worker的运行环境已完整安装Scrapy、Django等所有项目依赖
- 查看系统日志(如
/var/log/syslog)是否存在OOM杀死进程的记录,排除爬虫内存占用过高被系统强制终止的情况 - 检查Celery worker的超时、单进程最大任务数等配置,确认是否和爬虫的实际运行时长冲突
内容的提问来源于stack exchange,提问作者Surya Bhusal
相关产品推荐
相关产品推荐

