python爬虫数据提取脚本

背景

使用scrapy_redis框架时,为了利用redis高效的io,通常回把数据放到redis上。在任务结束后则需要将redis里的结果数据迁移。

场景

将爬虫数据从redis迁移到mongodb,并且提取生成一份excel格式的文件

使用方法

参数2:指定爬虫结果集

参数3~:指定指定结果集中键在excel中的别名

python export.py [spider_name]:items redis_key1=excel_title1 redis_key2=excel_title2

脚本

有些地方些的不太好,后续优化~

import sys
import time
import redis
import pymongo
import json
import openpyxl


# 配置
REDIS_HOST = "redis host"
REDIS_PORT = 6379
REDIS_DB = 0
REDIS_PWD = "redis password"
REDIS_COL = ""  # 导出数据的目标集合
MONGO_HOST = "mongodb host"
MONGO_PORT = 27017
MONGO_DB = ""   # 数据存储的库名
MONGO_COL = ""  # 数据存储的集合名
MONGO_USER = "mongodb username"
MONGO_PWD = "mongodb password"


db_field = []   # 数据库字段
file_field = []     # 存入表的字段


def string_date():
    return time.strftime("%Y_%m_%d", time.localtime())


class MoveData:
    def __init__(self, redis_db, redis_col, db_field: list, file_field: list):
        """
        满足调用MoveData实例完成数据迁移
        :param redis_db: 迁移数据所在redis库
        :param redis_col: 迁移数据所在redis集合     DanKeRent:items
        :param db_field: 提取迁移数据的字段名
        :param file_field: 数据保存文件的字段名
        :param path: 保存数据的文件路径
        """
        self.redis_db = redis_db
        self.redis_col = redis_col
        self.db_field = db_field
        self.file_field = file_field
        self.mongo_db = self.redis_col.split(":")[0]       # mongo库名不改
        self.mongo_col = self.mongo_db + "_{}".format(string_date())   # mongo集合名添加日期后缀
        self.redis = redis.Redis(
            host=REDIS_HOST,
            port=REDIS_PORT,
            db=redis_db,
            password=REDIS_PWD
        )
        self.mongo = pymongo.MongoClient(
            host=MONGO_HOST,
            port=MONGO_PORT,
            username=MONGO_USER,
            password=MONGO_PWD
        )
        self.mongo_db_handle = self.mongo[self.mongo_db]
        self.mongo_col_handle = self.mongo_db_handle[self.mongo_col]
        self.workbook = None    # excel文件对象
        self.sheet = None
        self.write_line = 0

    def skip_redis(self):
        self.redis_empty()

    def move(self):
        # 将数据从redis迁移到mongo
        redis_data_len = self.redis.llen(self.redis_col)
        for index in range(redis_data_len):
            data = self.redis.lindex(self.redis_col, index)
            data = json.loads(data)
            print("导出redis缓存 {}: {}".format(index, data))
            self.mongo_col_handle.insert(data)
            print("导出redis缓存 {}: {}".format(index, data))
        if not redis_data_len:
            print("redis中无对应数据,直接从mongodb中导出数据")
            self.redis_empty()

    def redis_empty(self):
        # 当要迁移的redis列表不存在时(可能输入错误,也可能已经迁移过了)
        colls = self.mongo_db_handle.list_collection_names()
        select = max([time.mktime(time.strptime(coll[-10:], "%Y_%m_%d")) for coll in colls])
        select_date = time.strftime("%Y_%m_%d", time.localtime(select))
        self.mongo_col = self.mongo_db + "_{}".format(select_date)
        self.mongo_col_handle = self.mongo_db_handle[self.mongo_col]

    def create_file(self):
        self.workbook = openpyxl.Workbook()     # 新建工作簿
        self.sheet = self.workbook.create_sheet(self.redis_col.split(":")[1])    # 以redis集合名作为excel sheet名
        for cols in range(len(file_field)):
            self.sheet.cell(self.write_line + 1, cols + 1).value = file_field[cols]
        print("写入列名: {}".format(file_field))
        self.write_line += 1

    def save_row(self, data):
        for row in range(len(db_field)):
            self.sheet.cell(self.write_line + 1, row + 1).value = data.get(db_field[row], None)
        print("提取数据 {}: {}".format(self.write_line, data))
        self.write_line += 1

    def to_file(self):
        # 将迁移到mongodb的数据保存到文件(excel)
        # 1.创建文件excel
        self.create_file()
        # 2.遍历提取数据
        print("正在导表:{}".format(self.mongo_col))
        for data in self.mongo_col_handle.find():
            self.save_row(data)
        # 3.保存数据
        save_path = "{}.xlsx".format(self.mongo_col)
        self.workbook.save(save_path)

    def over(self):
        # 删除redis缓存
        self.redis.delete(self.redis_col)

    def run(self):
        self.move()
        # self.skip_redis()
        self.to_file()
        self.over()


if __name__ == '__main__':
    # 需要迁移的redis列表
    REDIS_COL = sys.argv[1]
    for i in sys.argv[2:]:
        before, after = i.split("=")
        db_field.append(before)
        file_field.append(after)
    m = MoveData(
        redis_db=REDIS_DB,
        redis_col=REDIS_COL,        # spider_name:items
        db_field=db_field,          # 字段列表
        file_field=file_field,      # 导表表头列表
    )
    m.run()
    time.sleep(10)


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值