python实现爬虫统计学校BBS男女比例之数据处理(三)

python实现爬虫统计学校BBS男女比例之数据处理(三),第1张

概述本文主要介绍了数据处理方面的内容,希望大家仔细阅读。一、数据分析得到了以下列字符串开头的文本数据,我们需要进行处理

本文主要介绍了数据处理方面的内容,希望大家仔细阅读。

一、数据分析

得到了以下列字符串开头的文本数据,我们需要进行处理

二、回滚

我们需要对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</em>(.*?)</li')  timeRe = re.compile(u'em>\u4e0a\u6b21\u6d3b\u52a8\u65f6\u95f4</em>(.*?)</li')  notexistRe = re.compile(u'(p>)\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,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,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,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,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,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,secretcount)  #没有活动时间,但是有性别  elif filename.startswith("errTime"):    newname = 'E:\pythonProject\ruisi\%s' % (filename)    readfile = open(newname,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,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,sys#全局变量SUM = 0BOY = 0GIRL = 0SECRET = 0UNKOWN = 0class StafileList(threading.Thread):  #文本名称列表  fileList = []  def __init__(self,SECRET    if mutex.acquire(1):      self.staManyfiles(self.fileList)      mutex.release()  #处理输入的files列表,统计男女人数  #注意这儿数据同步问题  def staCorrectfiles(self,SECRET)  def staManyfiles(self,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,total is %s; %s boys; %s girls;" \        #    " %s secret;" %(self.name,SECRET)      #没有活动时间,但是有性别      elif name.startswith("errTime"):        newname = 'E:\pythonProject\ruisi\%s' % (name)        readfile = open(newname,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,'rU')):          pass        count += 1        UNKOWN += count        SUM += count        # print "thread %s,total is %s; %s unkownsex" %(self.name,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,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,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

以上就是本文的全部内容,希望对大家的学习有所帮助。

总结

以上是内存溢出为你收集整理的python实现爬虫统计学校BBS男女比例之数据处理(三)全部内容,希望文章能够帮你解决python实现爬虫统计学校BBS男女比例之数据处理(三)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1203417.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-04
下一篇 2022-06-04

发表评论

登录后才能评论

评论列表(0条)

保存