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存在插入不存在更新,同时指定如果不存在才插入的字段的更多相关文章

  1. Python Mongo操作

    # -*- coding: utf-8 -*- ''' Python Mongo操作Demo Done: ''' from pymongo import MongoClient conn = None ...

  2. Python之路,Day25-----暂无正在更新中

    Python之路,Day25-----暂无正在更新中

  3. Python之路,Day26-----暂无正在更新中

    Python之路,Day26-----暂无正在更新中

  4. Python之路,Day23-----暂无正在更新中

    Python之路,Day23-----暂无正在更新中

  5. Python之路,Day13-----暂无正在更新中

    Python之路,Day13-----暂无正在更新中

  6. MySQL 避免重复数据的批量插入与批量更新

    [转发] 导读 我们在向数据库里批量插入数据的时候,会遇到要将原有主键或者unique索引所在记录更新的情况,而如果没有主键或者unique索引冲突的时候,直接执行插入操作. 这种情况下,有三种方式执 ...

  7. spring data jpa开启批量插入、批量更新

    spring data jpa开启批量插入.批量更新 原文链接:https://www.cnblogs.com/blog5277/p/10661096.html 原文作者:博客园--曲高终和寡 *** ...

  8. MySql快速插入以及批量更新

    MySql快速插入以及批量更新 插入: MySql提供了可以一次插入多条数据的用法: [sql] INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6), ...

  9. mysql主键重复,不抱错,只更新的骚操作 (如果没有插入,如果有更新)

    平时我们在设计数据库表的时候总会设计 unique  或者 给表加上 primary key 的限制条件. 此时 插入数据的时候 ,经常会有这样的情况: 我们想向数据库插入一条记录: 若数据表中存在以 ...

随机推荐

  1. 学习笔记之CloudCompare

    CloudCompare - Open Source project https://www.danielgm.net/cc/ 3D point cloud and mesh processing s ...

  2. Java 之 函数式接口

    函数式接口 一.概念 函数式接口在 java 中是指:有且仅有一个抽象方法的接口. 函数式接口,即适用于函数式编程场景的接口. 而Java中的函数式编程体现就是Lambda,所以函数式接口就是可以适用 ...

  3. 蓝牙 BLE 三种 UUID 格式转换

    蓝牙广播中对服务 UUID 格式定义都有三种 16 bit UUID.32 bit UUID.128 bit UUID. 但是熟悉安卓开发的小伙伴都知道接口都 UUID 格式,fromString 时 ...

  4. AI人脸识别SDK接入 — 参数优化篇(虹软)

    引言 使用了虹软公司免费的人脸识别算法,感觉还是很不错的,当然,如果是初次接触的话会对一些接口的参数有些疑问的.这里分享一下我对一些参数的验证结果(这里以windows版本为例,linux.andro ...

  5. springboot学习入门简易版八---springboot2.0多环境配置、整合mybatis mysql8+(19-20)

    2.11 SpringBoot多环境配置(19)  application.properties中配置 Spring.profiles.active=prd 配置环境: Application-dev ...

  6. 臀部——哑铃&杠铃

  7. 快速搭建Kerberos服务端及入门使用

    快速搭建Kerberos服务端及入门使用 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Kerberos是一种网络身份验证协议.它旨在通过使用秘密密钥加密为客户端/服务器应用程序提 ...

  8. 1.后期特效合成AE概述&&工作流程&&磁盘缓存清理

    1.简介: After Effects:是一款专业的后期制作与特效合成软件: 2.AE界面介绍  2.1 项目面板   2.2 合成预览面板   2.3 时间线面板     2.4 辅助面板    2 ...

  9. STL用法之set

    [C++::STL]之set的用法 c++ set求差集,并集,交集

  10. Caused by: java.nio.charset.MalformedInputException: Input length = 1

    java.lang.IllegalStateException: Failed to load property source from location 'classpath:/applicatio ...