zoukankan      html  css  js  c++  java
  • pandas数据处理(一)pymongo数据库量大插入时去重速度慢

      之前写脚本爬斗鱼主播信息时用了一个pymongo的去重语句

    db['host_info'].update({'主播': data['主播'], '时间': data['时间']}, {'$set': data}, True):

      这句话以主播和时间为索引判断数据库中如果没有同一主播同一时间的数据就更新到数据库。一开始还是很好用的,爬取速度还可以,但是我的计划是每天晚上爬取黄金时间整点段的数据,几个小时过后数据量就达到了十几万条,然后速度越来越慢,mongodb进程占用cpu率很高,可以看到数据是一条条地存进去。毕竟以十几万条数据为基准去重工作量很大,随着数据量的增长会更加慢,直到我的电脑爆掉。

      仔细分析了一下,我用主播和时间作为索引,每一个整点爬取一次,所以每一次爬取的时间肯定不一样,也就是每一次爬的过程中可能会有重复数据,次与次之间不会存在重复数据。于是就把数据先放入一个空的临时数据表中,仍然用上面的去重方法做去重,等数据全部爬完后再把临时空数据库中的数据存入主数据库中,这时只需要插入,不需要去重,存入的速度是很快的。

    #-*- coding:utf-8 -*-
    #_author:John
    #date:2018/12/29 20:11
    import time
    from functools import partial
    import requests
    import json
    from multiprocessing import Pool
    import pymongo
    import datetime
    
    client = pymongo.MongoClient('localhost')
    db = client['douyu']
    
    
    def single_page_info(page, cur_time):
        # 防止网络无响应,重试3次
        for i in range(3):
            try:
                respones = requests.get('https://www.douyu.com/gapi/rkc/directory/0_0/{}'.format(page))
                break
            except Exception as E:
                print(E)
                respones = None
                time.sleep(10)
        if respones:
            datas = json.loads(respones.text)
            items = datas['data']['rl']
            for item in items:
                data = {
                    '标题': item['rn'],
                    '主播': item['nn'],
                    '人气': item['ol'],
                    '类别': item['c2name'],
                    '房间号': item['rid'],
                    '时间': cur_time
                }
                # 用临时数据表完成此次爬虫的去重工作,在程序结束前把临时数据表删除
                if db['host_info_draft'].update({'主播': data['主播']}, {'$set': data}, True):
                    print('Save to Mongo, {}'.format(data))
                else:
                    print('Save to Mong fail, {}'.format(data))
            print('已经完成第{}页'.format(page))
    
    
    # 存入主数据表
    def write_to_primary_db(data):
        db['host_infos'].insert_one(data)
    # 删除临时数据表
    def drop_draft():
        db.drop_collection('host_info_draft')
    
    
    if __name__ == '__main__':
        pool = Pool()
        print('start')
        # 多线程抓200页
        while True:
            # 判断当前时间是否为整点,如果是则开始爬虫程序
            minute = datetime.datetime.now().strftime('%M')
            if int(minute) < 2:
                # 把初始时间传入作为此次爬虫统一时间,python3用partial可以在map中传入的函数传递参数
                cur_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M')
                pool.map(partial(single_page_info, cur_time=cur_time), [page for page in range(1, 201)])
                print('Move the temporary table to the primary table')
                pool.map(write_to_primary_db, [data for data in db['host_info_draft'].find()])
                print('End with this cycle')
                drop_draft()
                sleep_time = 60 - int(datetime.datetime.now().strftime('%M'))
                time.sleep(sleep_time*60)
            else:
                time.sleep(58)
    
        # cur_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M')
        # pool.map(partial(single_page_info, cur_time=cur_time), [page for page in range(1, 201)])
        # drop_draft()
  • 相关阅读:
    简单协议解析
    三刺激值
    74hc595
    色彩理论
    灰度值和强度值概念
    RGB 常用颜色对照表
    IAR注释的快捷键
    visual studio 2015 2017 key vs2015 vs2017密钥
    如何在cmd命令行中查看、修改、删除与添加环境变量
    win cmd 设置代理
  • 原文地址:https://www.cnblogs.com/lkd8477604/p/10201137.html
Copyright © 2011-2022 走看看