You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask整合Scrapyrt爬虫进程后子进程挂起问题排查

解决Flask与Scrapy整合时爬虫挂起的问题

我碰到过好几个类似的整合场景,核心问题基本都绕不开Twisted和Flask的事件循环冲突——毕竟两者都想抢占主线程,直接硬凑在一起肯定会“打架”。结合你的描述,大概率是这些细节没处理好:

1. 事件循环冲突:同步Flask阻塞了Twisted

Flask默认用Werkzeug的同步服务器,而Scrapy(包括Scrapyrt)依赖Twisted的异步事件循环。如果直接在Flask的主线程里启动爬虫,Twisted的reactor会被Flask的同步逻辑阻塞,导致爬虫进程挂起。

解决方法:用线程隔离爬虫运行

把爬虫的启动逻辑放到单独的线程里,让Flask主线程和Twisted reactor互不干扰:

from flask import Flask
from scrapy.crawler import CrawlerRunner
from scrapy.utils.log import configure_logging
from twisted.internet import reactor, defer
import threading

app = Flask(__name__)

# 导入你的Scrapy爬虫类
from my_scrapy_project.spiders.my_spider import MySpider

# 初始化Scrapy配置
configure_logging()
runner = CrawlerRunner(settings={
    'USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
    'ITEM_PIPELINES': {'my_scrapy_project.pipelines.MyPipeline': 300},
    # 这里补充你的Scrapy项目其他配置
})

def run_spider():
    @defer.inlineCallbacks
    def crawl():
        yield runner.crawl(MySpider)
        reactor.stop()  # 爬虫完成后停止reactor
    # 禁用信号处理,避免和Flask的信号冲突
    reactor.run(installSignalHandlers=False)

@app.route('/start-crawl')
def trigger_crawl():
    # 启动新线程运行爬虫,不阻塞Flask主线程
    threading.Thread(target=run_spider, daemon=True).start()
    return '爬虫已启动,后台运行中!'

if __name__ == '__main__':
    # 关闭Flask调试模式的自动重载,避免重复启动reactor
    app.run(debug=True, use_reloader=False)

2. 调试模式的自动重载坑

如果开启了Flask的debug=True,默认的自动重载机制会重启进程,导致Twisted reactor被重复启动,直接引发冲突。一定要加上use_reloader=False避免这个问题。

3. 未正确初始化Scrapy环境

单独运行Scrapyrt时,它会自动加载你的Scrapy项目配置(比如settings.py),但整合到Flask里时,你需要手动初始化这些配置——否则爬虫找不到管道、中间件等依赖,会静默挂起。

进阶方案:让Flask和Scrapyrt共享Twisted事件循环

既然Scrapyrt本身就是基于Twisted的Web服务,你可以直接把Flask app挂载到Twisted的reactor上,让两者共享同一个事件循环,彻底避免冲突:

from flask import Flask
from scrapyrt.server import Scrapyrt
from twisted.web.wsgi import WSGIResource
from twisted.web.server import Site
from twisted.internet import reactor

app = Flask(__name__)

# 添加你的Flask业务路由
@app.route('/')
def home():
    return '这是Flask的主页,访问/crawl可以触发Scrapy爬虫!'

# 初始化Scrapyrt,指定你的Scrapy项目配置
scrapyrt = Scrapyrt(settings_module='my_scrapy_project.settings')

# 把Flask资源挂载到Twisted站点
flask_resource = WSGIResource(reactor, reactor.getThreadPool(), app)
scrapyrt.root_resource.putChild(b'flask', flask_resource)

# 启动整合后的Twisted服务
site = Site(scrapyrt.root_resource)
reactor.listenTCP(8080, site)
print('服务启动:http://localhost:8080/flask(Flask) | http://localhost:8080/crawl(Scrapyrt)')
reactor.run()

这样你既可以用Scrapyrt的原生API触发爬虫,也能正常访问Flask的业务路由,完全不需要分开启动两个终端服务。

内容的提问来源于stack exchange,提问作者8-Bit Borges

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:43:42