在Django中集成Scrapy遭遇SynchronousOnlyOperation错误求合规方案
解决Django集成Scrapy时的SynchronousOnlyOperation错误
方法一:用Django异步ORM接口适配Scrapy异步Pipeline(Django 3.1+可用)
Scrapy现在默认用异步Pipeline,而Django ORM同步操作不能在异步上下文里直接执行,这就是报错的核心原因。你可以用asgiref.sync里的sync_to_async把同步ORM操作包装成异步执行:
from scrapy.exceptions import DropItem from myapp.models import MyModel from asgiref.sync import sync_to_async class DjangoPipeline: async def process_item(self, item, spider): # 把同步的create操作转成异步执行 await sync_to_async(MyModel.objects.create)( field1=item['field1'], field2=item['field2'] ) return item
要是你用的是Django 4.2及以上版本,还能直接用ORM的异步创建方法acreate,写法更简洁:
async def process_item(self, item, spider): await MyModel.objects.acreate( field1=item['field1'], field2=item['field2'] ) return item
方法二:强制Scrapy用同步Pipeline
要是不想折腾异步逻辑,直接把Pipeline改成同步的就行——只要把process_item写成普通的同步方法,不需要加async关键字:
from myapp.models import MyModel from scrapy.exceptions import DropItem class DjangoPipeline: def process_item(self, item, spider): MyModel.objects.create( field1=item['field1'], field2=item['field2'] ) return item
另外可以在Scrapy的settings.py里加一行配置,确保使用同步反应器,避免异步上下文的干扰:
TWISTED_REACTOR = "twisted.internet.selectreactor.SelectReactor"
方法三:直接用数据库驱动操作(不推荐)
如果上面两种方法都有问题,也可以绕开Django ORM,直接用数据库驱动(比如psycopg2)写SQL语句保存数据。但这种方法需要自己处理数据校验、事务等逻辑,维护成本高,仅适合应急场景。
内容的提问来源于stack exchange,提问作者kévin Goncalves
相关产品推荐
相关产品推荐

