内容简介:MongoDB 避免插入重复数据。摘要:尽量使用 update_one() 方法而不是 insert_one() 插入数据。相信你一定有过这样的经历:大晚上好不容易写好一个爬虫,添加了种种可能出现的异常处理,测试了很多遍都没有问题,点击了 RUN 开始正式运行 ,然后美滋滋地准备钻被窝睡觉,睡前还特意检查了下确认没有问题,合上眼后期待着第二天起来,数据都乖乖地躺在 MongoDB 中。第二天早上一睁眼就满心欢喜地冲到电脑前,结果发现爬虫半夜断了,你气得想要砸电脑,然后你看了一下 MongoDB 中爬了一半
MongoDB 避免插入重复数据。
摘要:尽量使用 update_one() 方法而不是 insert_one() 插入数据。
相信你一定有过这样的经历:大晚上好不容易写好一个爬虫,添加了种种可能出现的异常处理,测试了很多遍都没有问题,点击了 RUN 开始正式运行 ,然后美滋滋地准备钻被窝睡觉,睡前还特意检查了下确认没有问题,合上眼后期待着第二天起来,数据都乖乖地躺在 MongoDB 中。第二天早上一睁眼就满心欢喜地冲到电脑前,结果发现爬虫半夜断了,你气得想要砸电脑,然后你看了一下 MongoDB 中爬了一半的数据,在想是删掉重新爬,还是保留下来接着爬。
到这儿问题就来了,删掉太可惜,接着爬很可能会爬到重复数据,虽然后期可以去重,但你有强迫症,就是不想爬到重复数据,怎么办呢?
这就遇到了「爬虫断点续传」问题,关于这个问题的解决方法有很多种,不过本文主要介绍 数据存储到 MongoDB 时如何做到只插入新数据,而重复数据自动过滤不插入。
先来个简单例子,比如现在有两个 list ,data2 中的第一条数据和 data 列表中的第一条数据是重复的,我们想将这两个 list 依次插入 MnogoDB 中去, 通常我们会使用 insert_one() 或者 insert_many() 方法插入,这里我们使用 insert_one() 插入,看一下效果。
data = [ {'index':'A','name':'James','rank':'1' }, {'index':'B','name':'Wade','rank':'2' }, {'index':'C','name':'Paul','rank':'3' }, ] data2 = [ {'index':'A','name':'James','rank':'1' }, {'index':'D','name':'Anthony','rank':'4' }, ] import pymongo client = pymongo.MongoClient('localhost',27017) db = client.Douban mongo_collection = db.douban for i in data: mongo_collection.insert_one(i)
插入第一个 list :
插入第二个 list :
你会发现,重复的数据 A 被插入进去了,那么怎么只插入 D,而不插入 A 呢,这里就要用到 update_one() 方法了,改写一下插入方法:
for i in data2: mongo_collection.update_one(i,{'$set':i},upsert=True)
这里用到了 $set
运算符,该运算符作用是将字段的值替换为指定的值,upsert 为 True 表示插入。这里也可以用 update() 方法,但是这个方法比较老了,不建议使用。另外尝试使用 update_many() 方法发现不能更新多个相同的值。
for i in data2: mongo_collection.update(i, i, upsert=True)
下面举一个豆瓣电影 TOP250 的实例,假设我们先获取 10 个电影的信息,然后再获取前 20 个电影,分别用 insert_one() 和 update_one() 方法对比一下结果。
insert_one() 方法会重复爬取 前 10 个电影的数据:
update_one() 方法则只会插入新的 10 个电影的数据:
这就很好了对吧,所以当我们去爬那些需要分页的网站,最好在爬取之前使用 update_one() 方法,这样就算爬虫中断了,也不用担心会爬取重复数据。
代码实现如下:
import requests import json import csv import pandas as pd from urllib.parse import urlencode import pymongo client = pymongo.MongoClient('localhost', 27017) db = client.Douban mongo_collection = db.douban class Douban(object): def __init__(self): self.url = 'https://api.douban.com/v2/movie/top250?' def get_content(self, start_page): params = { 'start': start_page, 'count': 10 } response = requests.get(self.url, params=params).json() movies = response['subjects'] data = [{ 'rating': item['rating']['average'], 'genres':item['genres'], 'name':item['title'], 'actor':self.get_actor(item['casts']), 'original_title':item['original_title'], 'year':item['year'], } for item in movies] self.write_to_mongodb(data) def get_actor(self, actors): actor = [i['name'] for i in actors] return actor def write_to_mongodb(self, data): for item in data: if mongo_collection.update_one(item, {'$set': item}, upsert=True): # if mongo_collection.insert_one(item): print('存储成功') else: print('存储失败') def get_douban(self, total_movie): # 每页10条,start_page循环1次 for start_page in range(0, total_movie, 10): self.get_content(start_page) if __name__ == '__main__': douban = Douban() douban.get_douban(10)
本文完。
以上所述就是小编给大家介绍的《爬虫断了?一招搞定 MongoDB 重复数据》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Lambda Calculus, Its Syntax and Semantics . Revised Edition
H.P. Barendregt / North Holland / 1985-11-15 / USD 133.00
The revised edition contains a new chapter which provides an elegant description of the semantics. The various classes of lambda calculus models are described in a uniform manner. Some didactical impr......一起来看看 《The Lambda Calculus, Its Syntax and Semantics . Revised Edition》 这本书的介绍吧!