重复数据_MongoDB 自动过滤重复数据
摘要:使用 update_one() 方法而不是 insert_one() 插入數據。
相信你一定有過這樣的經歷:大晚上好不容易寫好一個爬蟲,添加了種種可能出現的異常處理,測試了很多遍都沒有問題,點擊了 RUN 開始正式運行 ,然后美滋滋地準備鉆被窩睡覺,睡前還特意檢查了下確認沒有問題,合上眼后期待著第二天起來,數據都乖乖地躺在 MongoDB 中。第二天早上一睜眼就滿心歡喜地沖到電腦前,結果發現爬蟲半夜斷了,你氣得想要砸電腦,然后你看了一下 MongoDB 中爬了一半的數據,在想是刪掉重新爬,還是保留下來接著爬。
到這兒問題就來了,刪掉太可惜,接著爬很可能會爬到重復數據,雖然后期可以去重,但你有強迫癥,就是不想爬到重復數據,怎么辦呢?
這就遇到了「爬蟲斷點續傳」問題,關于這個問題的解決方法有很多種,不過本文主要介紹數據存儲到 MongoDB 時如何做到只插入新數據,而重復數據自動過濾不插入。
先來個簡單例子,比如現在有兩個 list ,data2 中的第一條數據和 data 列表中的第一條數據是重復的,我們想將這兩個 list 依次插入 MnogoDB 中去, 通常我們會使用 insert_one() 或者 insert_many() 方法插入,這里我們使用 insert_one() 插入,看一下效果。
1data = [2{'index':'A','name':'James','rank':'1' },3{'index':'B','name':'Wade','rank':'2' },4{'index':'C','name':'Paul','rank':'3' },5]67data2 = [8{'index':'A','name':'James','rank':'1' },9{'index':'D','name':'Anthony','rank':'4' }, 10] 11 12import pymongo 13client = pymongo.MongoClient('localhost',27017) 14db = client.Douban 15mongo_collection = db.douban 16 17for i in data: 18 mongo_collection.insert_one(i)插入第一個 list :
插入第二個 list :
你會發現,重復的數據 A 被插入進去了,那么怎么只插入 D,而不插入 A 呢,這里就要用到 update_one() 方法了,改寫一下插入方法:
1for i in data2: 2 mongo_collection.update_one(i,{'$set':i},upsert=True)這里用到了 $set 運算符,該運算符作用是將字段的值替換為指定的值,upsert 為 True 表示插入。這里也可以用 update() 方法,但是這個方法比較老了,不建議使用。另外嘗試使用 update_many() 方法發現不能更新多個相同的值。
1for i in data2: 2 mongo_collection.update(i, i, upsert=True)下面舉一個豆瓣電影 TOP250 的實例,假設我們先獲取 10 個電影的信息,然后再獲取前 20 個電影,分別用 insert_one() 和 update_one() 方法對比一下結果。
insert_one() 方法會重復爬取前 10 個電影,最終生成 30 個數據:
update_one() 方法則只會插入新的 10 個電影,最終生成 20 個數據:
這就很好了對吧,所以當我們去爬那些需要分頁的網站,最好在爬取之前使用 update_one() 方法,這樣就算爬蟲中斷了,也不用擔心會爬取重復數據。
代碼實現如下:
1import requests2import json3import csv4import pandas as pd5from urllib.parse import urlencode6import pymongo78client = pymongo.MongoClient('localhost', 27017)9db = client.Douban 10mongo_collection = db.douban 11class Douban(object): 12 def __init__(self): 13 self.url = 'https://api.douban.com/v2/movie/top250?' 14 15 def get_content(self, start_page): 16 params = { 17 'start': start_page, 18 'count': 10 19 } 20 response = requests.get(self.url, params=params).json() 21 movies = response['subjects'] 22 data = [{ 23 'rating': item['rating']['average'], 24 'genres':item['genres'], 25 'name':item['title'], 26 'actor':self.get_actor(item['casts']), 27 'original_title':item['original_title'], 28 'year':item['year'], 29 } for item in movies] 30 31 self.write_to_mongodb(data) 32 33 def get_actor(self, actors): 34 actor = [i['name'] for i in actors] 35 return actor 36 37 def write_to_mongodb(self, data): 38 for item in data: 39 if mongo_collection.update_one(item, {'$set': item}, upsert=True): 40 # if mongo_collection.insert_one(item): 41 print('存儲成功') 42 else: 43 print('存儲失敗') 44 45 def get_douban(self, total_movie): 46 # 每頁10條,start_page循環1次 47 for start_page in range(0, total_movie, 10): 48 self.get_content(start_page) 49 50if __name__ == '__main__': 51 douban = Douban() 52 douban.get_douban(10)本文完。
推薦閱讀:
從函數 def 到類 Class
從 類 Class 到 Scrapy
總結
以上是生活随笔為你收集整理的重复数据_MongoDB 自动过滤重复数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java previous_java –
- 下一篇: java 线程定时器_Java线程之Ti