python mongo存在插入不存在更新,同时指定如果不存在才插入的字段
python爬虫的任务数据操作的小技巧
好久没写公众号了,最近太忙了,这里就不多说了。直接根据需求上代码,我想这个应该是大家比较喜欢的,
需求
爬取某网站的项目列表页,获取其url,标题等信息,作为后续爬取详情页的任务url。
先上代码
代码
# -*- coding: utf-8 -*-
# @Time : 2019-11-08 14:04
# @Author : cxa
# @File : motor_helper.py
# @Software: PyCharm
import asyncio
import datetime
from loguru import logger
from motor.motor_asyncio import AsyncIOMotorClient
from collections import Iterable
try:
import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
except ImportError:
pass
db_configs = {
'host': '127.0.0.1',
'port': '27017',
'db_name': 'mafengwo',
'user': ''
}
class MotorOperation:
def __init__(self):
self.__dict__.update(**db_configs)
if self.user:
self.motor_uri = f"mongodb://{self.user}:{self.passwd}@{self.host}:{self.port}/{self.db_name}?authSource={self.db_name}"
else:
self.motor_uri = f"mongodb://{self.host}:{self.port}/{self.db_name}"
self.client = AsyncIOMotorClient(self.motor_uri)
self.mb = self.client[self.db_name]
async def save_data_with_status(self, items, col="seed_data"):
for item in items:
data = dict()
data["update_time"] = datetime.datetime.now()
data["status"] = 0 # 0初始
data.update(item)
print("data", data)
await self.mb[col].update_one({
"url": item.get("url")},
{'$set': data, '$setOnInsert': {'create_time': datetime.datetime.now()}},
upsert=True)
async def add_index(self, col="seed_data"):
# 添加索引
await self.mb[col].create_index('url')
因为我的爬虫是异步网络模块aiohttp写的,所以选择了pymongo的异步版本motor进行操作。
异步代码的基本属性就是async/await成对的出现,如果把上面的await和async去掉,就是类似pymongo的写法了,这里异步不是重点,重点是我们怎么处理每条数据。
这里除了网页的url,标题等信息,我需要附加3个字段。分别是create_time, status,update_time。
这三个字段分别代表,数据插入数据,状态和更新时间。
那么我为什么添加三个字段呢?
首先,我们需要判断每次的任务数据是否存在,我这里的情况是存在就更新不存在就插入,那么我就需要一个查询条件,作为更新的条件,很显然这里可以使用任务的url作为唯一条件(你还可以使用url+标题做个md5然后保存)。好了查询条件确定,
下面说create_time这个比较好理解就是数据插入时间,关键是为什么还要一个update_time,这个的话和status字段有一定的关系。 画重点:这个status作为后续爬虫进行爬取的一个标志用。目前这个status有4个值,0-4,我这是这样定义的,
0:初始状态 1:抓取中的任务 2:抓取成功 3:抓取失败 4:抓取成功但是没有匹配到任务。
后面随着任务的爬取,状态也是不断变化的,同时我们需要更新update_time为最新的时间。这个目前的话是体现不出来什么作用,它的使用场景是,重复任务的抓取,比如今天我抓取了任务列表里的url1,url2,第二天的时候我如果再抓到,为了区分是抓取失败还是抓取成功,我们根据create_time和update_time就可以进行推断了,如果两者相同而且是当前的日期说明刚抓的,如果update_time的日期比create_time新可以说明,抓到了重复的任务。关于字段的设计就啰嗦这么写。
下面是实现,我们可以通过update_one方法,对数据作存在或者插入操作,因为url作为查询条件,后面量大的话就最好添加一个索引。也就是上面的 add_index方法。
好了最好说插入更新的具体代码
需要注意的是
{'$set': data, '$setOnInsert': {'create_time': datetime.datetime.now()}}
$setOnInsert里面使用的字段是数据不存在的时候才插入的,存在就不动了,只插入$set里面指定的。
另外$setOnInsert里面使用的字段不能在$set里面再次出现
upsert=True代表的是不存在就插入。
大概就这么多,不明白的可以给我留言,或者添加微信进群交流。
python mongo存在插入不存在更新,同时指定如果不存在才插入的字段的更多相关文章
- Python Mongo操作
# -*- coding: utf-8 -*- ''' Python Mongo操作Demo Done: ''' from pymongo import MongoClient conn = None ...
- Python之路,Day25-----暂无正在更新中
Python之路,Day25-----暂无正在更新中
- Python之路,Day26-----暂无正在更新中
Python之路,Day26-----暂无正在更新中
- Python之路,Day23-----暂无正在更新中
Python之路,Day23-----暂无正在更新中
- Python之路,Day13-----暂无正在更新中
Python之路,Day13-----暂无正在更新中
- MySQL 避免重复数据的批量插入与批量更新
[转发] 导读 我们在向数据库里批量插入数据的时候,会遇到要将原有主键或者unique索引所在记录更新的情况,而如果没有主键或者unique索引冲突的时候,直接执行插入操作. 这种情况下,有三种方式执 ...
- spring data jpa开启批量插入、批量更新
spring data jpa开启批量插入.批量更新 原文链接:https://www.cnblogs.com/blog5277/p/10661096.html 原文作者:博客园--曲高终和寡 *** ...
- MySql快速插入以及批量更新
MySql快速插入以及批量更新 插入: MySql提供了可以一次插入多条数据的用法: [sql] INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6), ...
- mysql主键重复,不抱错,只更新的骚操作 (如果没有插入,如果有更新)
平时我们在设计数据库表的时候总会设计 unique 或者 给表加上 primary key 的限制条件. 此时 插入数据的时候 ,经常会有这样的情况: 我们想向数据库插入一条记录: 若数据表中存在以 ...
随机推荐
- 如何导出ane所需的swc
来源:http://blog.sina.com.cn/s/blog_6471e1bb01012ard.html 打包.ane文件的时候需要用到ActionScript的扩展库(swc文件),那么如何生 ...
- javascript_17-基本类型和引用类型
基本类型 直接存储值 Number . String .Boolean undefined.null 引用类型 存储引用 -Object.Array.Date.函数 包装基本类型--引用类型 func ...
- Nginx配置文件示例
Nginx的配置文件示例:(仅供参考) 强烈建议先将默认的配置文件备份再进行操作! 请根据自己项目的实际路径来配置相关路径! uwsgi配置文件请参考:uwsgi配置文件示例 # For more i ...
- 微信小程序中使用云开发获取openid
微信小程序获取openid 新建一个微信小程序项目 注意要注册一个自己的小程序账号,并有属于自己的appid 点击云开发按钮,自行填入开发环境名称 打开app.js,找到依赖环境 修改为刚才设置的环境 ...
- [centos][yum] centos升级到特定版本
我们已知,yum upgrade命令可以将整个系统升级到最新版本. 但是很多时候,我们需要更新到指定版本,比如,当前最新的CentOS版本是7.6.1810 但是我需要更新到7.4,可以如下这样做: ...
- 公用表表达式(CTE) with as
在编写T-SQL代码时,往往需要临时存储某些结果集.前面我们已经广泛使用和介绍了两种临时存储结果集的方法:临时表和表变量.除此之外,还可以使用公用表表达式的方法.公用表表达式(Common Table ...
- gdb调试(二)
继续研究gdb相关的调试技巧,话不多说进入正题: 查看运行时数据: 这个上节中已经用过了,这里就不多说了,比较简单 还是有上节中的simple.c例子,不过得稍微做一些修改为了使用这些命令: simp ...
- 0030redis主从复制以及哨兵模式的搭建
------------------------------redis主从备份以及哨兵模式------------------------------------------------------- ...
- (三)WCF之契约
自从我们接收ITOO项目之后,就必须跟WCF打交道,既然必须直面WCF,我就对WCF进行了研究(还不是很深入,是自己目前的理解).之前对WCF的一些基础知识进行了简单的介绍,本篇重点来介绍WCF的契约 ...
- test20190825 AmberFrame
100+0+99=199,第二题一分没得不应该. count 给定 \(n\),求合法的 \((x_1,x_2,x_3,\dots,x_{2m})\) 组数.一组 \(x\) 是合法的,当且仅当 \[ ...