在上一篇博文中,我讲述了利用Python的selenium模块抓取动态数据的方法点击打开链接,那么这些抓到的数据如何处理呢?可以写入到excel表格中制成表格,进而画成统计图表直观显示出来。例如按照时间轴统计网站的在线人数,查看哪个时间段人最多,哪个时间段人最少,从而网站维护人员可以按照合适的时间分配资源,用户则可以选择合适的时间访问。
要做到以上所述的数据处理,涉及到两个问题:
一是如何把数据写入已存在的表格中,并且多次写入不会影响先前的数据;
二是如何每隔一段时间运行抓取动态数据的函数和写入到excel表格的函数,Linux下用crontab很好解决,但windows则比较麻烦。
第一个问题,用xlwt模块不能解决,因为xlwt每次都会把excel文件中已存在的数据清除再写入,用xlutils模块可以将数据写入到已存在的excel中而且不影响sheet中原有的数据。你需要安装xlutils模块,联网状态下cmd直接输入pip install xlutils,系统会找到Python的安装目录直接下载解压并安装这个模块。等到终端提示完成后可以看看,在C:\Python27\Lib\site-packages目录下有没有selenium模块,这个目录取决于你安装Python的路径。如果有xlutils和xlutils-1.7.1-py2.7.egg-info这两个文件夹,代表模块可以在Python程序中被加载了。另外还要安装xlrd模块,由这个模块的子模块open_workbook对excel文件执行打开操作,返回文件对象让xlutils的copy子模块重写数据进去,安装xlrd的方法同上。
第二个问题,其实没那么复杂,一开始还考虑是不是要用到os.system(command)或者windows计划任务什么的?但是往简单的角度想,直接写一个循环:循环里面执行抓取动态数据的函数和写入到excel表格的函数,然后time.sleep(x)让进程暂停x秒,接着跳入下一次循环即可。至于什么时候终止循环,引入计数变量即可。
思路已经有了,直接上代码。
# -*- coding: utf-8 -*- from selenium import webdriver from selenium.common.exceptions import NoSuchElementException import time import re from xlrd import open_workbook from xlutils.copy import copy #这个函数打开指定的url,获取动态数据,返回一个列表 def find_sec(secid): #正则模块 pa=re.compile(r'\w+') browser = webdriver.Firefox() # Get local session of firefox browser.get("http://bbs.byr.cn/#!section/%s "%secid) # Load page time.sleep(1) # Let the page load result=[] try: #获得版面名称和在线人数,形成列表 board=browser.find_elements_by_class_name('title_1') ol_num=browser.find_elements_by_class_name('title_4') max_bindex=len(board) max_oindex=len(ol_num) assert max_bindex==max_oindex,'index not equivalent!' #版面名称有中英文,因此用正则过滤只剩英文的 for i in range(1,max_oindex): board_en=pa.findall(board[i].text) result.append([str(board_en[-1]),int(ol_num[i].text)]) browser.close() return result except NoSuchElementException: assert 0, "can't find element" #写入excel,xlutils可以写入到已存在的excel中,xlwt只能每次都重写 def write_xls(lis,times,filename): rb=open_workbook(filename) wb=copy(rb) ws=wb.get_sheet(0) for i in range(0,len(lis)): #写入excel中,第0列是板块名称,第times列(times=1,2,3...)是在线人数 ws.write(i,0,lis[i][0]) ws.write(i,times,lis[i][1]) wb.save(filename) cnt_times=1 while(1): #获得分区2下面所以板块在线人数,在终端打印并写入excel中,如果要获得分区5的数据就用find_sec('5') result_lis2=find_sec('2') print result_lis2 write_xls(result_lis2,cnt_times,filename='count2.xls') cnt_times+=1 #每隔1800秒,即半个小时统计一次 time.sleep(1800) #当统计了20次后跳出循环,终止程序 if(cnt_times>20): break
打开浏览器并且打印抓取到的数据列表->把数据写入到excel中->计数变量加1->关闭session和关闭浏览器。
每隔半小时执行一次上述的操作流,这里程序设计成当计数变量到20的时候跳出循环,终止程序运行。
在终端打印的结果如下(前4次循环的结果):
版块名称和在线人数写入到excel表格里的效果如下:
从中选择某几个版块,以时间为横坐标,在线人数为纵坐标,插入折线图,画出统计图表:
这里时间跨度不大,在线人数变化不多,因此折线图的效果不是很明显,如果让程序运行一天,统计24小时内各个时间段的在线人数情况,变化就比较明显了。按照这种方法实现统计在线人数,简单直接,并且系统开销很小。唯一要保证的是,你的浏览器能正确访问指定的url,程序不会异常(好像也不好保证的说= = )。