Python实战篇——利用Python下载并解压压缩文件

  • 前言
  • 应用背景
  • 工具包准备
  • 压缩文件下载
  • 压缩文件解压
  • 拓展
  • 总结


前言

挺久没整理自己的学习笔记了,今天就理一下如何通过Python下载并自动解压在线打包好的压缩包吧~

应用背景

公司的产品日志(log)是每天自动在服务器上打包好的,在当天能下载前一天的日志,在日常工作中的数据分析经常需要通过处理日志文件来产出结果。而在需要同时处理多个产品日志,且几乎每天都要到浏览器粘贴个链接来下载日志,还得到文件夹中手动解压……的情况下,让我越来越忍受不了这种又费时间又费精力还低效的重复性操作,于是本文的内容就这么产生了。。m(o_ _)m

工具包准备

import requests
from datetime import timedelta,date,datetime
import time
import os
import zipfile

压缩文件下载

压缩包下载先是通过requests.get()来获取,再通过os.write()来写入到本地文件夹中。

yday = (date.today()+timedelta(days=-1)).strftime('%Y%m%d') # 获取昨日日期
r =  requests.get('http://XXXXXXXX/XX_%s.zip'%yday) # 获取以日期命名的压缩包信息
with open(r'D:\数据源\XX_%s.zip'%yday,'wb') as code: # 将压缩包内容写入到 "D:\数据源\" 下,并按日期命名
	code.write(r.content)
print('昨日XX日志下载完成。')

这样日志就下载下来了~

压缩文件解压

接下来就到关键一步了,压缩包解压要用的是zipfile这个包。

zip_file = zipfile.ZipFile(r'D:\数据源\XX_%s.zip'%yday)
zip_list = zip_file.namelist() # 压缩文件清单,可以直接看到压缩包内的各个文件的明细
for f in zip_list: # 遍历这些文件,逐个解压出来,
    zip_file.extract(f,r'D:\数据源')
zip_file.close() # 不能少!
print('昨日日志解压完成,请在文件夹中验收!') # 当然我是不需要查收的(*/ω\*)

这里的解压操作实际就相当于鼠标右键“解压到当前文件夹”的效果。

完成解压后运行.close()是个比较好的习惯,否则可能会导致包括但不限于:

  1. 文件会一直被占用着,可能无法重新打开;
  2. 在进程结束之前文件都删不掉;
  3. 文件内容不能即时 flush 到磁盘直到进程结束;

到此,整个流程在无需打开浏览器和文件夹的情况下便自动完成了。
为了方便日常运行代码(也为了好看。。),这里把上面的两个流程包装成一个函数,下载解压一条龙服务~~

#下载昨日日志
def download_XXlog():
	yday = (date.today()+timedelta(days=-1)).strftime('%Y%m%d') # 获取昨日日期
	r =  requests.get('http://XXXXXXXX/XX_%s.zip'%yday) # 获取以日期命名的压缩包信息
	with open(r'D:\数据源\XX_%s.zip'%yday,'wb') as code: # 将压缩包内容写入到 "D:\数据源\" 下,并按日期命名
	code.write(r.content)
	print('昨日XX日志下载完成。') 
    zip_file = zipfile.ZipFile(r'D:\数据源\XX_%s.zip'%yday)
	zip_list = zip_file.namelist() # 压缩文件清单,可以直接看到压缩包内的各个文件的明细
	for f in zip_list: # 遍历这些文件,逐个解压出来,
	    zip_file.extract(f,r'D:\数据源')
	zip_file.close() # 不能少!
	print('昨日日志解压完成,请在文件夹中验收!') 
download_XXlog()

拓展

作为拓展,这里再加一个可以根据实际情况输入(input)起始和终止日期,来下载一个特定时间段日志的函数,这里就涉及了datetime和time这两个工具包了。

#下载多日日志
def daterange(start_date,end_date): # 根据input构建时间序列,存放于 date_all 列表中
    start_date = datetime.strptime(start_date,"%Y%m%d")
    end_date = datetime.strptime(end_date,"%Y%m%d")
    date_all = []
    while start_date<=end_date:
        date_all.append(int(start_date.strftime('%Y%m%d')))
        start_date+=timedelta(days=1)
    return date_all

def start_function(): # 获取起始、终止日期(input),调用上述函数
    start_date = input('请输入起始日期(如:20201101):')
    end_date = input('请输入终止日期(如:20201111):')
    return daterange(start_date,end_date)

def download_log_plus(): 
    lst = start_function() # 调用函数构建时间序列
    lst_exists = [] # 用于下面判断
    for i in lst: # 调用日期,判断本地文件中是否已经下载了该日期的日志,避免重复下载。
        if os.path.exists(r'D:\数据源\XX_%s.zip'%i):
            lst_exists.append(i)
            print('%s日志已存在'%i)
        else:
            r =  requests.get('http://XXXXXXXX/XX_%s.zip'%i)
            if str(r) == '<Response [404]>':
                lst_exists.append(i)
                print('%s日志暂未打包,请重新选择日志下载日期区间或核对日志下载链接是否有误。'%i)
            else:
                with open(r'D:\数据源\XX_%s.zip'%i,'wb') as code:
                    code.write(r.content)
                print('%s日志下载完成'%i)
                zip_file = zipfile.ZipFile(r'D:\数据源\XX_%s.zip'%i)
                zip_list = zip_file.namelist()
                for f in zip_list:
                    zip_file.extract(f,r'D:\数据源')
                zip_file.close()
                print('%s日志解压完成。'%i)
    print('日志下载并解压完成,共下载并解压了%s天的日志,请在文件夹中验收!'%(len(lst)-len(lst_exists)))
download_log_plus()

总结

  1. 本代码的应用场景可能有限,应该只适用于文本文件压缩包的下载,其他场景我还没接触过,欢迎各位大神提点;
  2. 压缩包的下载分两个步骤:①读取压缩包信息;②保存到本地;网络传输速度慢也可能影响代码运行的速度;
  3. 文件解压后记得运行.close()函数,原因上面已经提到了;
  4. datetime确实是个很好用的包~~~