Scrapy数据库异步插入的坑

 

重要参考: 将爬虫数据插入SQL数据库是为什么出现重复?

重要参考: scrapy爬虫,数据入库后一直有重复数据,百思不得其解!!求指导

这是跟我遇到相同问题找到的两个参考,看了下他们的解释,大致原因如下:

因为数据库柄插入操作是次线程的,与主线程不同步,但是你传递给数据库柄的item 是引用传递,如果主线程中改变item的值了,那么次线程中的item也会改变,所以当数据库真正要插入第一条记录时,可能已经成了第三条记录了。前面两条记录就没有了。解决办法:将引用传递 修改成值传递,或者 生成多个item对象,每次yeild的item对象不是同一个。

用户:Mycro,这样解释:

数据爬出来的是对的,入库才会出现重复,问题出在:

query = self.dbpool.runInteraction(self._Cate_insert, Item)
_Cate_insert()

这句话上,这句话之前打印到文件就是对的,之后打印的就会出错,有重复有丢失,但数目刚好是一样的。

_Cate_insert() 执行的时候,Item已经变了。

因此问题就出在 这句话是异步的,Item ,这个对象,在出现了共享出现了问题。

这个解释的就很明确,和我做的测试一模一样

用户qq_33245827

其原因是由于Spider的速率比较快,而scapy操作数据库操作比较慢,导致pipeline中的方法调用较慢,这样当一个变量正在处理的时候,一个新的变量过来,之前的变量的值就会被覆盖,比如pipline的速率是1TPS,而spider的速率是5TPS,那么数据库应该会有5条重复数据。

解决方案是对变量进行保存,在保存的变量进行操作,通过互斥确保变量不被修改

#pipeline默认调用
def process_item(self, item, spider):
    #深拷贝
    asynItem = copy.deepcopy(item)
    d = self.dbpool.runInteraction(self._do_upinsert, asynItem, spider)

 

这个就是更加通俗易懂,我也尝试过这个解决方法,但是最后发现这个deepcopy效率实在是太慢了,把异步的效果都牺牲掉了,有种得不偿失的感觉,还不如同步呢

简单来说其实就是引用传参的问题

所以将item定义到循环里面,scrapy自带多线程

直接借用大佬的图片,这样一改就可以了

这个方法很靠谱,利用了scrapy的多线程,生成了不同的item,就将引用分开了,测试下,有恢复到异步的速度,而且数据没有重复

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值