本文主要介绍了数据处理方面的内容,希望大家仔细阅读。
一、数据分析
得到了以下列字符串开头的文本数据,我们需要进行处理
二、回滚
我们需要对httperror的数据进行再处理
因为代码的原因,具体可见本系列文章(二),会导致文本里面同一个id连续出现几次httperror记录:
//httperror265001_266001.txt265002 httperror265002 httperror265002 httperror265002 httperror265003 httperror265003 httperror265003 httperror265003 httperror
所以我们在代码里要考虑这种情形,不能每一行的id都进行处理,是判断是否重复的id。
java里面有缓存方法可以避免频繁读取硬盘上的文件,python其实也有,可以见这篇文章。
def main(): reload(sys) sys.setdefaultencoding('utf-8') global sexre,timere,notexistre,url1,url2,file1,file2,file3,file4,startnum,endnum,file5 sexre = re.compile(u'em>\u6027\u522b(.*?)\u4e0a\u6b21\u6d3b\u52a8\u65f6\u95f4(.*?))\u62b1\u6b49\uff0c\u60a8\u6307\u5b9a\u7684\u7528\u6237\u7a7a\u95f4\u4e0d\u5b58\u5728<') url1 = 'http://rs.xidian.edu.cn/home.php?mod=space&uid=%s' url2 = 'http://rs.xidian.edu.cn/home.php?mod=space&uid=%s&do=profile' file1 = 'ruisi\\correct_re.txt' file2 = 'ruisi\\errtime_re.txt' file3 = 'ruisi\\notexist_re.txt' file4 = 'ruisi\\unkownsex_re.txt' file5 = 'ruisi\\httperror_re.txt' #遍历文件夹里面以httperror开头的文本 for filename in os.listdir(r'e:\pythonproject\ruisi'): if filename.startswith('httperror'): count = 0 newname = 'e:\\pythonproject\\ruisi\\%s' % (filename) readfile = open(newname,'r') oldline = '0' for line in readfile: #newline 用来比较是否是重复的id newline = line if (newline != oldline): nu = newline.split()[0] oldline = newline count += 1 searchweb((int(nu),)) print %s deal %s lines %(filename, count)
本代码为了简便,没有再把httperror的那些id分类,直接存储为下面这5个文件里
file1 = 'ruisi\\correct_re.txt' file2 = 'ruisi\\errtime_re.txt' file3 = 'ruisi\\notexist_re.txt' file4 = 'ruisi\\unkownsex_re.txt' file5 = 'ruisi\\httperror_re.txt'
可以看下输出log记录,总共处理了多少个httperror的数据。
d:\program files\python27\python.exe e:/pythonproject/webcrawler/reload.pyhttperror132001-133001.txt deal 21 lineshttperror2001-3001.txt deal 4 lineshttperror251001-252001.txt deal 5 lineshttperror254001-255001.txt deal 1 lines
三、单线程统计unkownsex 数据
代码简单,我们利用单线程统计一下unkownsex(由于权限原因无法获取、或者该用户没有填写)的用户。另外,经过我们检查,没有性别的用户也是没有活动时间的。
数据格式如下:
253042 unkownsex253087 unkownsex253102 unkownsex253118 unkownsex253125 unkownsex253136 unkownsex253161 unkownseximport os,timesumcount = 0starttime = time.clock()for filename in os.listdir(r'e:\pythonproject\ruisi'): if filename.startswith('unkownsex'): count = 0 newname = 'e:\\pythonproject\\ruisi\\%s' % (filename) readfile = open(newname,'r') for line in open(newname): count += 1 sumcount +=1 print %s deal %s lines %(filename, count)print '%s unkowns sex' %(sumcount)endtime = time.clock()print cost time + str(endtime - starttime) + s
处理速度很快,输出如下:
unkownsex1-1001.txt deal 204 linesunkownsex100001-101001.txt deal 50 linesunkownsex10001-11001.txt deal 206 lines#...省略中间输出信息unkownsex99001-100001.txt deal 56 linesunkownsex_re.txt deal 1085 lines14223 unkowns sexcost time 0.0813142301261 s
四、单线程统计 correct 数据
数据格式如下:
31024 男 2014-11-11 13:2031283 男 2013-3-25 19:4131340 保密 2015-2-2 15:1731427 保密 2014-8-10 09:1731475 保密 2013-7-2 08:5931554 保密 2014-10-17 17:0231621 男 2015-5-16 19:2731872 保密 2015-1-11 16:4931915 保密 2014-5-4 11:0131997 保密 2015-5-16 20:14
代码如下,实现思路就是一行一行读取,利用line.split()获取性别信息。sumcount 是统计一个多少人,boycount 、girlcount 、secretcount 分别统计男、女、保密的人数。我们还是利用unicode进行正则匹配。
import os,sys,timereload(sys)sys.setdefaultencoding('utf-8')starttime = time.clock()sumcount = 0boycount = 0girlcount = 0secretcount = 0for filename in os.listdir(r'e:\pythonproject\ruisi'): if filename.startswith('correct'): newname = 'e:\\pythonproject\\ruisi\\%s' % (filename) readfile = open(newname,'r') for line in readfile: sexinfo = line.split()[1] sumcount +=1 if sexinfo == u'\u7537' : boycount += 1 elif sexinfo == u'\u5973': girlcount +=1 elif sexinfo == u'\u4fdd\u5bc6': secretcount +=1 print until %s, sum is %s boys; %s girls; %s secret; %(filename, boycount,girlcount,secretcount)print total is %s; %s boys; %s girls; %s secret; %(sumcount, boycount,girlcount,secretcount)endtime = time.clock()print cost time + str(endtime - starttime) + s
注意,我们输出的是截止某个文件的统计信息,而不是单个文件的统计情况。输出结果如下:
until correct1-1001.txt, sum is 110 boys; 7 girls; 414 secret;until correct100001-101001.txt, sum is 125 boys; 13 girls; 542 secret;#...省略until correct99001-100001.txt, sum is 11070 boys; 3113 girls; 26636 secret;until correct_re.txt, sum is 13937 boys; 4007 girls; 28941 secret;total is 46885; 13937 boys; 4007 girls; 28941 secret;cost time 3.60047888495 s
五、多线程统计数据
为了更快统计,我们可以利用多线程。
作为对比,我们试下单线程需要的时间。
# encoding: utf-8import threadingimport time,os,sys#全局变量sum = 0boy = 0girl = 0secret = 0num =0#本来继承自threading.thread,覆盖run()方法,用start()启动线程#这和java里面很像class stafilelist(threading.thread): #文本名称列表 filelist = [] def __init__(self, filelist): threading.thread.__init__(self) self.filelist = filelist def run(self): global sum, boy, girl, secret #可以加上个耗时时间,这样多线程更加明显,而不是顺序的thread-1,2,3 #time.sleep(1) #acquire获取锁 if mutex.acquire(1): self.stafiles(self.filelist) #release释放锁 mutex.release() #处理输入的files列表,统计男女人数 #注意这儿数据同步问题,global使用全局变量 def stafiles(self, files): global sum, boy, girl, secret for name in files: newname = 'e:\\pythonproject\\ruisi\\%s' % (name) readfile = open(newname,'r') for line in readfile: sexinfo = line.split()[1] sum +=1 if sexinfo == u'\u7537' : boy += 1 elif sexinfo == u'\u5973': girl +=1 elif sexinfo == u'\u4fdd\u5bc6': secret +=1 # print thread %s, until %s, total is %s; %s boys; %s girls; \ # %s secret; %(self.name, name, sum, boy,girl,secret)def test(): #files保存多个文件,可以设定一个线程处理多少个文件 files = [] #用来保存所有的线程,方便最后主线程等待所以子线程结束 stathreads = [] i = 0 for filename in os.listdir(r'e:\pythonproject\ruisi'): #没获取10个文本,就创建一个线程 if filename.startswith('correct'): files.append(filename) i+=1 #一个线程处理20个文件 if i == 20 : stathreads.append(stafilelist(files)) files = [] i = 0 #最后剩余的files,很可能长度不足10个 if files: stathreads.append(stafilelist(files)) for t in stathreads: t.start() # 主线程中等待所有子线程退出,如果不加这个,速度更快些? for t in stathreads: t.join()if __name__ == '__main__': reload(sys) sys.setdefaultencoding('utf-8') starttime = time.clock() mutex = threading.lock() test() print multi thread, total is %s; %s boys; %s girls; %s secret; %(sum, boy,girl,secret) endtime = time.clock() print cost time + str(endtime - starttime) + s
输出
multi thread, total is 46885; 13937 boys; 4007 girls; 28941 secret;cost time 0.132137192794 s
我们发现时间和单线程差不多。因为这儿涉及到线程同步问题,获取锁和释放锁都是需要时间开销的,线程间切换保存中断和恢复中断也都是需要时间开销的。
六、较多数据的单线程和多线程对比
我们可以对correct、errtime 、unkownsex的文本都进行处理。
单线程代码
# coding=utf-8import os,sys,timereload(sys)sys.setdefaultencoding('utf-8')starttime = time.clock()sumcount = 0boycount = 0girlcount = 0secretcount = 0unkowncount = 0for filename in os.listdir(r'e:\pythonproject\ruisi'): # 有性别、活动时间 if filename.startswith('correct') : newname = 'e:\\pythonproject\\ruisi\\%s' % (filename) readfile = open(newname,'r') for line in readfile: sexinfo =line.split()[1] sumcount +=1 if sexinfo == u'\u7537' : boycount += 1 elif sexinfo == u'\u5973': girlcount +=1 elif sexinfo == u'\u4fdd\u5bc6': secretcount +=1 # print until %s, sum is %s boys; %s girls; %s secret; %(filename, boycount,girlcount,secretcount) #没有活动时间,但是有性别 elif filename.startswith(errtime): newname = 'e:\\pythonproject\\ruisi\\%s' % (filename) readfile = open(newname,'r') for line in readfile: sexinfo =line.split()[1] sumcount +=1 if sexinfo == u'\u7537' : boycount += 1 elif sexinfo == u'\u5973': girlcount +=1 elif sexinfo == u'\u4fdd\u5bc6': secretcount +=1 # print until %s, sum is %s boys; %s girls; %s secret; %(filename, boycount,girlcount,secretcount) #没有性别,也没有时间,直接统计行数 elif filename.startswith(unkownsex): newname = 'e:\\pythonproject\\ruisi\\%s' % (filename) # count = len(open(newname,'ru').readlines()) #对于大文件用循环方法,count 初始值为 -1 是为了应对空行的情况,最后+1得到0行 count = -1 for count, line in enumerate(open(newname, 'ru')): pass count += 1 unkowncount += count sumcount += count # print until %s, sum is %s unkownsex %(filename, unkowncount)print single thread, total is %s; %s boys; %s girls; %s secret; %s unkownsex; %(sumcount, boycount,girlcount,secretcount,unkowncount)endtime = time.clock()print cost time + str(endtime - starttime) + s
输出为
single thread, total is 61111; 13937 boys; 4009 girls; 28942 secret; 14223 unkownsex;
cost time 1.37444645628 s
多线程代码
__author__ = 'admin'# encoding: utf-8#多线程处理程序import threadingimport time,os,sys#全局变量sum = 0boy = 0girl = 0secret = 0unkown = 0class stafilelist(threading.thread): #文本名称列表 filelist = [] def __init__(self, filelist): threading.thread.__init__(self) self.filelist = filelist def run(self): global sum, boy, girl, secret if mutex.acquire(1): self.stamanyfiles(self.filelist) mutex.release() #处理输入的files列表,统计男女人数 #注意这儿数据同步问题 def stacorrectfiles(self, files): global sum, boy, girl, secret for name in files: newname = 'e:\\pythonproject\\ruisi\\%s' % (name) readfile = open(newname,'r') for line in readfile: sexinfo = line.split()[1] sum +=1 if sexinfo == u'\u7537' : boy += 1 elif sexinfo == u'\u5973': girl +=1 elif sexinfo == u'\u4fdd\u5bc6': secret +=1 # print thread %s, until %s, total is %s; %s boys; %s girls; \ # %s secret; %(self.name, name, sum, boy,girl,secret) def stamanyfiles(self, files): global sum, boy, girl, secret,unkown for name in files: if name.startswith('correct') : newname = 'e:\\pythonproject\\ruisi\\%s' % (name) readfile = open(newname,'r') for line in readfile: sexinfo = line.split()[1] sum +=1 if sexinfo == u'\u7537' : boy += 1 elif sexinfo == u'\u5973': girl +=1 elif sexinfo == u'\u4fdd\u5bc6': secret +=1 # print thread %s, until %s, total is %s; %s boys; %s girls; \ # %s secret; %(self.name, name, sum, boy,girl,secret) #没有活动时间,但是有性别 elif name.startswith(errtime): newname = 'e:\\pythonproject\\ruisi\\%s' % (name) readfile = open(newname,'r') for line in readfile: sexinfo = line.split()[1] sum +=1 if sexinfo == u'\u7537' : boy += 1 elif sexinfo == u'\u5973': girl +=1 elif sexinfo == u'\u4fdd\u5bc6': secret +=1 # print thread %s, until %s, total is %s; %s boys; %s girls; \ # %s secret; %(self.name, name, sum, boy,girl,secret) #没有性别,也没有时间,直接统计行数 elif name.startswith(unkownsex): newname = 'e:\\pythonproject\\ruisi\\%s' % (name) # count = len(open(newname,'ru').readlines()) #对于大文件用循环方法,count 初始值为 -1 是为了应对空行的情况,最后+1得到0行 count = -1 for count, line in enumerate(open(newname, 'ru')): pass count += 1 unkown += count sum += count # print thread %s, until %s, total is %s; %s unkownsex %(self.name, name, sum, unkown)def test(): files = [] #用来保存所有的线程,方便最后主线程等待所以子线程结束 stathreads = [] i = 0 for filename in os.listdir(r'e:\pythonproject\ruisi'): #没获取10个文本,就创建一个线程 if filename.startswith(correct) or filename.startswith(errtime) or filename.startswith(unkownsex): files.append(filename) i+=1 if i == 20 : stathreads.append(stafilelist(files)) files = [] i = 0 #最后剩余的files,很可能长度不足10个 if files: stathreads.append(stafilelist(files)) for t in stathreads: t.start() # 主线程中等待所有子线程退出 for t in stathreads: t.join()if __name__ == '__main__': reload(sys) sys.setdefaultencoding('utf-8') starttime = time.clock() mutex = threading.lock() test() print multi thread, total is %s; %s boys; %s girls; %s secret; %s unkownsex %(sum, boy,girl,secret,unkown) endtime = time.clock() print cost time + str(endtime - starttime) + s endtime = time.clock() print cost time + str(endtime - starttime) + s
输出为
multi thread, total is 61111; 13937 boys; 4009 girls; 28942 secret;
cost time 1.23049112201 s
可以看出多线程还是优于单线程的,由于使用的同步,数据统计是一直的。
注意python在类内部经常需要加上self,这点和java区别很大。
def __init__(self, filelist): threading.thread.__init__(self) self.filelist = filelist def run(self): global sum, boy, girl, secret if mutex.acquire(1): #调用类内部方法需要加self self.stafiles(self.filelist) mutex.release()
total is 61111; 13937 boys; 4009 girls; 28942 secret; 14223 unkownsex;
cost time 1.25413238673 s
以上就是本文的全部内容,希望对大家的学习有所帮助。