玩命加载中🤣🤣🤣

Python办公自动化


Python办公自动化

依赖安装

pip install pandas
pip install openpyxl

文件夹与文件

几个demo

查找 d 盘中 包含 python-office 的文件, 并且格式化输出(并且通过时间时间做出过滤)

import os
import glob
import time
import json
from datetime import datetime

# 查找 d 盘中 包含 python-office 的文件, 并且格式化输出

os.chdir('d:/dee_code')
file_list = glob.glob('**/*python-office*.md', recursive=True)

# 自定义一些时间范围
start_date = datetime(2024, 1, 1)
end_date = datetime(2025, 12, 1)
start_timestamp = time.mktime(start_date.timetuple())
end_timestamp = time.mktime(end_date.timetuple())

# 使用推导式
file_info_list = [
    {
        'absolute_path': os.path.abspath(f),
        'file_size': os.stat(f).st_size / 1024 / 1024,
        'create_time': time.strftime('%Y-%m-%d', time.localtime(os.stat(f).st_ctime)),
        'modify_time': time.strftime('%Y-%m-%d', time.localtime(os.stat(f).st_mtime))
    }
    for f in file_list
    if start_timestamp <= os.stat(f).st_ctime <= end_timestamp
]

# 打印结果,为了美观和可读性,可以使用 json.dumps 来格式化输出
print(json.dumps(file_info_list, ensure_ascii=False, indent=4))

[
    {
        "absolute_path": "d:\\dee_code\\dee-blog-code\\source\\_posts\\python-office.md",
        "file_size": 0.00748443603515625,
        "create_time": "2025-01-02",
        "modify_time": "2025-01-04"
    }
]

补充说明:列表推导式的用法

# 通用语法
new_list = [expression for item in iterable]
# demo
absolute_file_list = [os.path.abspath(file) for file in list]
# 带条件的列表推导式
even_numbers = [x for x in range(10) if x % 2 == 0]
# 等价传统 for 循环
absolute_file_list = []
for file in list:
    absolute_file_list.append(os.path.abspath(file))

查找目标文件夹下空文件和重复文件

import hashlib
import os.path
import json


# 计算文件的 md5 哈希值
def calculate_file_hash(file_path):
    hasher = hashlib.md5()
    with open(file_path, 'rb') as f:
        while chunk := f.read(8192): # 每次读取 8kb 数据块
            hasher.update(chunk)
    return hasher.hexdigest()

# 查找文件夹中重复文件
def find_repeat_file(path):
    if not os.path.isdir(path):
        raise Exception('请输入文件夹路径')
    file_dic = {} # 存储文件哈希值和对应完整路径
    repeat_dic = {} # 存储重复文件的hash值和路径列表
    blank_file = []
    for dir_path, child_dir_path, file_list in os.walk(path):
        # 遍历文件
        for file_name in file_list:
            # 构建完整路径
            file_path = os.path.join(dir_path, file_name)
            if os.stat(file_path).st_size == 0:
                blank_file.append(file_path)
                continue
            # 计算文件哈希值
            file_hash = calculate_file_hash(file_path)
            # 如果文件夹字典中没有, 则添加
            if file_hash not in file_dic:
                file_dic[file_hash] = file_path
            # 否则把重复的文件添加进重复字典
            else:
                # 先判断字典中有没有该文件
                if file_hash not in repeat_dic:
                    repeat_dic[file_hash] = []
                    # 将第一次该文件名的首次查询出来的路径放进来
                    repeat_dic[file_hash].append(file_dic[file_hash])
                repeat_dic[file_hash].append(file_path)
    json_result = json.dumps(repeat_dic, ensure_ascii=False, indent=4)
    print(f'空文件列表 >>> {blank_file}')
    print(f'重复文件列表 \n {json_result}')


if __name__ == '__main__':
    find_repeat_file(r'D:\Admin\Desktop\test')

基础使用

import pandas as pd
import os

os.chdir(r'D:\Admin\Desktop') # 设置工作路径

data = pd.read_excel('测试.xlsx') # 读取excel文件
dir = os.getcwd() # 获取当前工作路径
print(data)

自动路径连接

import os

p1 = '\外路径'
p2 = '中路径'
p3 = '内路径'

path = os.path.join(p1, p2, p3)
print('c:', path) # c: \外路径\中路径\内路径

遍历文件夹

判断文件和文件夹

list = os.listdir()
file = []
dir = []

for i in list:
    if os.path.isdir(i): # 判断文件夹
        dir.append(i)
    else:
        file.append(i)

遍历目录

import os

for 文件 in os.scandir(): # 可以选择文件夹
    print(文件.name, 文件.path, 文件.is_dir()) # 文件名 文件路径 是否为文件夹
    print(文件.stat()) # 文件属性
# os.stat_result(st_mode=33206, st_ino=0, st_dev=0, st_nlink=0, st_uid=0, st_gid=0, st_size=233, st_atime=1735824570, st_mtime=1735824570, st_ctime=1735822544)

属性说明

名称 说明
st_size 文件的体积大小(单位:bytes), 除以 1024 就是 KB
st_atime 文件的最近访问时间
st_mtime 文件的最近修改时间
st_ctime windws 下创建时间
st_birthtime Mac、linux 下创建时间

时间戳转换

import time
import datetime as dt

print('创建时间', time.ctime(1735824570)) # Thu Jan  2 21:29:30 2025
print('创建时间', dt.datetime.fromtimestamp(1735824570)) # 2025-01-02 21:29:30

# 提取具体时间
print(time.year, time.month, time.day, time.hour, time.minute, time.second)

综合查询

import os
import re

dir = []
file = []

# 获取所有文件夹和文件
for i in os.scandir(r'D:\Admin\Downloads'):
    if i.is_dir():
        dir.append(i.name)
    else:
        file.append(i.name)
print(f'1)文件夹有{len(dir)}: {dir}')
print(f'2)文件有{len(file)}: {file}')

# 查找所有包含 typora 的文件
typora = []

for i in file:
    if 'typora' in i:
        typora.append(i)
print(f'3)包含typora的文件有{len(typora)}个: {typora}')

# 查找所有包含 git的文件(不区分大小写)
git = []
reg = '.*git.*'
for i in file:
    r = re.match(reg, i, re.I)
    try:
        git.append(r.group())
    except:
        pass
print(f'4)包含git的文件有{len(git)}个: {git}')

# 查找所有 excel
excel_list = []
for i in file:
    if i.endswith('.xlsx'):
        excel_list.append(i)
print(f'excel文件有{len(excel_list)}个: {excel_list}')

👍套娃遍历文件(os.walk() 函数)

import os

count = 0
# 文件夹路径:该目录下所有文件夹全路径, 子文件夹列表:文件夹路径下的所有子文件夹, 文件列表: 文件夹路径下的所有文件
for 文件夹路径, 子文件夹列表, 文件列表 in os.walk(r'D:\Admin\Downloads'):
    for i in 文件列表:
        print(文件夹路径 + '\\' + i)
        count += 1
print(f'找到{count}个文件')

搜索匹配文件名称

字符串内置的方法:startswith()endswith()

glob 模块

glob 是 python 自带的一个文件操作相关模块,用它可以查找符合自己要求的文件,类似于 Windows 下的文件搜索,支持通配符操作,有*?[] 这三个通配符,

*:代表0个或者多个字符;

?:代表一个字符;

[]:匹配指定范围内的字符,如[0-9]匹配数字;

主要有以下 2 个主要方法。

  • glob 方法
    • 该方法返回所有匹配的文件路径列表(list)
    • 该方法需要一个参数用来制定匹配的路径字符串(字符串可以为绝对路径也可以为相对路径)
    • 其返回文件名只包括当前目录里的文件名,不包括子文件夹里的文件
import os
import glob

os.chdir(r'D:\Admin\Desktop')
# print(glob.glob('*.txt'))
# print(glob.glob('test*.txt'))
# print(glob.glob('孙兴华.分析[0-9].*'))
# print(glob.glob('孙兴华.分析[!0-9].*'))
list = glob.glob('*.jpg')

print(list) # 返回一个列表
for f in list:
    print(f)

👍👍注意

'''遍历文件夹深层目录下所有的指定文件
'''
import os
import glob

os.chdir(r'D:\Admin\Desktop')
list = glob.glob('**/*.xlsx',recursive=True) # 注意:用**表示任意层文件或文件夹,recursive=True会不断进入文件夹内。查找该路径下面的所有.xlsx文件,包括深层的文件
print(list) 
  • iglob 方法(选记)
    • 获取一个可编历对象,使用它可以逐个获取匹配的文件路径名
    • glob.glob() 的区别是:glob.glob 同时获取所有的匹配路径,而 glob.iglob 一次只获取一个匹配路径
import os
import glob

os.chdir(r'D:\Admin\Desktop')
list = glob.iglob('*.jpg')
print(list)
for f in list:
    print(f)

fnmatch 模块

是否匹配,返回的是 True/False

import os
import fnmatch

# 是否匹配
dir = os.listdir('./')
for f in dir:
    if fnmatch.fnmatch(f, '*.txt'): # 匹配规则和 glob 一样
        print(f)

创建文件夹

import os

# 创建单层目录
def mkdir(dir):
    dir_name = os.path.basename(dir) # 返回路径的最后一个元素
    exist = os.path.exists(dir)
    if not exist:
        os.mkdir(dir)
        print(dir_name + "文件夹创建成功")
        return True
    else:
        print('目标已存在: ', dir_name)

def mkdirs(dir):
    exist = os.path.exists(dir)
    if not exist:
        os.makedirs(dir)
        print('目录创建成功')
        return True
    else:
        print('目录已存在')
        return False

if __name__ == '__main__':
    mkdir("./test")
    mkdirs('./ss/dd/cc')

操作文件,shutil 模块

判断模块有没有安装

import shutil
#执行会不会报错
import shutil
import os

origin_path = './test.txt'
target_path = './copy/test.txt'

shutil.copy(origin_path, target_path) # 复制文件 注意文件夹要保证存在
shutil.copy2(origin_path, target_path) # 原封不动的复制,包括创建时间和修改时间

origin_dir = './test_dir'
target_dir = './copy/test_dir'

shutil.copytree(origin_dir, target_dir) # 复制文件夹 注意不能是已经存在的文件夹

shutil.move(target_path, origin_path) # 移动文件/文件夹

shutil.rmtree('./ttest.txt') # 删除文件/文件夹

shutil.rename('./test.txt', './test/ttest.txt') # 改名同时进行移动

读写临时文件 TemporaryFile 模块

创建临时文件存储数据

from tempfile import TemporaryFile

with TemporaryFile('w+t') as tmp:
    tmp.write('Hello World\n')
    tmp.write('Testing\n')

    tmp.seek(0)
    print(tmp.readlines())

创建临时文件夹存储数据

from tempfile import TemporaryDirectory

# with 表达式 as 变量: 打开文件不用手动关闭, 但要注意缩进
with TemporaryDirectory() as tmpdir:
    print(f'临时文件夹是:{tmpdir}')

解压 zip 文件

读取压缩包

import zipfile

# 读取压缩包
with zipfile.ZipFile(r'D:\dee_file\20240805_重庆诉保\hujiao.zip') as f:
    for f_name in f.namelist():
        f_info = f.getinfo(f_name) # 根据文件名 获取文件信息
        print(f_name, f_info) # <ZipInfo filename='hujiao/log/all.log' compress_type=deflate filemode='-rw-rw-rw-' file_size=3878241 compress_size=129218>

解压单个文件

解压全部文件

import zipfile
import os

with zipfile.ZipFile(r'D:\dee_file\20240805_重庆诉保\hujiao.zip', 'r') as file:
    print(file)
    file.extractall(path=os.getcwd()) # 解压全部 (如果需要密码就额外指定参数 pwd=)

压缩文件

import os
import zipfile

# 压缩文件
def zipDir(dirPath, outFileName=None):
    '''
    :param dirPath: 目标文件或文件夹
    :param outFileName: 压缩文件名,默认和目标文件相同
    :return: none
    '''
    # 如果不校验文件也可以生成zip文件,但是压缩包内容为空,所以最好有限校验路径是否正确
    if not os.path.exists(dirPath):
        raise Exception("文件路径不存在:", dirPath)

    # zip文件名默认和被压缩的文件名相同,文件位置默认在待压缩文件的同级目录
    if outFileName == None:
        outFileName = dirPath + ".zip"

    if not outFileName.endswith("zip"):
        raise Exception("压缩文件名的扩展名不正确!因以.zip作为扩展名")

    zip = zipfile.ZipFile(outFileName, "w", zipfile.ZIP_DEFLATED)
    # 遍历文件或文件夹
    for path, dirnames, filenames in os.walk(dirPath):
        fpath = path.replace(dirPath, "")

        for filename in filenames:
            zip.write(os.path.join(path, filename), os.path.join(fpath, filename))
    zip.close()

if __name__ == "__main__":
    zipDir(r"C:\练习1")

pandas操作Excel

写入

import pandas as pd
import os

path = os.path.join(os.getcwd(), 'test.xlsx')
data = pd.DataFrame({'姓名': ['张三', '李四', '王五'], '年龄': [18, 19, 20]})
data = data.set_index('姓名') # 设置索引列
data.to_excel(path)
print('新建xlsx成功')

读取与修改

读取csv

import os
import pandas as pd

# 新建
path = os.path.join(os.getcwd(), 'tmp.csv')
# data = pd.DataFrame({'姓名': ['张三', '李四', '王五'], '年龄': [18, 19, 20]})
# data = data.set_index('姓名') # 设置索引列
# data.to_csv(path)

# 读取
# data = pd.read_csv(path)
data = pd.read_table(path, sep=',', nrows=3) # 使用read_table()的时候要指定分隔符, 如果有,和\t 要用正则
print(data) # 指定行数
print(data.shape) # 该表有几行几列 (3, 2)
print(data.columns) # 列名 Index(['姓名', '年龄'], dtype='object')
print(data.dtypes) #

读取xlsx

import pandas as pd

path = os.path.join(os.getcwd(), 'tmp.xlsx')
data = pd.readz-excel(path)
# 如果excel没有表头
data = pd.read_excel(path, header=None, names=['序号', '姓名', '年龄'])

# 排序
print(data.sort_values('年龄'))
# 查看是否为空
print(data.isnull())

# 修改
data.to_excel(path)

pandas数据结构

DataFrame:二维数据,整个表格,多行多列 【简称df】

df.index:索引列

df.columns:列名

Series:一维数据,一行或一列

Series

import pandas as pd

# 默认索引列 0,1,2,3
data = pd.Series([520, '张三', 1314, '2024-01-02'])
print(data)

# 指定索引列
data2 = pd.Series(['张三', 18, '2024-01-02'], index=['姓名', '年龄', '日期'])
print(data2)

# 使用python字典创建series
dic = pd.Series({'姓名': '张三', '性别': '男', '年龄': 18})
data3 = pd.Series(dic)
print(data3)
print(f'查询单个索引值 >>> 姓名: {data3['姓名']}') # 查询具体索引的值
print(f'查询多个索引值 >>> 姓名, 性别: {data3[['姓名', '性别']]}') # 查询多个值

DataFrame

DataFrame 的创建

import pandas as pd

data = pd.DataFrame([[1,2,3], [4,5,6], [7,8,9]], columns=['a','b','c'])
print(data)
print(data['a'][0]) # 取a列0行
print(data.loc[0]['a']) # 取a列0行
print(data.iloc[0][0]) # 与列无关, 只取坐标

# 查询多列数据
print(data[['a', 'b']]) # 拿a列和b列

根据字典创建 DataFrame

import pandas as pd

data_dic = {
    '姓名': ['张三', '李四', '王五'],
    '性别': ['男', '女', '男'],
    '年龄': [18, 19, 20]
}

data = pd.DataFrame(data_dic)
print(data)
print(data.dtypes) # 查看列类型
print(data.columns) # 查看列
print(data.index) # 查看索引
print(data['姓名']) # 查看【姓名】列以及对应的值
print(data.loc[1]) # 查看第[1]行数据
print(data.loc[1]['姓名']) # 查看第[1]行的姓名
print(data[['姓名', '年龄']]) # 查看多列以及对应的值
print(data.loc[1:2]) # 查看多行的值

根据多个 series 创建 DataFrame(不常见)

DataFrame 常用方法👍


文章作者: 👑Dee👑
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 👑Dee👑 !
  目录