Python中如何结合Tornado与Scrapy(Twisted)框架实现异步非阻塞和实时响应?
有谁处理处理过 Tornado+scrapy(Twisted) 框架结合吗?目前在参考( http://www.tornadoweb.org/en/stable/twisted.html#twisted-on-tornado )
主要目标:
0, 支持 newrelic 服务器监控
1, 异步非阻塞
2,realtime 实时响应(不经过任何数据库存储)
选择 Tornado 是因为支持 newrelic,这是主要原因,还有异步
Twisted 也是异步非阻塞。
以下方案我也参考过
scrapyDO, 已经被改造成阻塞(如 flask+scrapy 都是如此)
scrapyrt(modify)( https://github.com/haijunt/scrapyrt), 支持 realtime,不支持 newrelic
arachnado ( https://github.com/TeamHG-Memex/arachnado)
其他
pyspider 正在考虑研究。
Python中如何结合Tornado与Scrapy(Twisted)框架实现异步非阻塞和实时响应?
或者说能够使用 tornado.platform.twisted
具体是在 Tornado 框架下
import tornado.platform.twisted
tornado.platform.twisted.install()
from twisted.internet import reactor
调用 Scrapy 启动爬虫(EvenvLoop 事件循环的代码)
dfd = process.crawl(QuotesSpider)
# process.start() # the script will block here until the crawling is finished d.addBoth(lambda _: reactor.stop())
result = dfd.addCallback(self.result_items)
并且直接拿到爬取数据。
参考链接如下:
https://stackoverflow.com/questions/36384286/how-to-integrate-flask-scrapy
http://www.tornadoweb.org/en/stable/twisted.html#twisted-on-tornado
https://doc.scrapy.org/en/latest/topics/practices.html
核心思路:
Tornado 的 IOLoop 与 Scrapy/Twisted 的 Reactor 不能直接共存,需要借助 twisted.internet.asyncioreactor 将 Twisted 整合到 Tornado 的 asyncio 事件循环中,或者通过 CrawlerRunner 在 Tornado 中启动 Scrapy。
方案示例(使用 asyncio 桥接):
import asyncio
from tornado.platform.asyncio import AsyncIOMainLoop
from twisted.internet import asyncioreactor
from scrapy.crawler import CrawlerRunner
from scrapy.utils.project import get_project_settings
# 1. 在导入 Twisted 前安装 asyncio reactor
asyncioreactor.install(asyncio.get_event_loop())
# 2. 启动 Tornado 的 AsyncIOMainLoop
AsyncIOMainLoop().install()
import tornado.web
from twisted.internet import reactor
class MainHandler(tornado.web.RequestHandler):
async def get(self):
# 3. 在 Tornado 中异步启动 Scrapy
runner = CrawlerRunner(get_project_settings())
deferred = runner.crawl('your_spider_name')
# 将 Twisted Deferred 转为 asyncio Future
future = asyncio.wrap_future(deferred.asFuture(asyncio.get_event_loop()))
await future
self.write("Crawl finished")
def make_app():
return tornado.web.Application([(r"/", MainHandler)])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
关键点:
- 必须最先安装 asyncio reactor,避免 Twisted 默认 reactor 冲突。
- 使用
AsyncIOMainLoop让 Tornado 运行在 asyncio 上。 - 通过
asyncio.wrap_future()或deferred.asFuture()转换 Twisted 的 Deferred 对象。
一句话建议: 用 asyncio 作事件循环桥梁来整合两者。
原理是:Twisted 建立连接和请求,scrapy 分析数据,tornado 显示?
不知道目的是什么。我的做法是解耦,scrapy 只管并发抓取的事
pyspider rpc 调用挺好的
Tornado 做 webserver (可以用 newrelic 做服务器监控), 调用 scrapy 项目的爬虫并实时响应返回。( scrapyrt 是用 Twisted 做 Webserver:不能够与 newrelic 搭配使用 XXX )
1, 需要的是实时响应,类似 scrapyrt(realtime, nonblocking)这种。但 scrapyrt 是使用 Twisted 做 WebServer,并不能与 newrelic(:一种服务器监控软件)搭配使用。现在想使用 Tornado 做 WebServer(支持 newrelic,且异步)。
我没太懂啊,实时响应的意思是前端传一个 URL,爬虫马上去抓取然后返回结果给 client ?那这过程不是同步的么?
请问楼主有没有新进展?我也想做类似的


