python办公自动化(入门)
持久化:内存(不能长时间保存数据)到硬盘(可以长时间保存数据)
文件系统:存储和管理数据的一种方式
格式化硬盘的时候就是在创建一个文件系统
open()函数
在python中使用操作文件之前,需要使用open()打开文件,其会返回一个文件对象。
下面时open函数的参数列表:
open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True)
file:要创建或者打开的文件。通常为:文件路径/文件名.文件格式
mode:可选参数,指定文件的打开模式,默认为只读的方式打开
buffering:可选参数,用于设置缓冲策略。具体操作在进阶里面说
encoding:可选参数,用于解码或编码的编码名称文件
errors:可选参数,errors是一个可选字符串,用于指定如何处理编码错误。这个参数不应该在二进制模式下使用
newline:可选参数,控制通用换行符的工作方式
closefd:默认值值为True,如果closefd为False,底层文件描述符将保持打开状态当文件关闭时。当给定了文件名时,这就不起作用了并且在这种情况下必须为真
文件的操作模式(mode参数)有如下几种:
操作模式 | 具体含义 |
---|
r | 读取 (默认) | w | 写入(会先截断之前的内容) | x | 写入,如果文件已经存在会产生异常 | a | 追加,将内容写入到已有文件的末尾 | b | 二进制模式 | t | 文本模式(默认) | + | 更新(既可以读又可以写) |
这里我们只需要先了解file、mode、encoding这三个参数
读取文件内容
致橡树.txt 文档
file = open(file ='致橡树.txt', mode ='r', encoding ='utf-8')
print(file.read())
file.close()
'r’以只读的方式打开,同时选取utf-8作为文件的编码方式(我的编译器编码方式为utf-8,而致橡树.txt文件的编码方式为gbk,所以需要把文档的编码改为utf-8)
如何查看编译器编码:
import sys
print(sys.getdefaultencoding())
这里有一个问题,就是如果在文件关闭之前,前面的代码出现错误,从而导致无法执行文件关闭的语句,这样怎么办呢?
这里我们可以使用一个异常处理语句try-finally,无论try语句里面的内容是否出现异常,始终都会执行finally语句块里面的内容。
代码如下:
file = open(file ='致橡树.txt', mode ='r', encoding ='utf-8')
try:
print(file.read())
finally:
file.close()
print('关闭文件成功')
以后我们都将使用上面这个格式去操作文件。
当一个文件很大时,这里将耗费很多时间和缓存,我们可以分批次读取
file = open(file ='致橡树.txt', mode ='r', encoding ='utf-8')
try:
data = file.read(32)
while data:
print(data, end = '')
data = file.read(32)
finally:
file.close()
print('关闭文件成功')
写入内容
如果要向文件中写入内容,我们需要将文件的打开模式改为a或者w
这里我们打开一个新的空白文件(文件不存在就在当前路径下创建一个新文档)
这里我们文件打开模型选择为w,为只读模式,我不能对其进行读操作。
file = open('小雨康桥的诗.txt', mode = 'w', encoding = 'utf-8')
try:
file.write('我只想做燕子\n')
file.write('只需简单思想\n')
file.write('只求风中流浪\n')
file.write('我想作树\n')
file.write('不想长五脏六腑\n')
file.write('不会肝肠寸断\n')
finally:
file.close()
print('关闭文件成功')
如果我们还行在文件后面继续写入文件,我们可以进行如下操作
file = open('小雨康桥的诗.txt', mode = 'a', encoding = 'utf-8')
try:
file.write('我做不成燕子\n')
file.write('所以我飞不过感情的墙\n')
file.write('我做不成树\n')
file.write('因此也撑不破伤心的网\n')
finally:
file.close()
print('关闭文件成功')
读写二进制文件
先给大家介绍一个函数seek()。我们可以使用它移动文件指针到指定位置,然后进行读写。
seek(移动字节数,移动模式): 移动模式有三种,如下: 0:默认的模式,以文件开头为初始点移动移动指针; 1:以当前指针所在位置为初始点移动指针; 2:以文件末尾为初始位置移动指针; 强调:其中0模式可以在t或者b模式使用,而1跟2模式只能在b模式下用
实例:
file = open('小雨康桥的诗.txt', mode = 'w', encoding = 'utf-8')
try:
print(file.tell())
file.seek(0, 0)
print(file.tell())
file.seek(8, 0)
print(file.tell())
finally:
file.close()
这里我们文件的操作模式为w,所以不能使用seek(n,1) 、seek(n, 2) (n表示移动字节数)
以二进制形式打开文件,以图片为例,该图片为一个截图
from io import SEEK_END, SEEK_SET
file = open(file = 'image.jpg', mode = 'rb')
file.seek(0, SEEK_END)
print(file.tell())
file.seek(0, SEEK_SET)
try:
data = file.read(512)
while data:
print(data, end = '')
data = file.read()
finally:
file.close()
print('关闭文件')
上下文语法
对于open函数,我们还可以用with上下文语法,使用with上下文语法会在结束文件操作之后,会自动保存文件,这样我们就不需要再写finally语句在执行close方法了,让代码变得更简洁。不过并不是所有的对象都可以使用with上下文语法,必须符合上下文管理器协议的对象(有__enter__ 和__exit__ 魔术方法)才可以使用。
实例:
with open('小雨康桥的诗.txt', 'r', encoding = 'utf-8-sig') as file:
print(file.read())
with open('小雨康桥的诗.txt', 'a', encoding = 'utf-8-sig') as file2:
file2.write('我做不成燕子\n')
file2.write('所以我飞不过感情的墙\n')
file2.write('我做不成树\n')
file2.write('因此也撑不破伤心的网\n')
读写CSV文件
CSV(Comma Separated Values)全称逗号分隔值文件。接下来将使用python对CSV文件进行操作。这里我们需要导入python中的csv模块。
csv这里我们主要介绍两个方法,
csv.reader:返回一个遍历 CSV 文件各行的读取对象(已经读取文件中的所有数据)
csv.writer:将数据写入CSV的写入对象
读取csv文件
import csv
with open('2018年北京积分落户数据2.csv', encoding = 'gb18030') as file:
content = file.readline()
while content:
values = content.replace('\n', '').split(',')
print(values)
content = file.readline()
还可以通过delimiter 、quotechar 参数来指定分隔符(默认是英文的逗号)、包围值的字符(默认是英文双引号)。其中,包围值的字符主要用于当字段中有特殊符号时,通过添加包围值的字符可以避免二义性。
with open('2018年北京积分落户数据2.csv', encoding = 'gb18030') as file:
reader = csv.reader(file, delimiter = '#', quotechar = '@')
for row in reader:
print(row)
将数据写入csv文件中
import csv
import random
with open('成绩.csv', 'w', encoding = 'utf-8-sig', newline = "") as file:
writer = csv.writer(file)
writer.writerow(['姓名', '语文成绩', '数学成绩', '英语成绩'])
names = ['小明', '大毛', '二毛']
for i in range(3):
subject1 = random.randrange(50, 101)
subject2 = random.randrange(60, 101)
subject3 = random.randrange(40, 101)
writer.writerow([names[i], subject1, subject2, subject3])
读写Excel文件
读写Excel文件,我们需要使用一些python的第三方库:
xlrd / xlwt :读取 / 写入,二者兼容低版本的Excel文件(后缀名为xls)
xlutils:支持同时对Excel文件进行读操作和写入操作
openpyxl:获取Excel对象,兼容高版本的Excel文件(后缀名为xlsx)
读取Excel文件
import xlrd
wb = xlrd.open_workbook('阿里巴巴2020年股票数据.xls')
print(type(wb))
print(wb.sheet_names())
sheet = wb.sheet_by_name('股票数据')
sheet2 = wb.sheet_by_index(0)
print(type(sheet))
print(sheet.nrows, sheet.ncols)
print(sheet.row(0))
print(sheet.row_slice(0, start_colx=0, end_colx=3))
print(sheet.col(4))
print(sheet.col_slice(4, start_rowx=1, end_rowx=11))
cell = sheet.cell(2, 2)
print(type(cell))
print(cell.value)
遍历整个sheet,根据数据的格式,在遍历的同时对数据进行处理
import xlrd
wb = xlrd.open_workbook('resources/阿里巴巴2020年股票数据.xls')
sheet = wb.sheet_by_index(0)
print(f'交易日期\t\t\t最高价\t\t最低价\t\t开盘价\t\t收盘价\t\t成交量\t\t调整收盘价')
for row in range(1, sheet.nrows):
for col in range(sheet.ncols):
value = sheet.cell(row, col).value
if col == 0:
curr_date = xlrd.xldate_as_datetime(value, 0)
print(curr_date.strftime('%Y年%m月%d日'), end='\t')
elif col == 5:
print(f'{int(value):<10d}', end='\t')
else:
print(f'{value:.4f}', end='\t')
print()
写Excel文件
import random
import xlwt
names = ['小明', '大毛', '二毛']
scores = [[random.randint(40, 100) for _ in range(3)] for _ in range(3)]
wb = xlwt.Workbook()
sheet = wb.add_sheet('五年级20班')
titles = ('姓名', '语文成绩', '数学成绩', '英语成绩')
for index, title in enumerate(titles):
sheet.write(0, index, title)
for row in range(len(scores)):
sheet.write(row + 1, 0, names[row])
for col in range(len(scores[row])):
sheet.write(row + 1, col + 1, scores[row][col])
wb.save('考试成绩表.xlsx')
调整单元格样式
我们还可以为单元格设置样式,主要包括字体(Font)、对齐方式(Alignment)、边框(Border)和背景(Background)的设置
import random
import xlwt
names = ['小明', '大毛', '二毛']
scores = [[random.randint(40, 100) for _ in range(3)] for _ in range(3)]
wb = xlwt.Workbook()
sheet = wb.add_sheet('五年级20班')
header_style = xlwt.XFStyle()
pattern = xlwt.Pattern()
pattern.pattern = xlwt.Pattern.SOLID_PATTERN
pattern.pattern_fore_colour = 4
header_style.pattern = pattern
font = xlwt.Font()
font.name = '华文楷体'
font.height = 20 * 18
font.bold = True
font.italic = False
font.colour_index = 1
header_style.font = font
align = xlwt.Alignment()
align.vert = xlwt.Alignment.VERT_CENTER
align.horz = xlwt.Alignment.HORZ_CENTER
header_style.alignment = align
borders = xlwt.Borders()
props = (
('top', 'top_colour'), ('right', 'right_colour'),
('bottom', 'bottom_colour'), ('left', 'left_colour')
)
for position, color in props:
setattr(borders, position, xlwt.Borders.DASHED)
setattr(borders, color, 2)
header_style.borders = borders
sheet.row(0).set_style(xlwt.easyxf(f'font:height {20 * 40}'))
titles = ('姓名', '语文', '数学', '英语')
for index, title in enumerate(titles):
sheet.col(index).width = 20 * 150
titles = ('姓名', '语文成绩', '数学成绩', '英语成绩')
for index, title in enumerate(titles):
sheet.write(0, index, title, header_style)
for row in range(len(scores)):
sheet.write(row + 1, 0, names[row])
for col in range(len(scores[row])):
sheet.write(row + 1, col + 1, scores[row][col])
wb.save('考试成绩表.xlsx')
简单计算
计算刚才的考试成绩表.xlsx里面每个人的平均成绩
import xlrd
import xlwt
from xlutils.copy import copy
wb1 = xlrd.open_workbook('考试成绩表.xls')
wb2 = copy(wb1)
sheet = wb2.get_sheet(0)
sheet.write(0, 4, '平均分')
for row_index in range(1, 4):
sheet.write(row_index, 4, xlwt.Formula(f'average(B{row_index + 1}:D{row_index + 1})'))
wb2.save('考试成绩表—平均成绩.xls')
openpyxl读取Excel文件
import openpyxl
from datetime import datetime
wb = openpyxl.load_workbook('股票数据.xlsx')
print(type(wb))
print(wb.sheetnames)
sheet = wb.worksheets[0]
print(type(sheet))
print(sheet.dimensions)
print(sheet.max_row, sheet.max_column)
操作Word文档
这里我们会用到两个模块python-docx、pillow,一个用于处理word文档,一个用于处理图像。
创建一个word文档
from docx import Document
from docx.shared import Inches
from docx.document import Document as Doc
document = Document()
document.add_heading('三国', 0)
p = document.add_paragraph('三国(220年-280年)是中国历史上位于汉朝之后、晋朝之前的一段历史时期。\
这一个时期,先后出现了曹魏、蜀汉、东吴三个主要政权。263年,蜀汉后主刘禅投降,\
蜀汉被魏所灭。265年司马昭去世,其子司马炎夺取曹魏政权,定都洛阳,建立晋朝,\
史称西晋。280年司马炎大举进攻吴国,孙吴灭亡,西晋统一天下,至此,')
p.add_run('近百年的战乱结束,').bold = True
p.add_run('三家归晋。').italic = True
document.add_heading('三国历史简介', level = 1)
document.add_paragraph('人物简介', style = 'Intense Quote')
document.add_paragraph(
'曹魏阵营', style = 'List Bullet'
)
document.add_paragraph(
'曹操:', style = 'List Number'
)
document.add_paragraph(
'郭嘉:', style = 'List Number'
)
document.add_picture('三国.jpg', width = Inches(4))
records = (
('刘备', '男', '蜀汉'),
('孙权', '男', '东吴'),
('曹丕', '男', '曹魏'),
('吕布', '男', '群雄')
)
table = document.add_table(rows = 1, cols = 3)
hdr_cells = table.rows[0].cells
hdr_cells[0].text = '姓名'
hdr_cells[1].text = '性别'
hdr_cells[2].text = '势力'
for qty, id, desc in records:
row_cells = table.add_row().cells
row_cells[0].text = str(qty)
row_cells[1].text = id
row_cells[2].text = desc
document.add_page_break()
document.save('三国.docx')
生成样板文章
from docx import Document
from docx.document import Document as Doc
doc = Document('离职证明.docx')
for i, paragraph in enumerate(doc.paragraphs):
print(i, paragraph.text)
for paragraph in doc.paragraphs:
if '曹操' in paragraph.text:
for run in paragraph.runs:
run.text = run.text.replace('曹操', '曹丕')
doc.save('离职证明(新).docx')
Word就简单介绍一下了。
操作PDF文件
在Python中,可以使用PyPDF2的三方库来读取PDF文件,安装的方法就不多说了。
虽然PyPDF2不能从PDF文档中提取图像、图表或其他媒体,但它可以提取文本,并将其返回为Python字符串。
读取PDF文件
import PyPDF2
from PyPDF2.pdf import PageObject
reader = PyPDF2.PdfFileReader('XGBOOST.pdf')
writer = PyPDF2.PdfFileWriter()
for page_num in range(reader.numPages):
current_page = reader.getPage(page_num)
current_page.rotateClockwise(90)
writer.addPage(current_page)
writer.addBlankPage()
with open('XGBOOS-newT.pdf', 'wb') as file:
writer.write(file)
加密PDF文件
import PyPDF2
reader = PyPDF2.PdfFileReader('XGBoost.pdf')
writer = PyPDF2.PdfFileWriter()
for page_num in range(reader.numPages):
writer.addPage(reader.getPage(page_num))
writer.encrypt('foobared')
with open('XGBoost_encrypted.pdf', 'wb') as file:
writer.write(file)
我们还可以将上面的代码封装在一个函数里面
def encrypt_all(path, name, ept):
"""
给PDF文件加密
:param path: 文件路劲
:param name: 文件名
:param ept: 加密密码
:return: 返回加密后的新文件
"""
reader = PyPDF2.PdfFileReader(f'{path}/{name}.pdf')
writer = PyPDF2.PdfFileWriter()
for page_num in range(reader.numPages):
writer.addPage(reader.getPage(page_num))
writer.encrypt(ept)
with open(f'{path}/{name}_encrypted.pdf', 'wb') as file:
writer.write(file)
创建PDF文件
这里我们需要用到一个三方库:reportlab
from reportlab.lib.pagesizes import A4
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfgen import canvas
pdfmetrics.registerFont(TTFont('Font1', 'fonts/Vera.ttf'))
pdfmetrics.registerFont(TTFont('Font2', 'fonts/IPix中文像素字体.ttf'))
pdf_canvas = canvas.Canvas('demo.pdf', pagesize = A4)
width, height = A4
image = canvas.ImageReader('guido.jpg')
pdf_canvas.drawImage(image, 20, height - 375, 250, 375)
pdf_canvas.showPage()
pdf_canvas.setFont('Font2', 40)
pdf_canvas.setFillColorRGB(1, 0, 0, 1)
pdf_canvas.drawString(width // 4 , height // 4, '我吕布天下无敌啊!')
pdf_canvas.setFont('Font1', 40)
pdf_canvas.setFillColorRGB(0, 1, 0, 0.5)
pdf_canvas.rotate(18)
pdf_canvas.drawString(200, 280, 'nothing can defeat you')
pdf_canvas.save()
添加水印
import PyPDF2
from PyPDF2.pdf import PageObject
reader1 = PyPDF2.PdfFileReader('XGBoost.pdf')
reader2 = PyPDF2.PdfFileReader('watermark.pdf')
writer = PyPDF2.PdfFileWriter()
watermark_page = reader2.getPage(0)
for page_num in range(reader1.numPages):
current_page = reader1.getPage(page_num)
current_page.mergePage(watermark_page)
writer.addPage(current_page)
with open('resources/XGBoost-watermarked.pdf', 'wb') as file:
writer.write(file)
知识补充:获取文件夹下所有内容
import os
path = 'D:\\pycharm_DATA\\code\\day19'
files_list = os.listdir(path)
for file in files_list:
fullpath = os.path.abspath(file)
print(fullpath)
正则表达式
查找符合某些复杂规则的字符串时,比如在编写处理字符串的程序或网页时,就需要正则表达式来给我筛选我们想要的内容。简单来说,就是正则表达式指一种匹配字符串的模式,功能非常强大,但是它的匹配模式也很复杂。这里我推荐大家去阅读这篇文字,里面所说非常详细[正则表达式30分钟入门教程](正则表达式30分钟入门教程 (deerchao.cn))
基本符号
符号 | 解释 | 示例 | 说明 |
---|
. | 匹配任意字符 | b.t | 可以匹配bat / but / b#t / b1t等 | \w | 匹配字母/数字/下划线 | b\wt | 可以匹配bat / b1t / b_t等 但不能匹配b#t | \s | 匹配空白字符(包括\r、\n、\t等) | love\syou | 可以匹配love you | \d | 匹配数字 | \d\d | 可以匹配01 / 23 / 99等 | \b | 匹配单词的边界 | \bThe\b | | ^ | 匹配字符串的开始 | ^The | 可以匹配The开头的字符串 | $ | 匹配字符串的结束 | .exe$ | 可以匹配.exe结尾的字符串 | \W | 匹配非字母/数字/下划线 | b\Wt | 可以匹配b#t / b@t等 但不能匹配but / b1t / b_t等 | \S | 匹配非空白字符 | love\Syou | 可以匹配love#you等 但不能匹配love you | \D | 匹配非数字 | \d\D | 可以匹配9a / 3# / 0F等 | \B | 匹配非单词边界 | \Bio\B | | [] | 匹配来自字符集的任意单一字符 | [aeiou] | 可以匹配任一元音字母字符 | [^] | 匹配不在字符集中的任意单一字符 | [^aeiou] | 可以匹配任一非元音字母字符 | * | 匹配0次或多次 | \w* | | + | 匹配1次或多次 | \w+ | | ? | 匹配0次或1次 | \w? | | {N} | 匹配N次 | \w{3} | | {M,} | 匹配至少M次 | \w{3,} | | {M,N} | 匹配至少M次至多N次 | \w{3,6} | | | | 分支 | foo|bar | 可以匹配foo或者bar | (?#) | 注释 | | | (exp) | 匹配exp并捕获到自动命名的组中 | | | (?<name>exp) | 匹配exp并捕获到名为name的组中 | | | (?:exp) | 匹配exp但是不捕获匹配的文本 | | | (?=exp) | 匹配exp前面的位置 | \b\w+(?=ing) | 可以匹配I’m dancing中的danc | (?<=exp) | 匹配exp后面的位置 | (?<=\bdanc)\w+\b | 可以匹配I love dancing and reading中的第一个ing | (?!exp) | 匹配后面不是exp的位置 | | | (?<!exp) | 匹配前面不是exp的位置 | | | *? | 重复任意次,但尽可能少重复 | a.*b
a.*?b | 将正则表达式应用于aabab,前者会匹配整个字符串aabab,后者会匹配aab和ab两个字符串 | +? | 重复1次或多次,但尽可能少重复 | | | ?? | 重复0次或1次,但尽可能少重复 | | | {M,N}? | 重复M到N次,但尽可能少重复 | | | {M,}? | 重复M次以上,但尽可能少重复 | | |
re 模块
python还提供 re 模块来支持正则表达式个各种操作,下面是 re 模块中的一些重要函数
函数 | 说明 |
---|
compile(pattern, flags=0) | 编译正则表达式返回正则表达式对象 | match(pattern, string, flags=0) | 用正则表达式匹配字符串 成功返回匹配对象 否则返回None | search(pattern, string, flags=0) | 搜索字符串中第一次出现正则表达式的模式 成功返回匹配对象 否则返回None | split(pattern, string, maxsplit=0, flags=0) | 用正则表达式指定的模式分隔符拆分字符串 返回列表 | sub(pattern, repl, string, count=0, flags=0) | 用指定的字符串替换原字符串中与正则表达式匹配的模式 可以用count 指定替换的次数 | fullmatch(pattern, string, flags=0) | match 函数的完全匹配(从字符串开头到结尾)版本 | findall(pattern, string, flags=0) | 查找字符串所有与正则表达式匹配的模式 返回字符串的列表 | finditer(pattern, string, flags=0) | 查找字符串所有与正则表达式匹配的模式 返回一个迭代器 | purge() | 清除隐式编译的正则表达式的缓存 | re.I / re.IGNORECASE | 忽略大小写匹配标记 | re.M / re.MULTILINE | 多行匹配标记 |
实例
实例1:判断用户名、QQ号码、手机号码是否有效
import re
username = input('请输入用户名: ')
matcher = re.match(r'^\w{6,20}$', username)
if matcher is None:
print('无效用户名')
else:
print(matcher)
print(matcher.group())
"""
# 判断QQ号是否有效
qq = input('请输入QQ号: ')
matcher = re.match(r'[1-9]\d{4,}', qq)
if matcher is None:
print('无效QQ')
else:
print(matcher)
print(matcher.group())
"""
"""
# 判断手机号码是否有效
telephone = input('请输入手机号码: ')
matcher = re.match(r'1[3-9]\d{9}$', telephone)
if matcher is None:
print('无效手机号码')
else:
print(matcher)
print(matcher.group())
"""
实例2:从字符串中提取跟正则表达式匹配的部分
import re
content = """报警电话:110,我们班是Python-2105班,
我的QQ号是123456789,我的手机号是98765432104,谢谢!"""
pattern = re.compile(r'\d+')
matcher = pattern.search(content)
while matcher:
print(matcher.group())
print(matcher.start(), matcher.end())
matcher = pattern.search(content, matcher.end())
results = pattern.findall(content)
for result in results:
print(result)
results = re.findall(r'\d+', content)
for result in results:
print(result)
实例3:正则表达式捕获组
import re
import requests
pattern = re.compile(r'<a\s.*?href="(.+?)".*?title="(.+?)".*?>')
resp = requests.get('https://www.sohu.com/')
results = pattern.findall(resp.text)
for href, title in results:
print(title)
print(href)
实例4:过滤不良内容
import re
content = '马化腾是一个沙雕煞笔,FUck you!'
pattern = re.compile(r'[傻沙煞][逼笔雕鄙]|笨蛋|fuck|shit', flags=re.IGNORECASE)
modified_content = pattern.sub('*', content)
print(modified_content)
实例5:正则表达式拆分字符串
import re
poem = '窗前明月光,疑是地上霜。举头望明月,低头思故乡。'
pattern = re.compile(r'[,。]')
sentences_list = pattern.split(poem)
print(sentences_list)
sentences_list = [sentence for sentence in sentences_list if sentence]
print(sentences_list)
for sentence in sentences_list:
print(sentence)
|