数据(资产对象)抽取——一键通关的快乐ing

一.人生苦短,学点Python

在编写完从Excel中抽取关键数据的时候,突然想到每家公司在对数据筛选要求上的不尽相同,于是乎又手写了另一个脚本作为plan-B,这回不仅在开头申明了用法说明和举例解释,还写了Readme提前补充一下,但固定的数据源是不存在的,如果只是算法的变量取值有变那倒还好说,就怕数据源的名词也有变,挨个同步岂不是要疯…

二.需求是第一生产动力

1.主线任务:数据抽取存放到新建文件中

2.赏金任务:写个replace(),通过该函数将文件中所有相同的【名词】进行替换;

3.修仙任务:对input()进行限制,如10分钟内连续输入5次则退出;

4.渡劫任务:实现输入的自动补全。

三.Just do it——干就完了

1.主线任务:抽取数据(plan-A)的代码
# coding:utf-8
# 抽选说明:依据'资产数量'和'重要程度'进行筛选,不要求用途名称相同的资产按照数量进行命名和排序
# 抽选方式:相同类型至少抽20%,10台以内全部抽选
# 关于数量的例子:
# 实际调查表中
#      资产名称             数量
#   应用系统服务器            10

# 调查表上传报告生成工具前应修改为:
#      资产名称             数量
#   应用系统服务器01          1
#   应用系统服务器02          1
#   应用系统服务器03-20       10

# 代码抽选的数据文件内存储为:
# [应用系统服务器01,应用系统服务器02]

# 导入模块
import sys
import openpyxl
import pprint
import re

# 定义:资产列表和字典
engine_Room_data = []
network_Equipment_data = []
aqData = []
fwqData = {}
zdData = []
glrjData = {}
application_System_data = []


# main:打开'调查表.xlsx',循序筛选每一个sheet的数据。
# 若'调查表.xlsx'发生更新,后期再由维护人员?手动更新代码即可。
def questionaire_main():
	#处理所有调用函数报错的情况
    try:
        wbData = file_read()
        engine_room_Function(wbData)
        network_equipment_Function(wbData)
        safety_equipment_Function(wbData)
        server_Function(wbData)
        terminal_Function(wbData)
        management_software_Function(wbData)
        application_system_Function(wbData)
        file_write()
    except SystemExit as err:
    	#将错误类型格式化成字符串
        message = pprint.pformat(err)
        if message == 'SystemExit(3)':
            sys.exit('文件读取失败!')
        elif message == 'SystemExit(4)':
            sys.exit('文件写入失败!')
        elif message == 'SystemExit(5)':
            sys.exit('sheet名字不正确(表2-物理机房)!')
        elif message == 'SystemExit(6)':
            sys.exit('sheet名字不正确(表3-网络设备)!')
        elif message == 'SystemExit(7)':
            sys.exit('sheet名字不正确(表4-安全设备)!')
        elif message == 'SystemExit(8)':
            sys.exit('sheet名字不正确(表6-服务器或存储设备)!')
        elif message == 'SystemExit(9)':
            sys.exit('sheet名字不正确(表7-终端或现场设备)!')
        elif message == 'SystemExit(10)':
            sys.exit('sheet名字不正确(表8-系统管理软件或平台)!')
        elif message == 'SystemExit(11)':
            sys.exit('sheet名字不正确(表9-业务应用系统或平台)!')
        elif message == 'SystemExit(12)':
            sys.exit('数据读取异常,\'表2-物理机房\' \'重要程度\'的内容有误。。。。。。')
        elif message == 'SystemExit(13)':
            sys.exit('数据读取异常,\'表3-网络设备\' \'数量\'的内容有误。。。。。。')
        elif message == 'SystemExit(14)':
            sys.exit('数据读取异常,\'表4-安全设备\' \'重要程度\'的内容有误。。。。。。')
        elif message == 'SystemExit(15)':
            sys.exit('数据读取异常,\'表6-服务器或存储设备\' \'数量\'的内容有误。。。。。。')
        elif message == 'SystemExit(16)':
            sys.exit('数据读取异常,\'表7-终端或现场设备\' \'数量\'的内容有误。。。。。。')
        elif message == 'SystemExit(17)':
            sys.exit('数据读取异常,\'表8-系统管理软件或平台\' \'重要程度\'的内容有误。。。。。。')
        elif message == 'SystemExit(18)':
            sys.exit('数据读取异常,\'表9-业务应用系统或平台\' \'重要程度\'的内容有误。。。。。。')

    sys.exit('***已结束***')


# func:读取文件
def file_read():
    try:
        wbData = openpyxl.load_workbook('../assess-require/调查表.xlsx')
        return wbData
    except Exception as e:
        sys.exit(3)


# func:保存文件
def file_write():
    try:
        outFile = open('../dataCool/asset/allAsset.py', 'w', encoding='utf-8')
        # 调用:用pprint格式化数据加拼接,并写入文件中
        outFile.write('\nengine_Room_data=' + pprint.pformat(engine_Room_data)+'\nnetwork_Equipment_data=' + pprint.pformat(network_Equipment_data)+'\naqData=' + pprint.pformat(aqData)+'\nfwqData=' + pprint.pformat(fwqData)+'\nfwqData=' + pprint.pformat(fwqData)+'\nzdData=' + pprint.pformat(zdData)+'\nglrjData=' + pprint.pformat(glrjData)+'\napplication_System_data=' + pprint.pformat(application_System_data))
    except Exception as e:
        sys.exit(4)


# func:处理物理机房数据,不?存在数量
def engine_room_Function(wb):
    # 找到'表2-物理机房'
    try:
        assetSh = wb['表2-物理机房']
    except Exception as err:
        sys.exit(5)
    for row in range(2, assetSh.max_row + 1):
        # B列'机房名称'
        name = assetSh['B' + str(row)].value
        # D列'重要程度'
        importance = assetSh['D' + str(row)].value
        if importance == '关键' or importance == '重要':
            engine_Room_data.append(name)
        # or 过滤?空行数据
        elif importance == '一般' or name == importance:
            continue
        else:
            sys.exit(12)


# func:处理网络设备数据
def network_equipment_Function(wb):
    # 找到'表3-网络设备'
    try:
        assetSh = wb['表3-网络设备']
    except Exception as err:
        sys.exit(6)
    for row in range(2, assetSh.max_row + 1):
        # B列'设备名称'
        name = assetSh['B' + str(row)].value
        # G列'重要程度'
        importance = assetSh['G' + str(row)].value
        # I列'数量'
        amount = assetSh['I' + str(row)].value
        if importance == '关键' or importance == '重要':
            # 处理非数字类型字符的异常
            try:
                # 如果资产数量10台以内
                if int(amount) < 10:
                    for i in range(1, int(amount) + 1):
                        network_Equipment_data.append(name + '0' + str(i))
                # 如果资产数量超过10
                elif int(amount) > 10:
                    i = 0
                    if int(amount) % 5 != 0:
                        i = int(amount) // 5 + 1
                    for j in range(1, i + 1):
                        # 调用:追加'设备名称',至少抽?20%
                        if i < 10:
                            network_Equipment_data.append(name + '0' + str(i))
                        else:
                            network_Equipment_data.append(name + str(i))
            except Exception as e:
                # 调用:退出程序,并打印错误信息
                sys.exit(13)
        # or 过滤?空行数据
        elif importance == '一般' or name == importance:
            continue
        else:
            print(importance)
            sys.exit('数据读取异常,\'表3-网络设备\' \'重要程度\'的内容有误。。。。。。')


# func:处理安全设备数据
def safety_equipment_Function(wb):
    # 找到'表4-安全设备'
    try:
        assetSh = wb['表4-安全设备']
    except Exception as err:
        sys.exit(7)
    for row in range(2, assetSh.max_row + 1):
        # B列'设备名称'
        name = assetSh['B' + str(row)].value
        # G列'重要程度'
        importance = assetSh['G' + str(row)].value
        # I列'数量'
        amount = assetSh['I' + str(row)].value
        if importance == '关键' or importance == '重要':
            # 处理非数字类型字符的异常
            try:
                # 如果资产数量10台以内
                if int(amount) < 10:
                    for i in range(1, int(amount) + 1):
                        aqData.append(name + '0'+str(i))
                # 如果资产数量超过10
                elif int(amount) > 10:
                    i=0
                    if int(amount)%5 != 0:
                       i=int(amount)//5+1
                    for j in range(1,i+1):
                        # 调用:追加'设备名称',至少抽?20%
                        if i <10:
                            aqData.append(name + '0'+str(i))
                        else:
                            aqData.append(name + str(i))
            except Exception as e:
                # 调用:退出程序,并打印错误信息
                sys.exit(14)
        # or 过滤?空行数据
        elif importance == '一般' or name == importance:
            continue
        else:
            sys.exit(14)


# func:处理服务器或存储设备数据
def server_Function(wb):
    # 找到'表6-服务器或存储设备'
    try:
        assetSh = wb['表6-服务器或存储设备']
    except Exception as err:
        sys.exit(8)
    for row in range(2, assetSh.max_row + 1):
        # B列'设备名称'
        name = assetSh['B' + str(row)].value
        # E列'操作系统'
        if re.search(r'windows',assetSh['E' + str(row)].value,flags=re.I):
            system='windows'
        elif re.search(r'linux',assetSh['E' + str(row)].value,flags=re.I):
            system='linux'
        elif re.search(r'centos',assetSh['E' + str(row)].value,flags=re.I):
            system='linux'
        elif re.search(r'redhat',assetSh['E' + str(row)].value,flags=re.I):
            system='linux'
        elif re.search(r'麒麟',assetSh['E' + str(row)].value,flags=re.I):
            system='linux'
        elif re.search(r'ubuntu', assetSh['E' + str(row)].value, flags=re.I):
            system = 'linux'
        elif re.search(r'suse', assetSh['E' + str(row)].value, flags=re.I):
            system = 'linux'
        elif re.search(r'debain', assetSh['E' + str(row)].value, flags=re.I):
            system = 'linux'
        elif re.search(r'aix',assetSh['E' + str(row)].value,flags=re.I):
            system='aix'
        else:
            system = 'common-system'
        # H列'重要程度'
        importance = assetSh['H' + str(row)].value
        # I列'数量'
        amount = assetSh['I' + str(row)].value
        if importance == '关键' or importance == '重要':
            # 处理非数字类型字符的异常
            try:
                # 如果资产数量10台以内
                if int(amount) < 10:
                    for i in range(1, int(amount) + 1):
                        fwqData.setdefault(name + '0' + str(i),system)
                # 如果资产数量超过10
                elif int(amount) > 10:
                    i = 0
                    if int(amount) % 5 != 0:
                        i = int(amount) // 5 + 1
                    for j in range(1, i + 1):
                        # 调用:追加'设备名称',至少抽?20%
                        if i < 10:
                            fwqData.setdefault(name + '0' + str(i),system)
                        else:
                            fwqData.setdefault(name + str(i),system)
            except Exception as e:
                # 调用:退出程序,并打印错误信息
                sys.exit(15)
        # or 过滤?空行数据
        elif importance == '一般' or name == importance:
            continue
        else:
            sys.exit(15)


# func:处理终端或现场设备数据
def terminal_Function(wb):
    # 找到'表7-终端或现场设备'
    try:
        assetSh = wb['表7-终端或现场设备']
    except Exception as err:
        sys.exit(9)
    for row in range(2, assetSh.max_row + 1):
        # B列'设备名称'
        name = assetSh['B' + str(row)].value
        # F列'重要程度'
        importance = assetSh['F' + str(row)].value
        # G列'数量'
        amount = assetSh['G' + str(row)].value
        if importance == '关键' or importance == '重要':
            # 处理非数字类型字符的异常
            try:
                # 如果资产数量10台以内
                if int(amount) < 10:
                    for i in range(1, int(amount) + 1):
                        zdData.append(name + '0' + str(i))
                # 如果资产数量超过10
                elif int(amount) > 10:
                    i = 0
                    if int(amount) % 5 != 0:
                        i = int(amount) // 5 + 1
                    for j in range(1, i + 1):
                        # 调用:追加'设备名称',至少抽?20%
                        if i < 10:
                            zdData.append(name + '0' + str(j))
                        else:
                            zdData.append(name + str(j))
            except Exception as e:
                # 调用:退出程序,并打印错误信息
                sys.exit(16)
        # or 过滤?空行数据
        elif importance == '一般' or name == importance:
            continue
        else:
            sys.exit(16)


# func:处理系统管理软件或平台数据
def management_software_Function(wb):
    # 找到'表8-系统管理软件或平台'
    try:
        assetSh = wb['表8-系统管理软件或平台']
    except Exception as err:
        sys.exit(10)
    for row in range(2, assetSh.max_row + 1):
        # B列'机房名称'
        name = assetSh['B' + str(row)].value
        # 软件系统
        # 数据库
        if re.search(r'mysql',name,flags=re.I):
            system='mysql'
        elif re.search(r'sqlserver',name,flags=re.I):
            system = 'sqlserver'
        elif re.search(r'sql server',name,flags=re.I):
            system = 'sqlserver'
        elif re.search(r'oracle',name,flags=re.I):
            system = 'oracle'
        elif re.search(r'sqlite',name,flags=re.I):
            system = 'sqlite'
        elif re.search(r'postgresql',name,flags=re.I):
            system = 'postgresql'
        elif re.search(r'mariadb',name,flags=re.I):
            system = 'mariadb'
        elif re.search(r'mongodb',name,flags=re.I):
            system = 'mongodb'
        elif re.search(r'redis',name,flags=re.I):
            system = 'redis'
        # 中间件
        elif re.search(r'iis',name,flags=re.I):
            system = 'iis'
        elif re.search(r'tomcat',name,flags=re.I):
            system = 'tomcat'
        elif re.search(r'weblogic',name,flags=re.I):
            system = 'weblogic'
        elif re.search(r'jetty',name,flags=re.I):
            system = 'jetty'
        elif re.search(r'jboss',name,flags=re.I):
            system = 'jboss'
        elif re.search(r'webshphere',name,flags=re.I):
            system = 'websphere'
        elif re.search(r'mq',name,flags=re.I):
            system = 'mq'
        else:
            system='common-system'
        # F列'重要程度'
        importance = assetSh['F' + str(row)].value
        if importance == '关键' or importance == '重要':
            glrjData.setdefault(name,system)
        # or 过滤?空行数据
        elif importance == '一般' or name == importance:
            continue
        else:
            sys.exit(17)


# func:处理业务应用系统或平台数据
def application_system_Function(wb):
    # 找到'表9-业务应用系统或平台'
    try:
        assetSh = wb['表9-业务应用系统或平台']
    except Exception as err:
        sys.exit(11)
    for row in range(2, assetSh.max_row + 1):
        # B列'机房名称'
        name = assetSh['B' + str(row)].value
        # F列'重要程度'
        importance = assetSh['F' + str(row)].value
        if importance == '关键' or importance == '重要':
            application_System_data.append(name)
        # or 过滤?空行数据
        elif importance == '一般' or name == importance:
            continue
        else:
            sys.exit(18)


# 当前文件被调用的时候,if里的语句不执行
if __name__ == '__main__':
    # 执行主函数
    questionaire_main()

0.知识点zero
‘/’ 这个除取浮点,’//’ 这个除采取商。

1.知识点one
try:
except SystemExit as err:可以用来接 sys.exit()的中断,返回在 err = SystemExit(),所以格式化一下就可以拿到括号里的值来判断错误类型了,或者和我上面一样偷懒。

2.知识点two

	if __name__ == '__main__':
		    questionaire_main()

此文件如果被当做模块引用,则 if 作用域下的所有内容都不被使用。

3.数据有误的话,如下所示

在数据那一列我改写为了 ‘非数字’类型字符 ‘ss’
在这里插入图片描述报错如下:
在这里插入图片描述无错执行结果如下:
在这里插入图片描述数据文件结果如下:
在这里插入图片描述
小结:
最大行数遍历的时候会遇到空行,所以筛选时应过滤一下。plan-B不贴了,只是把 ‘重要程度’ 和 ‘是否抽选’ 作为筛选条件进行互换了。

2.赏金任务:替换数据(replace.py)的代码
# coding:utf-8

# 使用注意:除非你要替换的内容为唯一内容,不涉及基础代码,不然替换会导致原代码异常,如拼写异常等情况发生。
import sys
import os
import pprint
import time
from datetime import datetime

# 从sys.path下找到包的路径
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
from configuration.OS_func_Limited import input_limited
from configuration.common_configure import outPut


# func:主函数-替换操作(如将'../temp/test.py'中的'c'替换为'i')
def main():
    print('   \n\n替换须谨慎!   内容确保唯一!')
    flag = 0
    flagOut = 0
    timeOut = datetime.now()
    while flag == flagOut:
        if flag == 0:
            print('请输入文件路径:')
        if (datetime.now() - timeOut).seconds >= int(outPut['time_out']):
            timeOut = datetime.now()
            flag=0
            flagOut=0
        try:
        	#用 input_limited()将input()封装了一下
            pathFile,count_max = input_limited(flag, timeOut)
            replace(pathFile)
        except SystemExit as err:
            message = pprint.pformat(err)
            if message == 'SystemExit(3)':
                sys.exit('连续错误输入,已退出......')
            elif message == 'SystemExit(4)':
                if flag < int(count_max) - 1:
                    print('文件路径错误或权限不够!')
                    print('请输入文件路径:')
            elif message == 'SystemExit(5)':
                sys.exit('文件读取失败,已退出......')
            elif message == 'SystemExit(6)':
                sys.exit('文件写入失败,已退出......')
            flag += 1
        flagOut += 1
    sys.exit('***已结束***')


# func:替换函数
def replace(file):
    flag = 0
    flagOut = 0
    while flag == flagOut:
    	content = read_file(file)
        oldContent = input('请输入原始内容:')
        newContent = input('请输入新内容:')
        contentNew = content.replace(oldContent, newContent)
        flagOut += 1
        if contentNew == content:
            print('替换失败,输入内容有误!')
            flag = replace_judge(flag,flagOut)
        else:
            rewrite_file(file, contentNew)
            flag = replace_judge(flag, flagOut)


# func:替换函数-内容判断、输入超时和次数
def replace_judge(flag,flagOut):
    print('是否还需要替换? (是/否)')
    judge = '否'
    flagGo = 0
    timeOut = datetime.now()
    while judge == '否':
        if (datetime.now() - timeOut).seconds >= int(outPut['time_out']):
            timeOut = datetime.now()
            flagGo = 0
        judge ,count_max= input_limited(flagGo, timeOut)
        if judge == '是':
            flag=flagOut
            return flag
        elif judge == '否':
            judge = 'out'
            return flag
        else:
            judge = '否'
            flagGo += 1
            if flagGo < int(count_max):
                print('请输入 是 或 否!')


# func:读文件函数
def read_file(file):
    try:
        fileOpen = open(file, encoding='UTF-8')
    except Exception as e:
        sys.exit(4)
    try:
        read_all = fileOpen.read()
    except Exception as e:
        sys.exit(5)
    return read_all


# func:写文件函数
def rewrite_file(file, data):
    try:
        fileOpen = open(file, 'w', encoding='UTF-8')
        print('***写入成功***')
    except Exception as e:
        sys.exit(4)
    try:
        fileOpen.write(data)
    except Exception as e:
        sys.exit(6)

# 外部调用此文件则不执行if下的语句
if __name__ == '__main__':
    main()

0.知识点zero:
核心就用到了 open(),read(),write(),这里例子网上一大堆我就不赘述了。

1.知识点one:

	# 从sys.path下找到包的路径
	sys.path.append(os.path.dirname(os.path.dirname(__file__)))
	from configuration.OS_func_Limited import input_limited
	from configuration.common_configure import outPut

有价值的就这个——sys.path.append(os.path.dirname(os.path.dirname(file))),它这个貌似是解析二级路径的,然后你可以从当前程序的路径退到外层一级路径,在外层路径同级下的其他目录文件里找自己的包模块,至于二级以上深度的我还测试过,是不是再嵌套写==os.pathdirname()==这里mark一下。

2.知识点two
datatime模块,datatime.now()——返回当前时间, ().seconds——可以做运算,返回值取不大于原值的最大整数(即忽略了小数)

小结:
input_limited()可实现输入次数和连续时间的部分控制功能。

3.修仙任务:控制输入(OS_func_Limited.py和common_configure.py)的代码

请结合赏金任务replace.py的代码来看
OS_func_Limited.py:

# coding:utf-8

import sys
import re
import time
from datetime import datetime

# 导入配置文件
from common_configure import outPut


# func:input()限制函数
# 3:输入次数超过5次,连续时间为10分钟
def input_limited(counter, data):
    D_Value = (datetime.now() - data).seconds
    count_max=outPut['count_input']
    if int(D_Value) < int(outPut['time_out']) and counter < int(outPut['count_input']):
        value = input()
    else:
        sys.exit(3)
    return value,count_max

common_configure.py:

# coding:utf-8

# unit of time_out is second.
outPut={
    'count_input':'5',
    'time_out':'60',
}

小结:
没啥好说的,除了系统函数,都是一些逻辑判断的组合,咱们直接上图吧
~~~ ︿( ̄︶ ̄)︿ ~~~

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
小结:
之前代码里出现了一个bug,content = read_file(file)没有放进while 循环里,导致了无论你多少次的read()和write(),程序只记最后一次结束前的替换值,因为在文件未被关闭或缓冲区未刷新时,输入的字符串存储在缓冲区中未写入文件。

3.渡劫任务:自动补全

嗯,这个坑先放一放,不然主线要做不完了(理由)。我在度娘那里实在是没捞到什么干货,怎么搜,给的都是自动补全如何配置或者代码自动补全功能等,我也是服了,包括后面退而求其次搜索如何获取键盘按键对应的值,也是无脑寻章摘句,tk()暂时是用不上了,如果走到后面用到GUI可以试一试,但图形界面还要手写确实太累,只好退而再求其次搜索如何获取所有路径。。。。。。忘了补全什么了吧,我只是懒的打file-path,后来加循环判断是否还需要替换就是应对这个问题的(狡辩)。

文章结语

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值