日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Python爬蟲的任務(wù)數(shù)據(jù)操作的小技巧

 需求

爬取某網(wǎng)站的項(xiàng)目列表頁(yè),獲取其url,標(biāo)題等信息,作為后續(xù)爬取詳情頁(yè)的任務(wù)url。

先上代碼

代碼

 
 
 
  1. # -*- coding: utf-8 -*-
  2. # @Time : 2019-11-08 14:04
  3. # @Author : cxa
  4. # @File : motor_helper.py
  5. # @Software: PyCharm
  6. import asyncio 
  7. import datetime
  8. from loguru import logger
  9. from motor.motor_asyncio import AsyncIOMotorClient
  10. from collections import Iterable
  11. try:
  12.     import uvloop
  13.     asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
  14. except ImportError:
  15.     pass
  16. db_configs = {
  17.     'host': '127.0.0.1',
  18.     'port': '27017',
  19.     'db_name': 'mafengwo',
  20.     'user': ''
  21. }
  22. class MotorOperation:
  23.     def __init__(self):
  24.         self.__dict__.update(**db_configs)
  25.         if self.user:
  26.             self.motor_uri = f"mongodb://{self.user}:{self.passwd}@{self.host}:{self.port}/{self.db_name}?authSource={self.db_name}"
  27.         else:
  28.             self.motor_uri = f"mongodb://{self.host}:{self.port}/{self.db_name}"
  29.         self.client = AsyncIOMotorClient(self.motor_uri)
  30.         self.mb = self.client[self.db_name]
  31.     async def save_data_with_status(self, items, col="seed_data"):
  32.         for item in items:
  33.             data = dict()
  34.             data["update_time"] = datetime.datetime.now()
  35.             data["status"] = 0  # 0初始
  36.             data.update(item)
  37.             print("data", data)
  38.             await self.mb[col].update_one({
  39.                 "url": item.get("url")},
  40.                 {'$set': data, '$setOnInsert': {'create_time': datetime.datetime.now()}},
  41.                 upsert=True)
  42.      async def add_index(self, col="seed_data"):
  43.         # 添加索引
  44.         await self.mb[col].create_index('url')

因?yàn)槲业呐老x是異步網(wǎng)絡(luò)模塊aiohttp寫的,所以選擇了pymongo的異步版本motor進(jìn)行操作。

異步代碼的基本屬性就是async/await成對(duì)的出現(xiàn),如果把上面的await和async去掉,就是類似pymongo的寫法了,這里異步不是重點(diǎn),重點(diǎn)是我們?cè)趺刺幚砻織l數(shù)據(jù)。

這里除了網(wǎng)頁(yè)的url,標(biāo)題等信息,我需要附加3個(gè)字段。分別是create_time, status,update_time。

這三個(gè)字段分別代表,數(shù)據(jù)插入數(shù)據(jù),狀態(tài)和更新時(shí)間。

那么我為什么添加三個(gè)字段呢?

首先,我們需要判斷每次的任務(wù)數(shù)據(jù)是否存在,我這里的情況是存在就更新不存在就插入,那么我就需要一個(gè)查詢條件,作為更新的條件,很顯然這里可以使用任務(wù)的url作為唯一條件(你還可以使用url+標(biāo)題做個(gè)md5然后保存),好了查詢條件確定。

下面說(shuō)create_time這個(gè)比較好理解就是數(shù)據(jù)插入時(shí)間,關(guān)鍵是為什么還要一個(gè)update_time,這個(gè)的話和status字段有一定的關(guān)系。畫重點(diǎn):這個(gè)status作為后續(xù)爬蟲進(jìn)行爬取的一個(gè)標(biāo)志用。目前這個(gè)status有4個(gè)值,0-4,我這是這樣定義的,

0:初始狀態(tài)

1:抓取中的任務(wù)

2:抓取成功

3:抓取失敗

4:抓取成功但是沒(méi)有匹配到任務(wù)。

后面隨著任務(wù)的爬取,狀態(tài)也是不斷變化的,同時(shí)我們需要更新update_time為最新的時(shí)間。這個(gè)目前的話是體現(xiàn)不出來(lái)什么作用,它的使用場(chǎng)景是,重復(fù)任務(wù)的抓取,比如今天我抓取了任務(wù)列表里的url1、url2,第二天的時(shí)候我如果再抓到,為了區(qū)分是抓取失敗還是抓取成功,我們根據(jù)create_time和update_time就可以進(jìn)行推斷了,如果兩者相同而且是當(dāng)前的日期說(shuō)明剛抓的,如果update_time的日期比create_time新可以說(shuō)明,抓到了重復(fù)的任務(wù)。關(guān)于字段的設(shè)計(jì)就啰嗦這么些。

下面是實(shí)現(xiàn),我們可以通過(guò)update_one方法,對(duì)數(shù)據(jù)作存在或者插入操作,因?yàn)閡rl作為查詢條件,后面量大的話就最好添加一個(gè)索引。也就是上面的 add_index方法。

好了最好說(shuō)插入更新的具體代碼

需要注意的是

 
 
 
  1. {'$set': data, '$setOnInsert': {'create_time': datetime.datetime.now()}}

$setOnInsert里面使用的字段是數(shù)據(jù)不存在的時(shí)候才插入的,存在就不動(dòng)了,只插入$set里面指定的。

另外$setOnInsert里面使用的字段不能在$set里面再次出現(xiàn)

upsert=True代表的是不存在就插入。


網(wǎng)站標(biāo)題:Python爬蟲的任務(wù)數(shù)據(jù)操作的小技巧
網(wǎng)站URL:http://www.dlmjj.cn/article/dpgcppi.html