word vba 压缩照片_Python加密有敏感信息的Word/Excel等文件

cc50ce7bf5ab2da87f94dede30f75953.png

① 目的

  1. 电脑使用时间长,保存了极多的WORD与EXCEL文件
  2. 文件版本不同(.doc .docx .xls .xlsx ......)
  3. 文件内保存有重要的身份信息(身份证号、手机号......)
  4. 要求所有包含身份信息的wd和xl文件进行加密操作

② 代码(version: 3.8.1)

#1 遍历所有文档

import psutil
import xlrd
import os
import itertools
import re
import time
import win32com.client
from typing import Generator, Any
from itertools import product

def fp_generator():
    # 导出所有文件路径
    for disk in [device[0] for device in psutil.disk_partitions()][::-1]:  # 获得电脑所有磁盘名称
        for root, dirs, files in os.walk(disk):
            for file in files:
                yield os.path.join(root, file)

#2 获取Word与Excel文件的内容

def excel_values(path) -> Generator[str, Any, Any]:
    # 获得所有EXCEL单元格(文本&数字)内容
    try:
        with xlrd.open_workbook(path) as wb:
            for sheet in wb.sheets():
                for x, y in itertools.product(range(sheet.ncols), range(sheet.nrows)):
                    cell = sheet.cell(y, x)
                    if cell.ctype == 1:
                        yield cell.value
                    elif cell.ctype == 2:
                        yield str(int(cell.value))
    except:
        pass


def word_values(path) -> Generator[str, Any, Any]:
    # 获得所有WORD段落、表格的内容
    try:
        word_app = win32com.client.Dispatch("Word.Application")
        word_app.Visible = 0
        word_app.DisplayAlerts = 0
        doc = word_app.Documents.Open(path, False, False, False, '8888aGa8332c9')
    except:
        return  # 捕获异常说明密码不对或者无密码,return终止生成器
    try:
        for para in doc.Paragraphs:
            yield para.Range.text
        doc.Close()
        word_app.Quit()
    except:
        return
    time.sleep(0.5)  # 不要删除,不要删除


map_get_values = {'.xls': excel_values,
                  '.doc': word_values}


def get_values(path) -> Generator[str, Any, Any]:
    global map_get_values
    for file_type, func in map_get_values.items():
        if file_type in os.path.splitext(path)[1]:
            print(f'正在查看:t{path}')
            return func(path)
    else:
        return (x for x in range(0))  # Generator

#3 判断是否含有客户身份私密信息(身份证号、手机号......)

def is_private(value: str) -> bool:
    # 若值的内容包含手机号或身份证号号,返回TRUE
    try:  
        if re.search(r'1((3[d])|(4[75])|(5[^3|4])|(66)|(7[013678])|(8[d])|(9[89]))d{8}', value) or re.search(
                r'[1-9]d{5}(18|19|20)d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|[1-3]0|31)d{3}[0-9xX]',
                value):
            return True
    except:
        pass

#4 word&excel 加密

# 相关参数:https://docs.microsoft.com/zh-CN/office/vba/api/Excel.Workbooks.Open
def try_several_times(func):
    def wrapper(*args, **kwargs):
        for i in range(100):
            try:
                func(*args, **kwargs)
                break
            except:
                print('something wrong')
        return func
    return wrapper


def excel_encryption(path, password):
    # 将EXCEL文件打开,并加密保存
    @try_several_times
    def encryption(fp, pw):
        excel_app = win32com.client.Dispatch('Excel.Application')
        excel_app.Visible = 0
        excel_app.DisplayAlerts = 0
        wb = excel_app.Workbooks.Open(fp, False, False, None, Password='')
        wb.SaveAs(fp, None, pw, '')
        wb.Close()
        excel_app.Quit()

    encryption(path, password)
    time.sleep(0.5)


def word_encryption(path, password):
    # 若加密保存.docx时,覆盖原文件,则无法成功添加密码。但是保存为另一个文件名,则可以添加密码。
    # 因此将A存为B,删A,再将B改为A。实在没办法,只能这样了 o(╥﹏╥)o
    # win32com操作word简直一言难尽
    dirname, tempname = os.path.split(path)
    path_temp = os.path.join(dirname, tempname)
    while os.path.exists(path_temp):
        tempname = f'{len(tempname)}' + tempname
        path_temp = os.path.join(dirname, tempname)

    # 海象牙操作符: while os.path.exists(path_temp := os.path.join(dirname, tempname := f'{len(tempname)}' + tempname)): pass

    @try_several_times
    def encryption(fp, pt, pw):
        word_app = win32com.client.Dispatch('Word.Application')
        word_app.Visible = 0
        word_app.DisplayAlerts = 0
        doc = word_app.Documents.Open(fp, False, False, False, '1')
        doc.SaveAs2(pt, None, False, pw)
        doc.Close()
        word_app.Quit()

    encryption(path, path_temp, password)
    os.remove(path)  # 删除原文件
    os.rename(path_temp, path)  # 改临时文件名称为原文件名称
    time.sleep(0.5)  # 不要删除,不要删除


map_encrption = {'.xls': excel_encryption,
                 '.doc': word_encryption}


def encryption(fp, pw):
    global map_encrption
    for file_type, func in map_encrption.items():
        if file_type in os.path.splitext(fp)[1]:
            func(fp, pw)
            print(f'正在加密:t{fp}')

#5 输入要设置的密码+运行逻辑

if __name__ == '__main__':
    # 设置6位数字密码
    while 1:
        password = input("输入6位数字密码:")
        password1 = input("确认6位数字密码:")
        if not (len(password) == len(password) == 6 and password.isdigit() == password1.isdigit() == True):
            print('n格式错误,重新输入')
        elif not password == password1:
            print('n两次密码不一致,重新输入')
        else:
            break

    # 主体逻辑
    for fp in fp_generator():
        for value in get_values(fp):
            if is_private(value):
                encryption(fp, password)
                break

③后续

  1. 单位要突击检查我们基层电脑中含有客户信息的文件是否全部设置密码,有没有进行保护。但是电脑使用时间太久,经手太多人,换人办公又不配备新电脑+新账号,不设置新计算机环境。以防疏漏,写此程序争取万无一失,不被通报批评。
  2. 仍可以完善,比如看看能不能检测PDF等常用格式并加密。而且若压缩包内存在需要加密的文件,也许会报错,还没有测试。
  3. 代码各个部分单独挑出来也蛮有用的,涉及到读取判断保存等内容。以此做个记录,以后忘了来这儿找找回忆回忆。
  4. 代码比较丑陋,但是也没有什么好的办法,似乎win32com给的接口不是很给力。而且调用了不少库,大杂烩啊这是。
  5. 过程还是不容易呀,又是生成器,又是装饰器,理解不少新知识。好在完成了大部分目的,可以鸣金收兵了 ^_^
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值