2021-06-13

Python办公自动化之文件自动化处理&邮件批量处理学习笔记


一.文件自动化处理

读写文件:

1. os.path.join()函数来创建文件名称字符串


2. os.getcwd()函数获取当前工作目录,并可以用os.chdir()改变当前工作路径


3.os.path.abspath(path):将相对路径转换为绝对路径,并返回参数的绝对路径的字符串

os.path.isabs(path):判断是否是绝对路径,是返回True,不是则返回False

4.os.path.relpath(path,start):返回从start路径到path的相对路径的字符串

os.path.dirname(path):返回当前路径的目录名称

os.path.basename(path):返回当前路径的文件名称

5. os.path.split():返回一个元组,里面包括路径的目录名称和基本名称

os.path.sep:路径分隔符

split():根据给定字符分割字符串,返回结果为列表

6. os.makedirs():创建所有必要的中间文件夹

os.path.getsize(path):返回path中文件的字节数

os.listdir():返回当前文件夹下文件名字字符串的列表

7. 文件读写过程

读过程:

open(path)函数:返回一个File对象

read()函数:读取文件内容

readlines()函数:按行读取文件中的内容,返回字符串列表

写过程:

open(‘path’,’w’):写模式打开一个文件

write():写入指定字符串

close():关闭已打开文件


实战模拟:

 一、生成随机的测验试卷文件假如你是一位地理老师,班上有35 名学生, 你希望进行美国各州首府的一个 小测验。不妙的是,班里有几个坏蛋, 你无法确信学生不会作弊。你希望随机调整 问题的次序, 这样每份试卷都是独一无二的, 这让任何人都不能从其他人那里抄袭答案。当然,手工完成这件事又费时又无聊。 好在, 你懂一些 Python。

下面是程序所做的事:

• 创建 35 份不同的测验试卷。

• 为每份试卷创建 50 个多重选择题,次序随机。

• 为每个问题提供一个正确答案和 3 个随机的错误答案,次序随机。

• 将测验试卷写到 35 个文本文件中。

• 将答案写到 35 个文本文件中。

这意味着代码需要做下面的事:

• 将州和它们的首府保存在一个字典中。

• 针对测验文本文件和答案文本文件,调用 open()、 write()和 close()。

• 利用 random.shuffle()随机调整问题和多重选项的次序。

写程序前准备:

1.准备一个字典存放美国各州以及对应首府

中文版:

```

Capitals={'阿拉巴马州':'蒙哥马利','阿拉斯加州':'朱诺','亚利桑那州':'凤凰城','阿肯色州':'小石城',          '加利福尼亚州':'萨克拉门托','科罗拉多州':'丹佛','康涅狄格州':'哈特福德','特拉华州':'多佛',          '佛罗里达州':'塔拉哈西','佐治亚州':'亚特兰大','夏威夷州':'火奴鲁鲁','爱达荷州':'博伊西',          '伊利诺伊州':'斯普林菲尔德','印第安纳州':'印第安纳波利斯','艾奥瓦州':'得梅因',          '堪萨斯州':'托皮卡','肯塔基州':'法兰克福','路易斯安那州':'巴吞鲁日','缅因州':'奥古斯塔',          '马里兰州':'安那波利斯','麻萨诸塞州':'波士顿','密歇根州':'兰辛','明尼苏达州':'圣保罗',          '密西西比州':'杰克逊','密苏里州':'杰弗逊城','蒙大拿州':'海伦那','内布拉斯加州':'林肯',          '内华达州':'卡森市','新罕布什尔州':'康科德','新泽西州':'特伦顿','新墨西哥州':'圣大非',          '纽约州':'奥尔巴尼','北卡罗来纳州':'罗利','北达科他州':'俾斯麦','俄亥俄州':'哥伦布',          '俄克拉何马州':'俄克拉何马城','俄勒冈州':'塞勒姆','宾夕法尼亚州':'哈里斯堡',          '罗得岛州':'普罗维登斯','南卡罗来纳州':'哥伦比亚','南达科他州':'皮尔','田纳西州':'纳什维尔',          '得克萨斯州':'奥斯汀','犹他州':'盐湖城','佛蒙特州':'蒙比利埃','弗吉尼亚州':'里士满',          '华盛顿州':'奥林匹亚','西弗吉尼亚州':'查尔斯顿','威斯康星州':'麦迪逊','怀俄明州':'夏延'          }

```

英文版:

capitals = {'Alabama': 'Montgomery', 'Alaska': 'Juneau', 'Arizona': 'Phoenix','Arkansas': 'Little Rock', 'California': 'Sacramento', 'Colorado': 'Denver','Connecticut': 'Hartford', 'Delaware': 'Dover', 'Florida': 'Tallahassee','Georgia': 'Atlanta', 'Hawaii': 'Honolulu', 'Idaho': 'Boise', 'Illinois':'Springfield', 'Indiana': 'Indianapolis', 'Iowa': 'Des Moines', 'Kansas':'Topeka', 'Kentucky': 'Frankfort', 'Louisiana': 'Baton Rouge', 'Maine':'Augusta', 'Maryland': 'Annapolis', 'Massachusetts': 'Boston', 'Michigan':'Lansing', 'Minnesota': 'Saint Paul', 'Mississippi': 'Jackson', 'Missouri':'Jefferson City', 'Montana': 'Helena', 'Nebraska': 'Lincoln', 'Nevada':'Carson City', 'New Hampshire': 'Concord', 'New Jersey': 'Trenton', 'New''Mexico': 'Santa Fe', 'New York': 'Albany', 'North Carolina': 'Raleigh','North Dakota': 'Bismarck', 'Ohio': 'Columbus', 'Oklahoma': 'Oklahoma City','Oregon': 'Salem', 'Pennsylvania': 'Harrisburg', 'Rhode Island': 'Providence','South Carolina': 'Columbia', 'South Dakota': 'Pierre', 'Tennessee':'Nashville', 'Texas': 'Austin', 'Utah': 'Salt Lake City', 'Vermont':'Montpelier', 'Virginia': 'Richmond', 'Washington': 'Olympia', 'West''Virginia': 'Charleston', 'Wisconsin': 'Madison', 'Wyoming': 'Cheyenne'}

2. 准备两个文件夹

savepath1='D://question//'savepath2='D://answer//'

savepath1用来保存35份试卷

savepath2原来保存试卷对应答案

写程序

我们首先用for循环生成35份试卷以及对应答案

具体如何操作:可以在每一次循环中用文件读写操作创建对应对卷文件和答案文件

testFile = open(savepath1+'capitals_test%s.txt' % (testNum + 1), 'w')

answerFile = open(savepath2+'capitals_test_answers%s.txt' % (testNum + 1), 'w')

创键完文件后,该怎么操作?这里,我们可以在试卷文件中添加一些试卷必要信息,包括姓名,班级,总分,并备注这是第几份试卷:

testFile.write('姓名:\n\n班级:\n\n总分:\n\n')testFile.write( 'State Capitals Quiz (Form %s)' % (testNum + 1))testFile.write('\n\n')


到这里,你可能感到无从下手,请听我慢慢道来

一份试卷要有50道题目

每个题目类似于:某个州的首府是?

这里的州如何具体化,这就要用到之前准备好capitals字典,字典keys()方法,返回所有键的视图对象

states = list(capitals.keys())

哪如何生成50个问题?这里使用for循环

在每一个循环里面,我们还要输出对应选项

在循环之前,我们还要注意,为了使每份试卷不同,我们要使用random.shuffle()打乱州次序

,每次循环中先找出正确答案,并从错误答案中选择三个组成四个选项答案

最终代码如下

import random

capitals={'阿拉巴马州':'蒙哥马利','阿拉斯加州':'朱诺','亚利桑那州':'凤凰城','阿肯色州':'小石城',          '加利福尼亚州':'萨克拉门托','科罗拉多州':'丹佛','康涅狄格州':'哈特福德','特拉华州':'多佛',          '佛罗里达州':'塔拉哈西','佐治亚州':'亚特兰大','夏威夷州':'火奴鲁鲁','爱达荷州':'博伊西',          '伊利诺伊州':'斯普林菲尔德','印第安纳州':'印第安纳波利斯','艾奥瓦州':'得梅因',          '堪萨斯州':'托皮卡','肯塔基州':'法兰克福','路易斯安那州':'巴吞鲁日','缅因州':'奥古斯塔',          '马里兰州':'安那波利斯','麻萨诸塞州':'波士顿','密歇根州':'兰辛','明尼苏达州':'圣保罗',          '密西西比州':'杰克逊','密苏里州':'杰弗逊城','蒙大拿州':'海伦那','内布拉斯加州':'林肯',          '内华达州':'卡森市','新罕布什尔州':'康科德','新泽西州':'特伦顿','新墨西哥州':'圣大非',          '纽约州':'奥尔巴尼','北卡罗来纳州':'罗利','北达科他州':'俾斯麦','俄亥俄州':'哥伦布',          '俄克拉何马州':'俄克拉何马城','俄勒冈州':'塞勒姆','宾夕法尼亚州':'哈里斯堡',          '罗得岛州':'普罗维登斯','南卡罗来纳州':'哥伦比亚','南达科他州':'皮尔','田纳西州':'纳什维尔',          '得克萨斯州':'奥斯汀','犹他州':'盐湖城','佛蒙特州':'蒙比利埃','弗吉尼亚州':'里士满',          '华盛顿州':'奥林匹亚','西弗吉尼亚州':'查尔斯顿','威斯康星州':'麦迪逊','怀俄明州':'夏延'          }

savepath1='D://question//'

savepath2='D://answer//'

for testNum in range(35):  

    testFile = open(savepath1+'capitals_test%s.txt' % (testNum + 1), 'w')    

    answerFile = open(savepath2+'capitals_test_answers%s.txt' % (testNum + 1), 'w')     

    testFile.write('姓名:\n\n班级:\n\n总分:\n\n')    

    testFile.write( 'State Capitals Quiz (Form %s)' % (testNum + 1))    

    testFile.write('\n\n')    

    states = list(capitals.keys())    

    random.shuffle(states)    

    for questionNum in range(50):       

        correctAnswer = capitals[states[questionNum]]        

        wrongAnswers = list(capitals.values())        

        del wrongAnswers[wrongAnswers.index(correctAnswer)]        

        wrongAnswers = random.sample(wrongAnswers, 3)        

        answerOptions = wrongAnswers + [correctAnswer]        

        random.shuffle(answerOptions)        

        testFile.write('%s. What is the capital of %s?\n' % (questionNum + 1,states[questionNum]))       

        for i in range(4):           

           testFile.write(' %s. %s\n' % ('ABCD'[i], answerOptions[i]))       

          testFile.write('\n')       

          answerFile.write('%s. %s\n' %      (questionNum+1,        'ABCD'[answerOptions.index(correctAnswer)]))    

          testFile.close()    

          answerFile.close()

组织文件:

1.shutil.copy(source, destination):将路径source处的文件复制到路径 destination处的文件夹(source 和 destination 都是字符串),并返回新复制文件绝对路径字符串。

shutil.copytree(source, destination) :将路径source处的文件夹,包括其包含的文件夹和文件,复制到路径destination处的文件夹,并返回新复制文件夹绝对路径字符串。

2.shutil.move(source, destination):将路径source 处的文件/文件夹移动到路径destination,并返回新位置的绝对路径的字符串。

3.os.unlink(path): 删除path处的文件。

os.rmdir(path): 删除path处的文件夹。该文件夹必须为空,其中没有任何文件和文件夹。

shutil.rmtree(path):删除 path 处的文件夹,它包含的所有文件和文件夹都会被删除。

4.os.walk(path):传入一个文件夹的路径,在for循环语句中使用os.walk()函数,遍历目录树,和range()函数遍历一个范围的数字类似。不同的是,os.walk()在循环的每次迭代中,返回三个值:

1)、当前文件夹称的字符串。

2)、当前文件夹中子文件夹的字符串的列表。

3)、当前文件夹中文件的字符串的列表。

实战模拟:

1)、编写一个程序,遍历一个目录树,查找特定扩展名的文件(诸如.pdf 或.jpg)。不论这些文件的位置在哪里, 将它们拷贝到一个新的文件夹中。

import  os

import shutil

path = 'D:\\try'newfolder = 'D:\\test'

for foldername,subfolders,filenames in os.walk(path):    

       print('The current folder is ' + foldername)    for filename in filenames:        

       if filename.endswith('.pdf') or filename.endswith('.png'):            

                print(os.path.join(foldername,filename))                                                                                  shutil.copy(os.path.join(foldername,filename),newfolder)

2)、一些不需要的、巨大的文件或文件夹占据了硬盘的空间,这并不少见。如果你试图释

放计算机上的空间,那么删除不想要的巨大文件效果最好。但首先你必须找到它们。编写

一个程序,遍历一个目录树,查找特别大的文件或文件夹,比方说,超过100MB 的文(回

忆一下,要获得文件的大小,可以使用 os 模块的os.path.getsize())。将这些文件的绝对

路径打印到屏幕上。

import os

for foldername,subfoldername,filenames in os.walk('D:\\BZY'):    

       for filename in   filenames:        

                filesize=os.path.getsize(foldername+'\\'+filename)        

                if(filesize>=100*1024*1024):           

                         print(foldername+'\\'+filename)


3)、编写一个程序, 在一个文件夹中, 找到所有带指定前缀的文件, 诸如 spam001.txt,spam002.txt 等,并定位缺失的编号(例如存在 spam001.txt 和 spam003.txt, 但不存在 spam002.txt)。让该程序对所有后面的文件改名, 消除缺失的编号。作为附加的挑战,编写另一个程序,在一些连续编号的文件中,空出一些编号,以便加入新的文件。

参考自:https://blog.csdn.net/weixin_51391096/article/details/116779284

首先面对这样一道题,必须想到正则匹配,切片,以及os模块相关包,按着我的提示,先不要继续往下看,尝试着自己写出来


import os

import re

import shutil

def eliminate_missing_numbers(folder, prefix):# 编写消除缺失编号的函数,参数folder为绝对路径,参数prefix为前缀

    numbers = []# 列表numbers记录文件名的编号部分

    files_types = []# 列表files_types记录文件名的文件类型部分

    real_filenames = []# 列表real_filenames记录文件名

    prefix_regex = re.compile(r'^(%s)(\d\d\d)(.*)?$' % prefix)# 正则表达式匹配带指定前缀的文件名,第2组匹配编号部分,第3组匹配文件类型部分

    filenames = os.listdir(folder)# 取得路径下文件名及文件夹名的列表

    for filename in filenames:# 遍历路径下文件名及文件夹名的列表

        if os.path.isfile(filename):# 判断是否为文件

            if prefix_regex.search(filename):# 判断是否匹配正则表达式

                numbers.append(prefix_regex.search(filename).group(2))# 将匹配文件名的编号部分加入numbers列表

                files_types.append(prefix_regex.search(filename).group(3))# 将匹配文件名的文件类型部分加入files_types列表

                real_filenames.append(prefix_regex.search(filename).group())# 将匹配的文件名加入real_filenames列表

    numbers.sort()# 将numbers列表排序

    for iin range(len(numbers)):# 遍历记录文件名编号部分的列表

        numbers[i] = i +int(numbers[0])# 消除缺失的编号

    for i, j, kin zip(numbers, files_types, real_filenames):

        after_filefolder = os.path.join(folder, prefix +str(i).rjust(3, '0') + j)# 组合消除缺失编号后的文件路径

        befroe_filefolder = os.path.join(folder, k)# 组合消除缺失编号前的文件路径

        shutil.move(befroe_filefolder, after_filefolder)# 对文件改名

# print(after_filefolder)

# print(befroe_filefolder)

def leave_out_extra_numbers(folder, prefix):# 编写消除缺失编号的函数,参数folder为绝对路径,参数prefix为前缀

    numbers = []# 列表numbers记录文件名的编号部分

    files_types = []# 列表files_types记录文件名的文件类型部分

    real_filenames = []# 列表real_filenames记录文件名

    prefix_regex = re.compile(r'^(%s)(\d\d\d)(.*)?$' % prefix)# 正则表达式匹配带指定前缀的文件名,第2组匹配编号部分,第3组匹配文件类型部分

    filenames = os.listdir(folder)# 取得路径下文件名及文件夹名的列表

    for filenamein filenames:# 遍历路径下文件名及文件夹名的列表

        if os.path.isfile(filename):# 判断是否为文件

            if prefix_regex.search(filename):# 判断是否匹配正则表达式

                numbers.append(prefix_regex.search(filename).group(2))# 将匹配文件名的编号部分加入numbers列表

                files_types.append(prefix_regex.search(filename).(3)group)# 将匹配文件名的文件类型部分加入files_types列表

                real_filenames.append(prefix_regex.search(filename).group())# 将匹配的文件名加入real_filenames列表

    numbers.sort()# 将numbers列表排序

    for iin range(len(numbers)):# 遍历记录文件名编号部分的列表

        numbers[i] =2 *int(numbers[i])# 空出编号

    for i, j, kin zip(numbers[::-1], files_types[::-1], real_filenames[::-1]):

        after_filefolder = os.path.join(folder, prefix +str(i).rjust(3, '0') + j)# 组合空出失编号后的文件路径

        befroe_filefolder = os.path.join(folder, k)# 组合消除缺失编号前的文件路径

        shutil.move(befroe_filefolder, after_filefolder)# 对文件改名

# print(after_filefolder)

# print(befroe_filefolder)


二.自动发送电子邮件

注意:

#1. 出现550错误,则是未设置客户端授权码时导致

#2. 出现554错误,则是126服务器把发送邮箱当作垃圾邮件处理
#1 先导入相关的库和方法

import smtplib  #导入库

from smtplib import SMTP_SSL  #加密邮件内容,防止中途被截获

from email.mime.text import  MIMEText  #构造邮件的正文

from email.mime.image import MIMEImage  #构造邮件的图片

from email.mime.multipart import MIMEMultipart  #把邮件的各个部分装在一起,邮件的主体

from email.header import Header  #邮件的文件头,标题,收件人

#2 设置邮箱域名、发件人邮箱、邮箱授权码、收件人邮箱

host_server ='smtp.163.com' #sina 邮箱smtp服务器                #smtp 服务器的地址

sender_163 ='jianhui202106@163.com'                  #sender_163为发件人的邮箱

pwd ='PBFCDNRXYTYYAZMB'                    #pwd为邮箱的授权码'DYEPOGLZDZYLOMRI'

#也可以自己注册个邮箱,邮箱授权码'DYEPOGLZDZYLOMRI' 获取方式可参考#http://help.163.com/14/0923/22/A6S1FMJD00754KNP.html

receiver ='laozhu202106@163.com'

#3 构建MIMEMultipart对象代表邮件本身,可以往里面添加文本、图片、附件等

msg = MIMEMultipart()#邮件主体

#4 设置邮件头部内容

mail_title ='python办公自动化邮件'  # 邮件标题

msg["Subject"] = Header(mail_title,'utf-8')#装入主体

msg["From"] = sender_163#寄件人

msg["To"] = Header("测试邮箱",'utf-8')#标题

#5 添加正文文本

mail_content ="您好,这是使用python登录163邮箱发送邮件的测试"  #邮件的正文内容

message_text = MIMEText(mail_content,'plain','utf-8')#构造文本,参数1:正文内容,参数2:文本格式,参数3:编码方式

msg.attach(message_text)# 向MIMEMultipart对象中添加文本对象

#6 添加图片

image_data =open('D:\\try\\python办公自动化\\icon1.jpg','rb')# 二进制读取图片

message_image = MIMEImage(image_data.read())# 设置读取获取的二进制数据

image_data.close()# 关闭刚才打开的文件

msg.attach(message_image)# 添加图片文件到邮件信息当中去

# 7 添加附件(excel表格)

atta = MIMEText(open('D:\\try\\python办公自动化\\cat.xlsx', 'rb').read(), 'base64', 'utf-8')# 构造附件

atta["Content-Disposition"] ='attachment; filename="cat.xlsx"'  # 设置附件信息

msg.attach(atta)## 添加附件到邮件信息当中去

#8 发送邮件

smtp = SMTP_SSL(host_server)#SSL登录  创建SMTP对象

smtp.login(sender_163,pwd)## 登录邮箱,传递参数1:邮箱地址,参数2:邮箱授权码

smtp.sendmail(sender_163,sender_163,msg.as_string())# 发送邮件,传递参数1:发件人邮箱地址,参数2:收件人邮箱地址,参数3:把邮件内容格式改为str

print("邮件发送成功")

smtp.quit# 关闭SMTP对象


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容