Add files via upload

This commit is contained in:
Muxiaoxiong 2021-06-18 10:16:23 +08:00 committed by GitHub
parent b63799ae5f
commit 96d9be0119
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 1157 additions and 493 deletions

View File

@ -0,0 +1,659 @@
# 1 文件自动化处理
[TOC]
## 1.1 读写文件
我们知道程序运行时可以用变量来保存运算结果但如果希望程序运行关闭后依然可以查看运行后的结果就需要将数据保存到文件中。简单点你可以将文件内容理解为一个字符串值大小可能有几个GB。本节将学习如何使用python在硬盘上创建、读取和保存文件。
## 1.1.1 文件与文件路径
文件的两个属性“路径”和“文件名”路径指明文件在计算机上的位置文件名是指该位置的文件的名称。比如我的电脑上有个名字为Datawhale - 开源发展理论研究.pdf的文件它的路径在D:\Datawhale。在windows中路径中的D:\部分是“根文件夹”Datawhale是文件夹名。注Windows中文件夹名和文件名不区分大小写的。
在windows上路径书写是使用倒斜杠'\'作为文件夹之间的分隔符而在OS X和Linux上是使用正斜杠'/'作为它们的路径分隔符。通常我们用`os.path.join()`函数来创建文件名称字符串。
```python
import os
os.path.join('Datawhale','docu')
```
我们可以看到返回的是('Datawhale\\\docu'有两个斜杠这是因为有一个斜杠是用来转义的在OS X或Linux上调用这个函数这个字符串就会是'Datawhale/docu'。
## 1.1.2 当前工作目录
每个运行在计算机上的程序,都有一个“当前工作目录”。利用`os.getcwd()`函数,可以取得当前工作路径的
字符串,并可以利用`os.chdir()`改变它。
```python
import os
os.getcwd() #获取当前工作目录
```
```python
os.chdir('D:\\Datawhale\\python办公自动化') #改变当前工作目录
os.getcwd()
```
## 1.1.3 路径操作
### 1.1.3.1 绝对路径和相对路径
“绝对路径”,总是从根文件夹开始。
“相对路径”,相对于程序的当前工作目录。
相对路径中,单个句点“.”表示当前目录的缩写,两个句点“..”表示父文件夹。
![image-20210518151332873](.\图片\image-20210518151332873.png)
几个常用的绝对路径和相对路径处理函数
`os.path.abspath(path)`:将相对路径转换为绝对路径,将返回参数的绝对路径的字符串。`os.path.isabs(path)`判断是否是绝对路径是返回True,不是则返回False
```python
os.path.abspath('.') #当前路径转化为绝对路径。 'D:\\Datawhale\\python办公自动化'
os.path.isabs('.') #False
os.path.isabs(os.path.abspath('.')) #True
```
### 1.1.3.2 路径操作
`os.path.relpath(path,start)`:返回从start路径到path的相对路径的字符串。如果没提供start,就使用当前工作目录作为开始路径。
`os.path.dirname(path)`: 返回当前路径的目录名称。
`os.path.basename(path)`:返回当前路径的文件名称。
```
os.path.relpath('D:\\Datawhale\\python办公自动化','D:\\') #'Datawhale\\python办公自动化'
```
```
path = 'D:\\Datawhale\\python办公自动化\\python课程画图.pptx'
os.path.dirname(path) #'D:\\Datawhale\\python办公自动化'
```
```
os.path.basename(path) #'python课程画图.pptx'
```
如果同时需要一个路径的目录名称和基本名称,可以调用`os.path.split()`,获得者两个字符串的元组。
```python
caFilePath = 'D:\\Datawhale\\python办公自动化\\python课程画图.pptx'
os.path.split(caFilePath) #('D:\\Datawhale\\python办公自动化', 'python课程画图.pptx')
```
```
我们也可以调用os.path.dirname()和os.path.basename(),将它们的返回值放在一个元组中,从而得到同样的元组。
```
```python
(os.path.dirname(caFilePath),os.path.basename(caFilePath)) #('D:\\Datawhale\\python办公自动化', 'python课程画图.pptx')
```
如果我们想返回每个文件夹的字符串的列表。用`os.path.split()`无法得到,我们可以用`split()`字符串方法,并根据`os.path.sep` 中的字符串进行分割。`os.path.sep` 变量设置为正确的文件夹分割斜杠。
```python
caFilePath.split(os.path.sep) #['D:', 'Datawhale', 'python办公自动化', 'python课程画图.pptx']
```
### 1.1.3.3 路径有效性检查
如果提供的路径不存在很多Python函数就会崩溃并报错。`os.path`模块提供了一些函数,用于检测给定的路径是否存在,以及判定是文件还是文件夹。
`os.path.exists(path)`如果path参数所指的文件或文件夹存在则返回True,否则返回False。
`os.path.isfile(path)`如果path参数存在并且是一个文件则返回True,否则返回False。
`os.path.isdir(path)`如果path参数存在并且是一个文件夹则返回True,否则返回False。
```python
os.path.exists('C:\\Windows')
```
```python
os.path.exists('C:\\else')
```
```python
os.path.isfile('D:\\Datawhale\\python办公自动化\\python课程画图.pptx')
```
```python
os.path.isfile('D:\\Datawhale\\python办公自动化')
```
```python
os.path.isdir('D:\\Datawhale\\python办公自动化\\python课程画图.pptx')
```
```python
os.path.isdir('D:\\Datawhale\\python办公自动化')
```
## 1.1.4 文件及文件夹操作
### 1.1.4.1 用os.makedirs()创建新文件夹
注:`os.makedirs()`可以创建所有必要的中间文件夹。
```python
import os
os.makedirs('D:\\Datawhale\\practice') #查看目录,已创建,若文件夹已存在,不会覆盖,会报错
```
### 1.1.4.2 查看文件大小和文件夹内容
我们已经可以处理文件路径,这是操作文件及文件夹的基础。接下来,我们可以搜集特定文件和文件夹的信息。`os.path`模块提供了一些函数,用于查看文件的字节数以及给定文件夹中的文件和子文件夹。
`os.path.getsize(path)`返回path参数中文件的字节数。
`os.listdir(path)`:返回文件名字符串的列表包含path参数中的每个文件。
```python
os.path.getsize('D:\\Datawhale\\python办公自动化\\python课程画图.pptx')
```
```python
os.listdir('D:\\Datawhale\\python办公自动化')
```
如果想知道目录下所有文件的总字节数,可以同时使用`os.path.getsize()`和`os.listdir()`
```python
totalSize = 0
for filename in os.listdir('D:\\Datawhale\\python办公自动化'):
totalSize = totalSize + os.path.getsize(os.path.join('D:\\Datawhale\\python办公自动化',filename))
print(totalSize)
```
## 1.1.5 文件读写过程
读写文件3个步骤
1.调用`open()`函数返回一个File对象。
2.调用File对象的`read()`或`write()`方法。
3.调用File对象的`close()`方法,关闭该文件。
### 1.1.5.1 用open()函数打开文件
要用`open()`函数打开一个文件,就要向它传递一个字符串路径,表明希望打开的文件。这既可以是绝对路径,也可以是相对路径。`open()`函数返回一个File对象。
先用TextEdit创建一个文本文件名为hello.txt。输入Hello World!作为该文本文件的内容,将它保存在你的用户文件夹中。
```python
helloFile = open('D:\\Datawhale\\python办公自动化\\hello.txt')
print(helloFile)
```
可以看到,调用`open()`函数将会返回一个File对象。当你需要读取或写入该文件就可以调用helloFile变量中的File对象的方法。
### 1.1.5.2 读取文件内容
有了File对象我们就可以开始从它读取内容。
`read()`:读取文件内容。
`readlines()`:按行读取文件中的内容,取得一个字符串列表,列表中每个字符串是文本中的一行且以\n结束。
```python
helloContent = helloFile.read()
helloContent
```
```python
sonnetFile = open('D:\\Datawhale\\python办公自动化\\hello.txt')
sonnetFile.readlines()
```
### 1.1.5.3 写入文件
需要用“写模式”w和“添加模式”'a'打开一个文件,而不能用读模式打开文件。
“写模式”将覆写原有的文件,从头开始。“添加模式”将在已有文件的末尾添加文本。
```python
baconFile = open('bacon.txt','w')
baconFile.write('Hello world!\n')
```
```python
baconFile.close() #注意关闭后才能完成写入从txt文件中看到写入的内容。
```
```python
baconFile = open('bacon.txt','a')
baconFile.write('Bacon is not a vegetable.')
```
```python
baconFile.close()
```
```python
baconFile = open('bacon.txt')
content = baconFile.read()
baconFile.close()
print(content)
```
注意,`write()`方法不会像print()函数那样,在字符串的末尾自动添加换行字符。必须自己添加该字符。
### 1.1.5.4 保存变量
1)、shelve模块
用`shelve`模块可以将Python中的变量保存到二进制的`shelf`文件中。这样,程序就可以从硬盘中恢复变量的数据。
```python
import shelve
shelfFile = shelve.open('mydata')
cats = ['Zonphie','Pooka','Simon']
shelfFile['cats'] = cats
shelfFile.close()
```
在Windows上运行前面的代码我们会看到当前工作目录下有3个新文件mydata.bak、mydata.dat和mydata.dir。在OS X上只会创建一个mydata.db文件。
重新打开这些文件,取出数据。注意:`shelf`值不必用读模式或写模式打开,因为打开后,既能读又能写。
```python
shelfFile = shelve.open('mydata')
type(shelfFile)
```
```python
shelve.DbfilenameShelf
```
```python
shelfFile['cats']
```
```python
shelfFile.close()
```
就像字典一样,`shelf`值有`keys()`和`values()`方法返回shelf中键和值的类似列表的值。但是这些方法返回类似列表的值却不是真正的列表所以应该将它们传递给`list()`函数,取得列表的形式。
```python
shelfFile = shelve.open('mydata')
list(shelfFile.keys())
```
```python
list(shelfFile.values())
```
```python
shelfFile.close()
```
2)、用`pprint.pformat()`函数保存变量
`pprint.pformat()`函数返回要打印的内容的文本字符串这个字符串既易于阅读也是语法上正确的Python代码。
假如,有一个字典,保存在一个变量中,希望保存这个变量和它的内容,以便将来使用。`pprint.pformat()`函数将提供一个字符串,我们可以将它写入.py文件。这个文件可以成为我们自己的模块如果需要使用存储其中的变量就可以导入它。
```python
import pprint
cats = [{'name':'Zophie','desc':'chubby'},{'name':'Pooka','desc':'fluffy'}]
pprint.pformat(cats)
```
```python
fileObj = open('myCats.py','w')
fileObj.write('cats = '+pprint.pformat(cats)+'\n')
```
```python
fileObj.close()
```
import语句导入的模块本身就是Python脚本。如果来自pprint.pformat()的字符串保存为一个.py文件该文件就是一个可以导入的模块。
```python
import myCats
myCats.cats
```
```python
myCats.cats[0]
```
```python
myCats.cats[0]['name']
```
## 1.1.6 练习
1、如果已有的文件以写模式打开会发生什么
2、`read()`和`readlines()`方法之间的区别是什么?
综合练习:
一、生成随机的测验试卷文件
假如你是一位地理老师, 班上有 35 名学生, 你希望进行美国各州首府的一个
小测验。不妙的是,班里有几个坏蛋, 你无法确信学生不会作弊。你希望随机调整
问题的次序, 这样每份试卷都是独一无二的, 这让任何人都不能从其他人那里抄袭答案。当然,手工完成这件事又费时又无聊。 好在, 你懂一些 Python。
下面是程序所做的事:
• 创建 35 份不同的测验试卷。
• 为每份试卷创建 50 个多重选择题,次序随机。
• 为每个问题提供一个正确答案和 3 个随机的错误答案,次序随机。
• 将测验试卷写到 35 个文本文件中。
• 将答案写到 35 个文本文件中。
这意味着代码需要做下面的事:
• 将州和它们的首府保存在一个字典中。
• 针对测验文本文件和答案文本文件,调用 open()、 write()和 close()。
• 利用 random.shuffle()随机调整问题和多重选项的次序。
## 1.2 组织文件
在上一节中已经学习了如何使用Python创建并写入新文件。本节将介绍如何用程序组织硬盘上已经存在的文件。不知你是否经历过查找一个文件夹里面有几十个、几百个、甚至上千个文件需要手工进行复制、改名、移动或压缩。比如下列这样的任务
• 在一个文件夹及其所有子文件夹中,复制所有的 pdf 文件(且只复制 pdf 文件)
• 针对一个文件夹中的所有文件,删除文件名中前导的零,该文件夹中有数百个文件,名为 spam001.txt、 spam002.txt、 spam003.txt 等。
• 将几个文件夹的内容压缩到一个 ZIP 文件中(这可能是一个简单的备份系统)
所有这种无聊的任务,正是在请求用 Python 实现自动化。通过对电脑编程来完成这些任务,你就把它变成了一个快速工作的文件职员,而且从不犯错。
### 1.2.1 shutil模块
`shutil`(或称为shell工具)模块中包含一些函数可以在Python程序中复制、移动、改名和删除文件。要使用`shutil`的函数,首先需要`import shutil`
#### 1.2.1.1 复制文件和文件夹
`shutil.copy(source, destination)`将路径source处的文件复制到路径 destination处的文件夹source 和 destination 都是字符串),并返回新复制文件绝对路径字符串。
其中destination可以是
1、一个文件的名称则将source文件复制为新名称的destination
2、一个文件夹则将source文件复制到destination中
3、若这个文件夹不存在则将source目标文件内的内容复制到destination中,若destination文件夹不存在则自动生成该文件。(慎用因为会将source文件复制为一个没有扩展名的名字为destination的文件这往往不是我们希望的)
```python
import shutil
shutil.copy('D:\\Datawhale\\python办公自动化\\bacon.txt', 'D:\\Datawhale\\practice')
```
```python
os.getcwd()
```
```python
shutil.copy('D:\\Datawhale\\python办公自动化\\capitalsquiz_answers1.txt', 'D:\\Datawhale\\practice\\bacon.txt')
```
```python
shutil.copy('D:\\Datawhale\\python办公自动化\\bacon.txt', 'D:\\Datawhale\\exercise')
```
`shutil.copytree(source, destination)` :将路径source处的文件夹包括其包含的文件夹和文件复制到路径destination处的文件夹,并返回新复制文件夹绝对路径字符串。
destination处的文件夹为新创建的文件夹如已存在则会报错
```python
import shutil
shutil.copytree('D:\\Datawhale\\python办公自动化','D:\\Datawhale\\practice')
```
#### 1.2.1.2 文件和文件夹的移动与改名
`shutil.move(source, destination)`:将路径 source 处的文件/文件夹移动到路径destination并返回新位置的绝对路径的字符串。
1)、如果source和destination是文件夹且destination已存在则会将source文件夹下所有内容复制到destination文件夹中。移动。
2、如果source是文件夹destination不存在则会将source文件夹下所有内容复制到destination文件夹中source原文件夹名称将被替换为destination文件夹名。 移动+重命名
3、如果source和destination是文件source处的文件将被移动到destination处的位置并以destination处的文件名进行命名移动+重命名。
注意如果destination中有原来已经存在同名文件移动后会被覆写所以应当特别注意。
```python
import shutil
shutil.move('D:\\Datawhale\\practice','D:\\Datawhale\\docu')
```
```python
shutil.move('D:\\Datawhale\\practice','D:\\Datawhale\\docue')
```
```python
shutil.move('D:\\Datawhale\\docue\\bacon.txt','D:\\Datawhale\\docu\\egg.txt')
```
#### 1.2.1.3 永久删除文件和文件夹
`os.unlink(path)`: 删除path处的文件。
`os.rmdir(path)`: 删除path处的文件夹。该文件夹必须为空其中没有任何文件和文件夹。
`shutil.rmtree(path)`:删除 path 处的文件夹,它包含的所有文件和文件夹都会被删除。
注意:使用时,需要非常小心,避免删错文件,一般在第一次运行时,注释掉这些程序,并加上`print()`函数来帮助查看是否是想要删除的文件。
```python
#建议先指定操作的文件夹,并查看
os.chdir('D:\\Datawhale\\docue')
os.getcwd()
```
```python
import os
for filename in os.listdir():
if filename.endswith('.dir'):
#os.unlink(filename)
print(filename)
```
#### 1.2.1.4 用send2trash模块安全地删除
`shutil.rmtree(path)`会不可恢复的删除文件和文件夹,用起来会有危险。因此使用第三方的`send2trash`模块可以将文件或文件夹发送到计算机的垃圾箱或回收站而不是永久删除。因程序缺陷而用send2trash 删除的某些你不想删除的东西,稍后可以从垃圾箱恢复。
注意:使用时,需要非常小心,避免删错文件,一般在第一次运行时,注释掉这些程序,并加上`print()`函数来帮助查看是否是想要删除的文件。
```python
pip install send2trash #安装send2trash模块
```
```python
import send2trash
send2trash.send2trash('bacon.txt')
```
## 1.2.2 遍历目录树
`os.walk(path)`:传入一个文件夹的路径在for循环语句中使用`os.walk()`函数遍历目录树和range()函数遍历一个范围的数字类似。不同的是,`os.walk()`在循环的每次迭代中,返回三个值:
1、当前文件夹称的字符串。
2、当前文件夹中子文件夹的字符串的列表。
3、当前文件夹中文件的字符串的列表。
当前文件夹是指for循环当前迭代的文件夹。程序的当前工作目录不会因为`os.walk()`而改变。
![image-20210518154517118](.\图片\image-20210518154517118.png)
按照下图目录树,创建相应的文件。
```python
import os
for folderName, subFolders,fileNames in os.walk('D:\\animals'):
print('The current folder is ' + folderName)
for subFolder in subFolders:
print('Subfolder of ' + folderName+':'+subFolder)
for filename in fileNames:
print('File Inside ' + folderName+':'+filename)
print('')
```
## 1.2.3 用zipfile模块压缩文件
为方便传输,常常将文件打包成.zip格式文件。利用zipfile模块中的函数Python程序可以创建和打开或解压zip文件。
### 1.2.3.1 创建和添加到zip文件
将上述章节中animals文件夹进行压缩。创建一个example.zip的zip文件并向其中添加文件。
`zipfile.ZipFile('filename.zip', 'w')` :以写模式创建一个压缩文件
`ZipFile` 对象的 `write('filename','compress_type=zipfile.ZIP_DEFLATED')`方法:如果向`write()`方法中传入一个路径Python 就会压缩该路径所指的文件, 将它加到 ZIP 文件中。 如果向`write()`方法中传入一个字符串,代表要添加的文件名。第二个参数是“压缩类型”参数,告诉计算机用怎样的算法来压缩文件。可以总是将这个值设置为 `zipfile.ZIP_DEFLATED`(这指定了 deflate 压缩算法,它对各种类型的数据都很有效)。
注意写模式会擦除zip文件中所有原有的内容。如果只希望将文件添加到原有的zip文件中就要向`zipfile.ZipFile()`传入'a'作为第二个参数,以添加模式打开 ZIP 文件。
```python
## 1 创建一个new.zip压缩文件并向其中添加文件
import zipfile
newZip = zipfile.ZipFile('new.zip','w')
newZip.write('Miki.txt',compress_type=zipfile.ZIP_DEFLATED)
newZip.close()
```
```python
newZip = zipfile.ZipFile('new.zip','w')
newZip.write('D:\\animals\\dogs\\Taidi.txt',compress_type=zipfile.ZIP_DEFLATED)
newZip.close()
```
```python
## 2 创建一个example.zip的压缩文件将animals文件夹下所有文件进行压缩。
import zipfile
import os
newZip = zipfile.ZipFile('example.zip','w')
for folderName, subFolders,fileNames in os.walk('D:\\animals'):
for filename in fileNames:
newZip.write(os.path.join(folderName,filename),compress_type=zipfile.ZIP_DEFLATED)
newZip.close()
```
### 1.2.3.2 读取zip文件
调用`zipfile.ZipFile(filename)`函数创建一个`ZipFile`对象注意大写字母Z和F,filename是要读取zip文件的文件名。
`ZipFile`对象中的两个常用方法:
`namelis()`方法返回zip文件中包含的所有文件和文件夹的字符串列表。
`getinfo()`方法,返回一个关于特定文件的`ZipInfo`对象。
`ZipInfo`对象的两个属性:`file_size`和`compress_size`分别表示原来文件大小和压缩后文件大小。1.2.3.2 读取zip文件
```
import zipfile,os
exampleZip = zipfile.ZipFile('example.zip')
exampleZip.namelist()
```
```
catInfo = exampleZip.getinfo('animals/Miki.txt')
```
```
catInfo.file_size
```
```
catInfo.compress_size
```
```
print('Compressed file is %s x smaller!' %(round(catInfo.file_size/catInfo.compress_size,2)))
```
```
exampleZip.close()
```
### 1.2.3.3 从zip文件中解压缩
`ZipFile` 对象的 `extractall()`方法从zip文件中解压缩所有文件和文件夹放到当前工作目录中。也可以向`extractall()`传递的一个文件夹名称,它将文件解压缩到那个文件夹, 而不是当前工作目录。如果传递的文件夹名称不存在,就会被创建。
`ZipFile` 对象的 `extract()`方法:从zip文件中解压单个文件。也可以向 extract()传递第二个参数, 将文件解压缩到指定的文件夹, 而不是当前工作目录。如果第二个参数指定的文件夹不存在, Python 就会创建它。extract()的返回值是被压缩后文件的绝对路径。
```python
import zipfile, os
exampleZip = zipfile.ZipFile('example.zip')
exampleZip.extractall('.\zip')
exampleZip.close()
```
```python
exampleZip = zipfile.ZipFile('example.zip')
exampleZip.extract('animals/Miki.txt')
exampleZip.extract('animals/Miki.txt', 'D:\\animals\\folders')
exampleZip.close()
```
## 1.2.4 练习
1、编写一个程序遍历一个目录树查找特定扩展名的文件诸如.pdf 或.jpg。不论这些文件的位置在哪里 将它们拷贝到一个新的文件夹中。
2 、一些不需要的、 巨大的文件或文件夹占据了硬盘的空间, 这并不少见。如果你试图释放计算机上的空间, 那么删除不想要的巨大文件效果最好。但首先你必须找到它们。编写一个程序, 遍历一个目录树, 查找特别大的文件或文件夹, 比方说, 超过100MB 的文件(回忆一下,要获得文件的大小,可以使用 os 模块的 `os.path.getsize()`)。将这些文件的绝对路径打印到屏幕上。
3、编写一个程序 在一个文件夹中, 找到所有带指定前缀的文件, 诸如 spam001.txt,spam002.txt 等,并定位缺失的编号(例如存在 spam001.txt 和 spam003.txt 但不存在 spam002.txt。让该程序对所有后面的文件改名 消除缺失的编号。作为附加的挑战,编写另一个程序,在一些连续编号的文件中,空出一些编号,以便加入新的文件。
## 2 自动发送电子邮件
使用Python实现自动化邮件发送可以让你摆脱繁琐的重复性业务节省非常多的时间。
Python有两个内置库`smtplib`和`email`,能够实现邮件功能,`smtplib`库负责发送邮件,`email`库负责构造邮件格式和内容。
邮件发送需要遵守**SMTP**协议Python内置对SMTP的支持可以发送纯文本邮件、HTML邮件以及带附件的邮件。
```python
#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 #邮件的文件头,标题,收件人
```
```python
#2 设置邮箱域名、发件人邮箱、邮箱授权码、收件人邮箱
host_server = 'smtp.163.com' #sina 邮箱smtp服务器 #smtp 服务器的地址
sender_163 = 'pythonauto_emai@163.com' #sender_163为发件人的邮箱
pwd = 'DYEPOGLZDZYLOMRI' #pwd为邮箱的授权码'DYEPOGLZDZYLOMRI'
#也可以自己注册个邮箱,邮箱授权码'DYEPOGLZDZYLOMRI' 获取方式可参考#http://help.163.com/14/0923/22/A6S1FMJD00754KNP.html
receiver = '********@163.com'
```
```python
#3 构建MIMEMultipart对象代表邮件本身可以往里面添加文本、图片、附件等
msg = MIMEMultipart() #邮件主体
```
```python
#4 设置邮件头部内容
mail_title = 'python办公自动化邮件' # 邮件标题
msg["Subject"] = Header(mail_title,'utf-8') #装入主体
msg["From"] = sender_163 #寄件人
msg["To"] = Header("测试邮箱",'utf-8') #标题
```
```python
#5 添加正文文本
mail_content = "您好这是使用python登录163邮箱发送邮件的测试" #邮件的正文内容
message_text = MIMEText(mail_content,'plain','utf-8') #构造文本,参数1正文内容参数2文本格式参数3编码方式
msg.attach(message_text) # 向MIMEMultipart对象中添加文本对象
```
```python
#6 添加图片
image_data = open('cat.jpg','rb') # 二进制读取图片
message_image = MIMEImage(image_data.read()) # 设置读取获取的二进制数据
image_data.close() # 关闭刚才打开的文件
msg.attach(message_image) # 添加图片文件到邮件信息当中去
```
```python
# 7 添加附件(excel表格)
atta = MIMEText(open('cat.xlsx', 'rb').read(), 'base64', 'utf-8') # 构造附件
atta["Content-Disposition"] = 'attachment; filename="cat.xlsx"' # 设置附件信息
msg.attach(atta) ## 添加附件到邮件信息当中去
```
```python
#8 发送邮件
smtp = SMTP_SSL(host_server) #SSL登录 创建SMTP对象
smtp.login(sender_163,pwd) ## 登录邮箱传递参数1邮箱地址参数2邮箱授权码
smtp.sendmail(sender_163,receiver,msg.as_string()) # 发送邮件传递参数1发件人邮箱地址参数2收件人邮箱地址参数3把邮件内容格式改为str
print("邮件发送成功")
smtp.quit # 关闭SMTP对象
```

View File

@ -1,5 +1,9 @@
# Python自动化之Excel
[TOC]
## 0.包的安装
方法一应用pip执行命令
安装**openpyxl**模块`pip install openpyxl`
@ -14,9 +18,9 @@
![](./图片/Excel.png)
### Excel读取
## 1.Excel读取
#### 读取对应表格
### 1.1读取对应表格
1. 打开已经存在的Excel表格
@ -47,7 +51,7 @@ sheet = exl_1.active
print(sheet.dimensions)
```
#### 读取单元格
### 1.2读取单元格
1. 获取某个单元格的具体内容
@ -65,7 +69,7 @@ print(cell_1.value)
print(cell_1.row, cell_1.column, cell.coordinate)
```
#### 读取多个格子的值
### 1.3读取多个格子的值
1. 指定坐标范围
@ -107,7 +111,7 @@ for col in sheet.iter_cols(min_row = 1, max_row = 5,
print(cell.value)
```
#### 练习题
### 1.4练习题
找出test_1.xlsx中sheet1表中空着的格子并输出这些格子的坐标
@ -126,9 +130,9 @@ for row in sheet.iter_rows(min_row = 1, max_row = 29972,
### Excel写入
## 2.Excel写入
#### 写入单元格并保存
### 2.1写入单元格并保存
```
from openpyxl import load_workbook
@ -141,7 +145,7 @@ sheet['A1'] = 'hello world'
exl.save(filename = 'test.xlsx') #存入原Excel表中,若创建新文件则可命名为不同名称
```
#### 写入行数据并保存
### 2.2写入行数据并保存
1. 写入一行数据并保存
@ -175,14 +179,14 @@ for i in range(len(data)):
exl.save(filename = 'test1.xlsx')
```
#### 将公式写入单元格保存
### 2.3将公式写入单元格保存
```
sheet[A2] = '=SUM(A1:D1)'
exl.save(filename='test.xlsx')
```
#### 插入列数据
### 2.4插入列数据
1. 插入一列
@ -197,7 +201,7 @@ sheet.insert_cols(idx=2) #idx=2第2列第2列前插入一列
sheet.insert_cols(idx=2, amount=5)
```
#### 插入行数据
### 2.5插入行数据
第2行前上面插入一行(或多行)
@ -208,7 +212,7 @@ sheet.insert_rows(idx=2)
sheet.insert_rows(idx=2, amount=5)
```
#### 删除
### 2.6删除
1. 删除多列
@ -222,7 +226,7 @@ sheet.delete_cols(idx=5, amount=2) #第5列前删除2列
sheet.delete_rows(idx=2, amount=5)
```
#### 移动
### 2.7移动
当数字为正即向下或向右,为负即为向上或向左
@ -230,7 +234,7 @@ sheet.delete_rows(idx=2, amount=5)
sheet.move_range('C5:F10', rows=2, cols=-3)
```
#### Sheet表操作
### 2.8Sheet表操作
1. 创建新的sheet
@ -257,7 +261,7 @@ sheet = exl.active
sheet.title = 'newname'
```
#### 创建新的Excel表
### 2.9创建新的Excel表
```
from openpyxl import load_workbook
@ -269,9 +273,9 @@ workbook.save(filename = 'new_test.xlsx')
### Excel 样式
## 3.Excel 样式
#### 设置字体样式
### 3.1设置字体样式
1. 设置字体样式
@ -304,7 +308,7 @@ workbook.save(filename = 'new_test.xlsx')
workbook.save(filename='new_test')
```
#### 设置对齐样式
### 3.2设置对齐样式
水平对齐:`distributed, justify, center, left, fill, centerContinuous, right, general`
@ -352,7 +356,7 @@ cell2.fill = gradient_fill
workbook.save(filename='new_test')
```
#### 设置行高与列宽
### 3.3设置行高与列宽
```
from openpyxl import Workbook
@ -363,7 +367,7 @@ sheet.row_dimensions[1].height = 50
sheet.column_dimensions['C'].width = 20 workbook.save(filename='new_test')
```
#### 合并、取消合并单元格
### 3.4合并、取消合并单元格
```
sheet.merge_cells('A1:B2')
@ -375,7 +379,7 @@ sheet.unmerge_cells(start_row=1, start_column=3,
end_row=2, end_column=4)
```
#### 练习题
### 3.5练习题
打开test文件找出文件中购买数量`buy_mount`超过5的行并对其标红、加粗、附上边框。

View File

@ -1,444 +1,447 @@
# python自动化之word操作
[TOC]
## 1.课前准备
> python 处理 Word 需要用到 python-docx 库,终端执行如下安装命令:
```pyhton
pip3 install python-docx
```
> 或在pycharm的setting操作安装示意如下
![](.\图片\安装docx.png)
## 2.知识要点
> 说明:
> 1. 通过小试牛刀初步认识docx然后系统学习python对word的操作
> 2. 预估每个知识点需要讲解的时间;
> 3. 研发逻辑就是讲解逻辑,一般从上往下,遵循:`What - Why - How` 或 `Why - What - How` 思路;
### 2.1预热初步认识docx
相信同学们都进行过word的操作。话不多说直接上python对word简单操作的代码先有个直观的感觉然后再系统学习
#### 2.1.1新建空白word并插入文字
```python
# 导入库
from docx import Document
# 新建空白文档
doc_1 = Document()
# 添加标题0相当于文章的题目默认级别是1级别范围为0-9
doc_1.add_heading('新建空白文档标题级别为0',level = 0)
doc_1.add_heading('新建空白文档标题级别为1',level = 1)
doc_1.add_heading('新建空白文档标题级别为2',level = 2)
# 新增段落
paragraph_1 = doc_1.add_paragraph('这是第一段文字的开始\n请多多关照')
# 加粗
paragraph_1.add_run('加粗字体').bold = True
paragraph_1.add_run('普通字体')
# 斜体
paragraph_1.add_run('斜体字体').italic =True
# 新段落(当前段落的下方)
paragraph_2 = doc_1.add_paragraph('新起的第二段文字。')
# 新段落(指定端的上方)
prior_paragraph = paragraph_1.insert_paragraph_before('在第一段文字前插入的段落')
# 添加分页符(可以进行灵活的排版)
doc_1.add_page_break()
# 新段落(指定端的上方)
paragraph_3 = doc_1.add_paragraph('这是第二页第一段文字!')
# 保存文件(当前目录下)
doc_1.save('doc_1.docx')
```
### 2.2正式python自动化之word操作
上节只是小试牛刀一下接下来我们系统地学习python自动化之word操作。
在操作之前,我们需要了解 Word 文档的<font color=red>页面结构</font>
- 文档 - Document
- 段落 - Paragraph
- 文字块 - Run
**`python-docx`**将整个文章看做是一个**`Document`**对象 ,其基本结构如下:
- 每个**`Document`**包含许多个代表“段落”的**`Paragraph`**对象,存放在**`document.paragraphs`**中。
- 每个**`Paragraph`**都有许多个代表"行内元素"的**`Run`**对象,存放在**`paragraph.runs`**中。
在**`python-docx`**中,**`run`**是最基本的单位,每个**`run`**对象内的文本样式都是一致的,也就是说,在从**`docx`**文件生成文档对象时,**`python-docx`**会根据样式的变化来将文本切分为一个个的`Run`对象。
#### 2.2.1整体页面结构介绍
我们以一个小案例为主线把文档,段落和文字块串一下:
```python
# 导入库
from docx import Document
from docx.shared import RGBColor, Pt,Inches,Cm
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.oxml.ns import qn
# 新建文档Datawhale
doc_1 = Document()
# 字体设置(全局)
'''只更改font.name是不够的还需要调用._element.rPr.rFonts的set()方法。'''
doc_1.styles['Normal'].font.name = u'宋体'
doc_1.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')
# 添加标题0相当于文章的题目默认级别是1级别范围为0-90时候自动带下划线
heading_1 = doc_1.add_heading('周杰伦',level = 0)
heading_1.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER #居中对齐,默认居左对齐
# 新增段落
paragraph_1 = doc_1.add_paragraph()
'''
设置段落格式首行缩进0.75cm居左段后距离1.0英寸,1.5倍行距。
'''
paragraph_1.paragraph_format.first_line_indent = Cm(0.75)
paragraph_1.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
paragraph_1.paragraph_format.space_after = Inches(1.0)
paragraph_1.paragraph_format.line_spacing = 1.5
text = '中国台湾华语流行歌手、' \
'音乐创作家、作曲家、作词人、' \
'制作人、杰威尔音乐公司老板之一、导演。' \
'近年涉足电影行业。周杰伦是2000年后亚洲流行乐坛最具革命性与指标' \
'性的创作歌手,有“亚洲流行天王”之称。他突破原有亚洲音乐的主题、形' \
'式,融合多元的音乐素材,创造出多变的歌曲风格,尤以融合中西式曲风的嘻哈' \
'或节奏蓝调最为著名,可说是开创华语流行音乐“中国风”的先声。周杰伦的' \
'出现打破了亚洲流行乐坛长年停滞不前的局面,为亚洲流行乐坛翻开了新的一页!'
r_1 = paragraph_1.add_run(text)
r_1.font.size =Pt(10) #字号
r_1.font.bold =True #加粗
r_1.font.color.rgb =RGBColor(255,0,0) #颜色
# 保存文件(当前目录下)
doc_1.save('周杰伦.docx')
```
通过上例我们可以看到最小的操作对象为文字块通过run的指定进行操作。比如字号颜色等而再上一个层级--段落是的格式是通过paragraph_format进行设置
#### 2.2.2字体设置
通过1同学们已经注意到字体的设置是全局变量。如果我想在不同的部分进行不同字体的设置那该怎么办呢这就需要在应用前操作设置一下。
```python
'''字体设置1.py'''
#导入库
from docx import Document
from docx.oxml.ns import qn
from docx.enum.style import WD_STYLE_TYPE
document = Document() # 新建docx文档
# 设置宋体字样式
style_font = document.styles.add_style('宋体', WD_STYLE_TYPE.CHARACTER)
style_font.font.name = '宋体'
document.styles['宋体']._element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')
# 设置楷体字样式
style_font = document.styles.add_style('楷体', WD_STYLE_TYPE.CHARACTER)
style_font.font.name = '楷体'
document.styles['楷体']._element.rPr.rFonts.set(qn('w:eastAsia'), u'楷体') # 将段落中的所有字体
# 设置华文中宋字样式
style_font = document.styles.add_style('华文中宋', WD_STYLE_TYPE.CHARACTER)
style_font.font.name = '华文中宋'
document.styles['华文中宋']._element.rPr.rFonts.set(qn('w:eastAsia'), u'华文中宋')
paragraph1 = document.add_paragraph() # 添加段落
run = paragraph1.add_run(u'aBCDefg这是中文', style='宋体') # 设置宋体样式
font = run.font #设置字体
font.name = 'Cambira' # 设置西文字体
paragraph1.add_run(u'aBCDefg这是中文', style='楷体').font.name = 'Cambira'
paragraph1.add_run(u'aBCDefg这是中文', style='华文中宋').font.name = 'Cambira'
document.save('字体设置1.docx')
```
```python
'''字体设置2.py'''
#导入库
from docx import Document
from docx.oxml.ns import qn
from docx.enum.style import WD_STYLE_TYPE
#定义字体设置函数
def font_setting(doc,text,font_cn):
style_add = doc.styles.add_style(font_cn, WD_STYLE_TYPE.CHARACTER)
style_add.font.name = font_cn
doc.styles[font_cn]._element.rPr.rFonts.set(qn('w:eastAsia'), font_cn)
par = doc.add_paragraph()
text = par.add_run(text, style=font_cn)
doc = Document()
a = '小朋友 你是否有很多问号'
b = '为什么 别人在那看漫画'
c = '我却在学画画 对着钢琴说话'
font_setting(doc,a,'宋体')
font_setting(doc,b,'华文中宋')
font_setting(doc,c,'黑体')
doc.save('字体设置2.docx')
```
我们很容易地看出来字体设置1.py与字体设置2.py的区别在于是否为同一段落同时字体设置2.py中自定义了一个函数。同学们可以在实际工作中看具体场景进行选择。
#### 2.2.3插入图片与表格
```python
#导入库
from docx import Document
from docx.shared import Inches
#打开文档
doc_1 = Document('周杰伦.docx') #上面脚本存储的文档
#新增图片
doc_1.add_picture('周杰伦.jpg',width=Inches(1.0), height=Inches(1.0))
# 创建3行1列表格
table1 = doc_1.add_table(rows=2, cols=1)
table1.style='Medium Grid 1 Accent 1' #表格样式很多种Light Shading Accent 1等
# 修改第2行第3列单元格的内容为营口
table1.cell(0, 0).text = '营口'
# 修改第3行第4列单元格的内容为人民
table1.rows[1].cells[0].text = '人民'
# 在表格底部新增一行
row_cells = table1.add_row().cells
# 新增行的第一列添加内容
row_cells[0].text = '加油'
doc_1.save('周杰伦为营口加油.docx')
```
#### 2.2.4设置页眉页脚
在python-docx包中则要使用节(section)中的页眉(header)和页脚(footer)对象来具体设置。
```python
from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
document = Document() # 新建文档
header = document.sections[0].header # 获取第一个节的页眉
print('页眉中默认段落数:', len(header.paragraphs))
paragraph = header.paragraphs[0] # 获取页眉的第一个段落
paragraph.add_run('这是第一节的页眉') # 添加页面内容
footer = document.sections[0].footer # 获取第一个节的页脚
paragraph = footer.paragraphs[0] # 获取页脚的第一个段落
paragraph.add_run('这是第一节的页脚') # 添加页脚内容
'''在docx文档中又添加了2个节共计3个节页面和页脚会显示了“与上一节相同”。
如果不使用上一节的内容和样式要将header.is_linked_to_previous的属性或footer.is_linked_to_previous的属性设置为False
用于解除“链接上一节页眉”或者“链接上一节页脚”。'''
document.add_section() # 添加一个新的节
document.add_section() # 添加第3个节
header = document.sections[1].header # 获取第2个节的页眉
header.is_linked_to_previous = False # 不使用上节内容和样式
#对齐设置
header = document.sections[1].header # 获取第2个节的页眉
header.is_linked_to_previous = False # 不使用上节内容和样式
paragraph = header.paragraphs[0]
paragraph.add_run('这是第二节的页眉')
paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 设置页眉居中对齐
document.sections[1].footer.is_linked_to_previous = False
footer.paragraphs[0].add_run('这是第二节的页脚') # 添加第2节页脚内容
footer.paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 设置第2节页脚居中对齐
header = document.sections[2].header # 获取第3个节的页眉
header.is_linked_to_previous = False # 不使用上节的内容和样式
paragraph = header.paragraphs[0] # 获取页眉中的段落
paragraph.add_run('这是第三节的页眉')
paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT # 设置页眉右对齐
document.sections[2].footer.is_linked_to_previous = False
footer.paragraphs[0].add_run('这是第三节的页脚') # 添加第3节页脚内容
footer.paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT # 设置第3节页脚右对齐
document.save('页眉页脚1.docx') # 保存文档
```
结果如下:
![](.\图片\页眉页脚设置.png)
#### 2.2.5代码延伸
```python
'''对齐设置'''
from docx.enum.text import WD_ALIGN_PARAGRAPH
#LEFT: 左对齐
#CENTER: 文字居中
#RIGHT: 右对齐
#JUSTIFY: 文本两端对齐
'''设置段落行距'''
from docx.shared import Length
# SINGLE :单倍行距(默认)
#ONE_POINT_FIVE : 1.5倍行距
# DOUBLE2 : 倍行距
#AT_LEAST : 最小值
#EXACTLY:固定值
# MULTIPLE : 多倍行距
paragraph.line_spacing_rule = WD_LINE_SPACING.EXACTLY #固定值
paragraph_format.line_spacing = Pt(18) # 固定值18磅
paragraph.line_spacing_rule = WD_LINE_SPACING.MULTIPLE #多倍行距
paragraph_format.line_spacing = 1.75 # 1.75倍行间距
'''设置字体属性'''
from docx.shared import RGBColor,Pt
#all_caps:全部大写字母
#bold:加粗
#color:字体颜色
#double_strike:双删除线
#hidden : 隐藏
#imprint : 印记
#italic : 斜体
#name :字体
#shadow :阴影
#strike : 删除线
#subscript :下标
#superscript :上标
#underline :下划线
```
## 3.项目实践
### 3.1需求
> 你是公司的行政人员,对合作伙伴进行邀请,参加公司的会议;
>
> 参会人名单如下:
![](.\图片\参会人名单.png)
拟定的邀请函样式如下:
![](.\图片\邀请函样式.png)
**根据参会人名单利用python批量生成邀请函。**
### 3.2需求分析
> 逻辑相对简单:
>
> - 获取 Excel 文件中每一行的信息,提取 参数;结合获取的参数设计邀请函样式并输出
> - 设计word段落及字体等样式。
### 3.3代码
```python
# 导入库
from openpyxl import load_workbook
from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.shared import RGBColor, Pt,Inches,Cm
from docx.oxml.ns import qn
path = r'D:\idea\cloud_analyse_game_sentiment\word自动化'
# 路径为Excel 文件所在的位置,可按实际情况更改
workbook = load_workbook(path + r'\excel到word.xlsx')
sheet = workbook.active #默认的WorkSheet
n = 0 #为了不遍历标题excel的第一行
for row in sheet.rows:
if n:
company = row[0].value
office = row[1].value
name = row[2].value
date = str(row[3].value).split()[0]
print(company, office, name, date)
doc = Document()
heading_1 = '邀 请 函'
paragraph_1 = doc.add_heading(heading_1, level=1)
# 居中对齐
paragraph_1.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
# 单独修改较大字号
for run in paragraph_1.runs:
run.font.size = Pt(17)
greeting_word_1 = '尊敬的'
greeting_word_2 = '公司'
greeting_word_3 = ',您好:'
paragraph_2 = doc.add_paragraph()
paragraph_2.add_run(greeting_word_1)
r_1 = paragraph_2.add_run(company)
r_1.font.bold = True # 加粗
r_1.font.underline = True #下划线
paragraph_2.add_run(greeting_word_2)
r_2 = paragraph_2.add_run(office)
r_2.font.bold = True # 加粗
r_2.font.underline = True #下划线
r_3 = paragraph_2.add_run(name)
r_3.font.bold = True # 加粗
r_3.font.underline = True #下划线
paragraph_2.add_run(greeting_word_3)
paragraph_3 = doc.add_paragraph()
paragraph_3.add_run('现诚挚的邀请您于2021年10月27日参加DataWhale主办的享受开源2050活动地点在北京鸟巢希望您届时莅临参加。')
paragraph_3.paragraph_format.first_line_indent = Cm(0.75)
paragraph_3.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
paragraph_3.paragraph_format.space_after = Inches(1.0)
paragraph_3.paragraph_format.line_spacing = 1.5
paragraph_4 = doc.add_paragraph()
date_word_1 = '邀请时间:'
paragraph_4.add_run(date_word_1)
paragraph_4.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
sign_date = "{}年{}月{}日".format(date.split('-')[0], date.split('-')[1], date.split('-')[2])
paragraph_4.add_run(sign_date).underline = True
paragraph_4.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
#设置全文字体
for paragraph in doc.paragraphs:
for run in paragraph.runs:
run.font.color.rgb = RGBColor(0, 0, 0)
run.font.name = '楷体'
r = run._element.rPr.rFonts
r.set(qn('w:eastAsia'), '楷体')
doc.save(path + "\{}-邀请函.docx".format(name))
n = n + 1
```
### 4.总结
> 本案例也可适用于批量生产固定格式的word如工资条通知单等
# python自动化之word操作
[TOC]
## 1.课前准备
> python 处理 Word 需要用到 python-docx 库,终端执行如下安装命令:
```pyhton
pip3 install python-docx
conda install python-doc
```
> 或在pycharm的setting操作安装示意如下
![](.\图片\安装docx.png)
## 2.知识要点
> 说明:
> 1. 通过小试牛刀初步认识docx然后系统学习python对word的操作
> 2. 预估每个知识点需要讲解的时间;
> 3. 研发逻辑就是讲解逻辑,一般从上往下,遵循:`What - Why - How` 或 `Why - What - How` 思路;
### 2.1初步认识docx
相信同学们都进行过word的操作。话不多说直接上python对word简单操作的代码先有个直观的感觉然后再系统学习
#### 2.1.1新建空白word并插入文字
```python
# 导入库
from docx import Document
# 新建空白文档
doc_1 = Document()
# 添加标题0相当于文章的题目默认级别是1级别范围为0-9
doc_1.add_heading('新建空白文档标题级别为0',level = 0)
doc_1.add_heading('新建空白文档标题级别为1',level = 1)
doc_1.add_heading('新建空白文档标题级别为2',level = 2)
# 新增段落
paragraph_1 = doc_1.add_paragraph('这是第一段文字的开始\n请多多关照')
# 加粗
paragraph_1.add_run('加粗字体').bold = True
paragraph_1.add_run('普通字体')
# 斜体
paragraph_1.add_run('斜体字体').italic =True
# 新段落(当前段落的下方)
paragraph_2 = doc_1.add_paragraph('新起的第二段文字。')
# 新段落(指定端的上方)
prior_paragraph = paragraph_1.insert_paragraph_before('在第一段文字前插入的段落')
# 添加分页符(可以进行灵活的排版)
doc_1.add_page_break()
# 新段落(指定端的上方)
paragraph_3 = doc_1.add_paragraph('这是第二页第一段文字!')
# 保存文件(当前目录下)
doc_1.save('doc_1.docx')
```
### 2.2python自动化之word操作
上节只是小试牛刀一下接下来我们系统地学习python自动化之word操作。
在操作之前,我们需要了解 Word 文档的<font color=red>页面结构</font>
- 文档 - Document
- 段落 - Paragraph
- 文字块 - Run
**`python-docx`**将整个文章看做是一个**`Document`**对象 ,其基本结构如下:
- 每个**`Document`**包含许多个代表“段落”的**`Paragraph`**对象,存放在**`document.paragraphs`**中。
- 每个**`Paragraph`**都有许多个代表"行内元素"的**`Run`**对象,存放在**`paragraph.runs`**中。
在**`python-docx`**中,**`run`**是最基本的单位,每个**`run`**对象内的文本样式都是一致的,也就是说,在从**`docx`**文件生成文档对象时,**`python-docx`**会根据样式的变化来将文本切分为一个个的`Run`对象。
#### 2.2.1整体页面结构介绍
我们以一个小案例为主线把文档,段落和文字块串一下:
```python
# 导入库
from docx import Document
from docx.shared import RGBColor, Pt,Inches,Cm
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.oxml.ns import qn
# 新建文档Datawhale
doc_1 = Document()
# 字体设置(全局)
'''只更改font.name是不够的还需要调用._element.rPr.rFonts的set()方法。'''
doc_1.styles['Normal'].font.name = u'宋体'
doc_1.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')
# 添加标题0相当于文章的题目默认级别是1级别范围为0-90时候自动带下划线
heading_1 = doc_1.add_heading('周杰伦',level = 0)
heading_1.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER #居中对齐,默认居左对齐
# 新增段落
paragraph_1 = doc_1.add_paragraph()
'''
设置段落格式首行缩进0.75cm居左段后距离1.0英寸,1.5倍行距。
'''
paragraph_1.paragraph_format.first_line_indent = Cm(0.75)
paragraph_1.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
paragraph_1.paragraph_format.space_after = Inches(1.0)
paragraph_1.paragraph_format.line_spacing = 1.5
text = '中国台湾华语流行歌手、' \
'音乐创作家、作曲家、作词人、' \
'制作人、杰威尔音乐公司老板之一、导演。' \
'近年涉足电影行业。周杰伦是2000年后亚洲流行乐坛最具革命性与指标' \
'性的创作歌手,有“亚洲流行天王”之称。他突破原有亚洲音乐的主题、形' \
'式,融合多元的音乐素材,创造出多变的歌曲风格,尤以融合中西式曲风的嘻哈' \
'或节奏蓝调最为著名,可说是开创华语流行音乐“中国风”的先声。周杰伦的' \
'出现打破了亚洲流行乐坛长年停滞不前的局面,为亚洲流行乐坛翻开了新的一页!'
r_1 = paragraph_1.add_run(text)
r_1.font.size =Pt(10) #字号
r_1.font.bold =True #加粗
r_1.font.color.rgb =RGBColor(255,0,0) #颜色
# 保存文件(当前目录下)
doc_1.save('周杰伦.docx')
```
通过上例我们可以看到最小的操作对象为文字块通过run的指定进行操作。比如字号颜色等而再上一个层级--段落是的格式是通过paragraph_format进行设置
#### 2.2.2字体设置
通过1同学们已经注意到字体的设置是全局变量。如果我想在不同的部分进行不同字体的设置那该怎么办呢这就需要在应用前操作设置一下。
```python
'''字体设置1.py'''
#导入库
from docx import Document
from docx.oxml.ns import qn
from docx.enum.style import WD_STYLE_TYPE
document = Document() # 新建docx文档
# 设置宋体字样式
style_font = document.styles.add_style('宋体', WD_STYLE_TYPE.CHARACTER)
style_font.font.name = '宋体'
document.styles['宋体']._element.rPr.rFonts.set(qn('w:eastAsia'), u'宋体')
# 设置楷体字样式
style_font = document.styles.add_style('楷体', WD_STYLE_TYPE.CHARACTER)
style_font.font.name = '楷体'
document.styles['楷体']._element.rPr.rFonts.set(qn('w:eastAsia'), u'楷体') # 将段落中的所有字体
# 设置华文中宋字样式
style_font = document.styles.add_style('华文中宋', WD_STYLE_TYPE.CHARACTER)
style_font.font.name = '华文中宋'
document.styles['华文中宋']._element.rPr.rFonts.set(qn('w:eastAsia'), u'华文中宋')
paragraph1 = document.add_paragraph() # 添加段落
run = paragraph1.add_run(u'aBCDefg这是中文', style='宋体') # 设置宋体样式
font = run.font #设置字体
font.name = 'Cambira' # 设置西文字体
paragraph1.add_run(u'aBCDefg这是中文', style='楷体').font.name = 'Cambira'
paragraph1.add_run(u'aBCDefg这是中文', style='华文中宋').font.name = 'Cambira'
document.save('字体设置1.docx')
```
```python
'''字体设置2.py'''
#导入库
from docx import Document
from docx.oxml.ns import qn
from docx.enum.style import WD_STYLE_TYPE
#定义字体设置函数
def font_setting(doc,text,font_cn):
style_add = doc.styles.add_style(font_cn, WD_STYLE_TYPE.CHARACTER)
style_add.font.name = font_cn
doc.styles[font_cn]._element.rPr.rFonts.set(qn('w:eastAsia'), font_cn)
par = doc.add_paragraph()
text = par.add_run(text, style=font_cn)
doc = Document()
a = '小朋友 你是否有很多问号'
b = '为什么 别人在那看漫画'
c = '我却在学画画 对着钢琴说话'
font_setting(doc,a,'宋体')
font_setting(doc,b,'华文中宋')
font_setting(doc,c,'黑体')
doc.save('字体设置2.docx')
```
我们很容易地看出来字体设置1.py与字体设置2.py的区别在于是否为同一段落同时字体设置2.py中自定义了一个函数。同学们可以在实际工作中看具体场景进行选择。
#### 2.2.3插入图片与表格
```python
#导入库
from docx import Document
from docx.shared import Inches
#打开文档
doc_1 = Document('周杰伦.docx') #上面脚本存储的文档
#新增图片
doc_1.add_picture('周杰伦.jpg',width=Inches(1.0), height=Inches(1.0))
# 创建3行1列表格
table1 = doc_1.add_table(rows=2, cols=1)
table1.style='Medium Grid 1 Accent 1' #表格样式很多种Light Shading Accent 1等
# 修改第2行第3列单元格的内容为营口
table1.cell(0, 0).text = '营口'
# 修改第3行第4列单元格的内容为人民
table1.rows[1].cells[0].text = '人民'
# 在表格底部新增一行
row_cells = table1.add_row().cells
# 新增行的第一列添加内容
row_cells[0].text = '加油'
doc_1.save('周杰伦为营口加油.docx')
```
#### 2.2.4设置页眉页脚
在python-docx包中则要使用节(section)中的页眉(header)和页脚(footer)对象来具体设置。
```python
from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
document = Document() # 新建文档
header = document.sections[0].header # 获取第一个节的页眉
print('页眉中默认段落数:', len(header.paragraphs))
paragraph = header.paragraphs[0] # 获取页眉的第一个段落
paragraph.add_run('这是第一节的页眉') # 添加页面内容
footer = document.sections[0].footer # 获取第一个节的页脚
paragraph = footer.paragraphs[0] # 获取页脚的第一个段落
paragraph.add_run('这是第一节的页脚') # 添加页脚内容
'''在docx文档中又添加了2个节共计3个节页面和页脚会显示了“与上一节相同”。
如果不使用上一节的内容和样式要将header.is_linked_to_previous的属性或footer.is_linked_to_previous的属性设置为False
用于解除“链接上一节页眉”或者“链接上一节页脚”。'''
document.add_section() # 添加一个新的节
document.add_section() # 添加第3个节
header = document.sections[1].header # 获取第2个节的页眉
header.is_linked_to_previous = False # 不使用上节内容和样式
#对齐设置
header = document.sections[1].header # 获取第2个节的页眉
header.is_linked_to_previous = False # 不使用上节内容和样式
paragraph = header.paragraphs[0]
paragraph.add_run('这是第二节的页眉')
paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 设置页眉居中对齐
document.sections[1].footer.is_linked_to_previous = False
footer.paragraphs[0].add_run('这是第二节的页脚') # 添加第2节页脚内容
footer.paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 设置第2节页脚居中对齐
header = document.sections[2].header # 获取第3个节的页眉
header.is_linked_to_previous = False # 不使用上节的内容和样式
paragraph = header.paragraphs[0] # 获取页眉中的段落
paragraph.add_run('这是第三节的页眉')
paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT # 设置页眉右对齐
document.sections[2].footer.is_linked_to_previous = False
footer.paragraphs[0].add_run('这是第三节的页脚') # 添加第3节页脚内容
footer.paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT # 设置第3节页脚右对齐
document.save('页眉页脚1.docx') # 保存文档
```
结果如下:
![](.\图片\页眉页脚设置.png)
#### 2.2.5代码延伸
```python
'''对齐设置'''
from docx.enum.text import WD_ALIGN_PARAGRAPH
#LEFT: 左对齐
#CENTER: 文字居中
#RIGHT: 右对齐
#JUSTIFY: 文本两端对齐
'''设置段落行距'''
from docx.shared import Length
# SINGLE :单倍行距(默认)
#ONE_POINT_FIVE : 1.5倍行距
# DOUBLE2 : 倍行距
#AT_LEAST : 最小值
#EXACTLY:固定值
# MULTIPLE : 多倍行距
paragraph.line_spacing_rule = WD_LINE_SPACING.EXACTLY #固定值
paragraph_format.line_spacing = Pt(18) # 固定值18磅
paragraph.line_spacing_rule = WD_LINE_SPACING.MULTIPLE #多倍行距
paragraph_format.line_spacing = 1.75 # 1.75倍行间距
'''设置字体属性'''
from docx.shared import RGBColor,Pt
#all_caps:全部大写字母
#bold:加粗
#color:字体颜色
#double_strike:双删除线
#hidden : 隐藏
#imprint : 印记
#italic : 斜体
#name :字体
#shadow :阴影
#strike : 删除线
#subscript :下标
#superscript :上标
#underline :下划线
```
## 3.项目实践
### 3.1需求
> 你是公司的行政人员,对合作伙伴进行邀请,参加公司的会议;
>
> 参会人名单如下:
![](.\图片\参会人名单.png)
拟定的邀请函样式如下:
![](.\图片\邀请函样式.png)
**根据参会人名单利用python批量生成邀请函。**
### 3.2需求分析
> 逻辑相对简单:
>
> - 获取 Excel 文件中每一行的信息,提取 参数;结合获取的参数设计邀请函样式并输出
> - 设计word段落及字体等样式。
### 3.3代码
```python
# 导入库
from openpyxl import load_workbook
from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.shared import RGBColor, Pt,Inches,Cm
from docx.oxml.ns import qn
path = r'D:\idea\cloud_analyse_game_sentiment\word自动化'
# 路径为Excel 文件所在的位置,可按实际情况更改
workbook = load_workbook(path + r'\excel到word.xlsx')
sheet = workbook.active #默认的WorkSheet
n = 0 #为了不遍历标题excel的第一行
for row in sheet.rows:
if n:
company = row[0].value
office = row[1].value
name = row[2].value
date = str(row[3].value).split()[0]
print(company, office, name, date)
doc = Document()
heading_1 = '邀 请 函'
paragraph_1 = doc.add_heading(heading_1, level=1)
# 居中对齐
paragraph_1.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
# 单独修改较大字号
for run in paragraph_1.runs:
run.font.size = Pt(17)
greeting_word_1 = '尊敬的'
greeting_word_2 = '公司'
greeting_word_3 = ',您好:'
paragraph_2 = doc.add_paragraph()
paragraph_2.add_run(greeting_word_1)
r_1 = paragraph_2.add_run(company)
r_1.font.bold = True # 加粗
r_1.font.underline = True #下划线
paragraph_2.add_run(greeting_word_2)
r_2 = paragraph_2.add_run(office)
r_2.font.bold = True # 加粗
r_2.font.underline = True #下划线
r_3 = paragraph_2.add_run(name)
r_3.font.bold = True # 加粗
r_3.font.underline = True #下划线
paragraph_2.add_run(greeting_word_3)
paragraph_3 = doc.add_paragraph()
paragraph_3.add_run('现诚挚的邀请您于2021年10月27日参加DataWhale主办的享受开源2050活动地点在北京鸟巢希望您届时莅临参加。')
paragraph_3.paragraph_format.first_line_indent = Cm(0.75)
paragraph_3.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
paragraph_3.paragraph_format.space_after = Inches(1.0)
paragraph_3.paragraph_format.line_spacing = 1.5
paragraph_4 = doc.add_paragraph()
date_word_1 = '邀请时间:'
paragraph_4.add_run(date_word_1)
paragraph_4.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
sign_date = "{}年{}月{}日".format(date.split('-')[0], date.split('-')[1], date.split('-')[2])
paragraph_4.add_run(sign_date).underline = True
paragraph_4.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
#设置全文字体
for paragraph in doc.paragraphs:
for run in paragraph.runs:
run.font.color.rgb = RGBColor(0, 0, 0)
run.font.name = '楷体'
r = run._element.rPr.rFonts
r.set(qn('w:eastAsia'), '楷体')
doc.save(path + "\{}-邀请函.docx".format(name))
n = n + 1
```
### 4.后记
> 本案例也可适用于批量生产固定格式的word如工资条通知单等面对这种相似且重复的任务python的自动化运行能大幅提升当前的工作效率。

View File

@ -1,28 +1,16 @@
# Python 操作 PDF
[TOC]
#### Python 操作 PDF
## 0.前言
PDF 操作是本次自动化办公的最后一个知识点,初级的 PDF 自动化包括 PDF 文档的拆分、合并、提取等操作,更高级的还包括 WORD与PDF互转等
初级操作一般比较常用,也可以解决较多的办公内容,所以本节将会主要介绍 PDF 的初级操作,具体内容将会从以下几个小节展开:
1. 相关介绍
2. 批量拆分
3. 批量合并
4. 提取文字内容
5. 提取表格内容
6. 提取图片内容
7. 转换为PDF图片
8. 添加水印
9. 加密与解密
下面直接开始本节内容。
初级操作一般比较常用,也可以解决较多的办公内容,所以本节将会主要介绍 PDF 的初级操作,具体内容可以索引目录
<br>
#### 1. 相关介绍
## 1. 相关介绍
Python 操作 PDF 会用到两个库分别是PyPDF2 和 pdfplumber
@ -48,7 +36,7 @@ win+r 后输入 cmd 打开 command 窗口,依次输入如下命令进行安装
<br>
#### 2. 批量拆分
## 2. 批量拆分
将一个完整的 PDF 拆分成几个小的 PDF因为主要涉及到 PDF 整体的操作,所以本小节需要用到 PyPDF2 这个库
@ -134,7 +122,7 @@ except Exception as e:
<br>
#### 3. 批量合并
## 3. 批量合并
比起拆分来,合并的思路更加简单:
@ -174,7 +162,7 @@ def concat_pdf(filename, read_dirpath, save_filepath):
<br>
#### 4. 提取文字内容
## 4. 提取文字内容
涉及到具体的 PDF 内容 操作,本小节需要用到 pdfplumber 这个库
@ -218,7 +206,7 @@ with pdfplumber.open(filepath) as pdf:
<br>
#### 5. 提取表格内容
## 5. 提取表格内容
同样的,本节是对具体内容的操作,所以也需要用到 pdfplumber 这个库
@ -274,7 +262,7 @@ for index in range(len(tables_info)):
<br>
#### 6. 提取图片内容
## 6. 提取图片内容
提取 PDF 中的图片和将 PDF 转存为图片是不一样的(下一小节),需要区分开。
@ -345,11 +333,11 @@ for index in range(1, xref_len):
<br>
#### 7. 转换为图片
## 7. 转换为图片
转换为照片比较简单,就是将一页页的 PDF 转换为一张张的图片。大致过程如下:
##### 7.1 安装 pdf2image
### 7.1 安装 pdf2image
首先需要安装对应的库,最新的 pdf2image 库版本应该是 1.14.0
@ -359,7 +347,7 @@ for index in range(1, xref_len):
> pip install pdf2image
##### 7.2 安装组件
### 7.2 安装组件
对于不同的平台,需要安装相应的组件,这里以 windows 平台和 mac 平台为例:
@ -399,7 +387,7 @@ for image in images:
<br>
#### 8. 添加水印
## 8. 添加水印
PDF 中添加水印首先需要一个水印PDF文件然后依次通过 mergePage 操作将每一页的 PDF 文件合并到水印文件上,据此,每一页的 PDF 文件将是一个带有水印的 PDF 文件
@ -444,7 +432,7 @@ with open(save_filepath, "wb") as out:
<br>
#### 9. 文档加密与解密
## 9. 文档加密与解密
你可能在打开部分 PDF 文件的时候,会弹出下面这个界面:

View File

@ -1,10 +1,14 @@
# Task5 爬虫入门与综合应用
[TOC]
## 0.前言
对于自动化办公而言,网络数据的批量获取完数据可以节约相当的时间,因此爬虫在自动化办公中占据了一个比较重要的位置。
因而本节针对爬虫项目进行一个介绍,力求最大程度还原实际的办公场景。
## **1.Requests简介**
## 1.Requests简介
Requests是一款目前非常流行的http请求库使用python编写能非常方便的对网页Requests进行爬取也是爬虫最常用的发起请求第三方库。
@ -23,6 +27,8 @@ rs.content 响应内容的二进制形式
rs.encoding 响应内容的编码
```
### 1.1访问百度
试一试对百度首页进行数据请求:
项目难度:⭐
@ -40,6 +46,8 @@ print(re.status_code)
**res.text** 返回的是服务器响应内容的字符串形式,也就是文本内容
### 1.2下载txt文件
用爬虫下载孔乙己的文章网址是https://apiv3.shanbay.com/codetime/articles/mnvdu
我们打开这个网址 可以看到是鲁迅的文章
@ -62,6 +70,8 @@ with open('鲁迅文章.txt', 'w') as file:
re.txt就是网页中的内容将内容保存到txt文件中
### 1.3下载图片
**re.text用于文本内容的获取、下载
re.content用于图片、视频、音频等内容的获取、下载**