Python自动化脚本【2】从sql文件中随机抽取条目

这个小脚本旨在用于前述的查询系统自动化测试而写的数据预处理程序。

前面的开发笔记中提到,查询系统中,填入的表单为IP地址的前三段。故需要从sql文件中匹配恰当的IP字段+抽取并保存生成新的文件,每次抽取100条(参数可改),保存的文件名为cnnic+处理完成的时间点,其中时间点精确到秒。

代码地址 itemselect,使用Python2.7开发。

本来其实从数据库中抽数据,直接连接数据库然后select…from..就行了。然而搜索了半天发现Python链接Oracle数据库的操作极其麻烦,还得装Oracle客户端,数据库本身用的又是PL/SQL,遂作罢。链接MySQL倒是很简单,而客观环境又不允许。于是想到从PL/SQL中把数据库导出为sql文件然后再进行抽取,反正数据库也不是很大,每个数据库也就一两百万条,均小于700M。

首先观察一下sql文件的特点。

prompt PL/SQL Developer import file
prompt Created on 2017年6月14日 by ****
set feedback off
set define off
prompt Disabling triggers for *******...
alter table ******* disable all triggers;
prompt Deleting *******...
delete from *******;
commit;
prompt Loading *******...
insert into ******* (IP, PROVINCE, CITY)
values ('1.3.111.1', '广东', null);
insert into ******* (IP, PROVINCE, CITY)
values ('1.3.112.1', '广东', null);
insert into ******* (IP, PROVINCE, CITY)
values ('1.3.113.1', '广东', null);
insert into ******* (IP, PROVINCE, CITY)
values ('1.3.114.1', '广东', null);
insert into ******* (IP, PROVINCE, CITY)
values ('1.3.115.1', '广东', null);

上面的这段即为某数据库导出的sql文件前20行,可以看出数据信息主要以

insert into ******* (IP, PROVINCE, CITY)
values ('1.3.115.1', '广东', null);

这类语句存储,星号为数据库名,括号内为类别名称,第二行则为每个类别对应的值。

既然需要抽取IP地址的前三段,则使用“\d{1,3}.\d{1,3}.\d{1,3}”这一正则表达式即可提取有效字段。

接下来详解每段的操作:

1.引入库并读取sql文件:

import re
import numpy as np
import pandas as pd
import time

path = 'G:\---\ipinfo\data\ipinfo-cnnic.sql'
unipath = unicode(path,"utf8")
inputfile=open(unipath)

re正则表达式库,numpy,pandas数据分析利器,time时间库。

路径使用绝对路径,由于路径中包含有中文字符(已马赛克)且Python2对中文支持不好,加了一条编码命令,随后再打开文件。

后面用了个try,finally结构,理了一下逻辑(虽然好像也没什么暖用),try块中主要进行随机抽取并且组合新列表的操作,finally块中进行时间显示,列表转换以及文件保存操作。

2.抽取:

n=0
ipinfo=inputfile.readlines()
pat=re.compile(r'\d{1,3}\.\d{1,3}\.\d{1,3}')    
ip_list=[]
timea=time.time()
for a in ipinfo:
    t=int(time.time())
    i1=np.random.randint(500,1000)
    t=i1+t
    i2=np.random.randint(0,i1)
    for ip in pat.findall(a):
        if (type(ip) != type(None)) and (n < 100) and (t%i1 == i2):
            ip_list.append(ip)
            n+=1          
timeb=time.time()

随机抽取的算法实现原理为取随机数i1,i2,时间戳t,并由三者之间的算数关系确定抽取操作的进行与否。时间戳t为一较大的整数,随着程序运行不断变化;i1为人为限制在500~1000之间的一随机整数,取值后变量t为时间戳加上这个随机整数;i2为小于i1大于0的另一随机整数。t,i1,i2均为随机数,对于百万大小的数据库而言,t除以i1所得值恰好为i2的概率较小,从而保证了隔行取值的随机性。

然而本算法难以保证覆盖得了所有的条目,亦难以保证不会出现溢出。需要使用数学方法以确认覆盖行数。

3.表格转换以及文件保存:

print 'Process is finished!\nAnd the total time is ' + str(round((timeb-timea),2)) +'s'
inputfile.close()
iplist=pd.DataFrame(ip_list,columns=['ip'])
timeloc=time.strftime("%Y-%m-%d %H.%M.%S", time.localtime())
name = 'cnnic_'+timeloc+'.csv'
iplist.to_csv(name)

这段就较为简单了。

首先输出整个抽取的运行时间,单位为s,保留两位小数。某次实验中,抽取10个条目时,总耗时38.25s,抽取100个时,总耗时23.83s。两者差距较大,具体原因有待进一步分析。

接下来将上面组合的列表ip_list转换为pandas中的dataframe格式,并以“年-月-日 时.分.秒”的格式将时间记录为字符串,由于文件名中不可出现冒号,故使用点号代替。

最后将数据库名与时间拼接为文件名,将dataframe输出为csv文件。

总结:

  1. 使用Python进行文件处理的脚本编写,需要较为熟悉time、sys等系统库,需要对文件读取与写出操作熟悉。
  2. 数学的重要性,不仅体现在算法的优化上。如本文中对大量数据进行随机抽取操作,既需要尽量保证所抽取的样本覆盖了全部数据,也需要保证遍历过程中不发生溢出错误。
  3. 也是最近才深有体会的,不管是否是计算机科班出身,写代码这种事,如果想要熟练还得天天写,计算机语言也是一门语言,许久不用,自然也会遗忘荒废。学一门语言也需要深到一定程度方可换一门继续学习,过程中也得有意识地进行区分,不然也会如一些日语专业学生讲不好英语一般,遗憾万分。

猜你喜欢

转载自blog.csdn.net/u013023297/article/details/74202925