PDFやexcelをPWリストから解除、上書き保存、開く

投稿者: | 2022-11-13
import sys
import pathlib 
from pikepdf import Pdf
import subprocess
import logging
import win32com.client

'''
pikepdf:
    https://pikepdf.readthedocs.io/en/latest/topics/pages.html
'''

# TODO:PWなしファイルであった場合?
# TODO:PWがヒットしなかった場合?→手動入力or終了

logging.basicConfig(level=logging.DEBUG, format='%(asctime)s:%(levelname)s: %(message)s')

if len(sys.argv) > 1:
    before_file = sys.argv[1]
else:
    print('no argv')

bf = pathlib.Path(before_file)
logging.info(f'保存場所:{bf}')

suffix = bf.suffix
logging.info(f'拡張子:{suffix}')

# TODO:拡張子が「pdf または xlsx,xslm」だったら処理を分岐する

pw_list = ['aaa', 'bbb', 'pdf']

is_match = False
for pw in pw_list:
    try:
        # 変更前のPDF(PWあり)を開き、格納する
        before_pdf = Pdf.open('/Users/mbp441/Desktop/sample.pdf', password=pw)
    except:
        # PW相違の場合はMSG表示後、ループに戻る
        logging.info(f'PW_NG:{pw!r}')
    else:
        is_match = True
        logging.info(f'PW_OK:{pw!r}')
        break

if is_match:

    # 変更後用に新規PDFを作成し、変更前のPDFデータを流し込む
    after_pdf = Pdf.new()
    after_pdf.pages.extend(before_pdf.pages)

    # 変更後のPDFを保存する(PWなし)
    after_pdf_name = bf.stem + "_PW解除済み" + bf.suffix
    after_pdf_path = bf.parent / after_pdf_name
    after_pdf.save(after_pdf_path)

    logging.info(f'PW解除済みのファイルを保存しました: {after_pdf_path}')

    #pdfを開く(確認用)
    # Mac:open、Win:start(Winの場合は、Popenの引数として、shell=Trueが必要)
    subprocess.Popen(['open', after_pdf_path])

else:
    print('既存のPWでは開きません。またはPWがかかってないファイルです。')
    print('手動で確認してください。処理を終了します。')


こちらが最新版(テスト前)

'''
PWありのPDF,Excelファイルを開き、PWなしで別名保存するスクリプト

cf) pikepdf : https://pikepdf.readthedocs.io/en/latest/#
'''

import logging
import pathlib 
from pikepdf import Pdf
import subprocess
import sys

formatter = '%(levelname)s:%(asctime)s:%(name)s: %(message)s'

logging.basicConfig(
  level=logging.INFO,
  format=formatter,
  datefmt='%F %H:%M:%S')

# パスワードのリスト(新規があればリストに追加する)
pw_list = ['abc', '123', 'pdf']

# PDFバージョン(PWありPDFを開き、PWなしで別名で保存する関数)
def unlock_pdf(bf):

    is_match = False
    for pw in pw_list:
        try:
            bf_pdf = Pdf.open(bf, password=pw)
        except:
            logging.info(f'PW_NG:{pw!r}')
        else:
            is_match = True
            logging.info(f'PW_OK:{pw!r}')
            break

    if is_match:

        # 変更後用に新規PDFを作成し、変更前のPDFデータを流し込む
        af_pdf = Pdf.new()
        af_pdf.pages.extend(bf_pdf.pages)

        # 変更後のPDFを保存する(PWなし)
        af_pdf_name = bf.stem + "_PW解除済み" + bf.suffix
        af_pdf_path = bf.parent / af_pdf_name
        af_pdf.save(af_pdf_path)

        logging.info(f'PW解除済みのファイルを保存しました: {af_pdf_path}')

        #pdfを開く(確認用)
        # Mac:open、Win:start(Winの場合は、Popenの引数として、shell=Trueが必要)
        subprocess.Popen(['start', af_pdf_path], shell=True)

    else:
        print('既存のPWでは開きません。またはPWがかかってないファイルです。')
        print('手動で確認してください。処理を終了します。')


# Excelバージョン(PWありexcelを開き、PWなしで別名で保存する関数)
def unlock_excel(bf):

    af_excel_name = bf.stem + "_PW解除済み" + bf.suffix
    af_excel_path = bf.parent / af_excel_name
    
    is_match = False # TODO:ExcelVerはこれは不要か。
    for pw in pw_list:
        try:
            bf_excel = win32com.client.Dispatch('Excel.Application')
            book = bf_excel.Workbooks.Open(bf, False, False, None, pw)
            book.SaveAs(af_excel_path, 51, '')
            book.Close()
            bf_excel.Quit()
            logging.info(f'PW解除済みのファイルを保存しました: {af_excel_path}')
            # ファイルを開く
            subprocess.Popen(['start', af_excel_path], shell=True)
        except:
            logging.info(f'PW_NG:{pw!r}')
        else:
            is_match = True
            logging.info(f'PW_OK:{pw!r}')
            break

def main():
    
    logging.info(f'ファイルを実行:{sys.argv[0]}')

    if len(sys.argv) > 1:
        before_file = sys.argv[1]
        logging.info(f'対象ファイル:{before_file.name}')
    else:
        logging.info('対象ファイルがありません。処理を中断します')
        sys.exit

    bf = pathlib.Path(before_file)

    suffix = bf.suffix

    if suffix == 'pdf':
      unlock_pdf(bf)
    elif suffix == 'xlsx':
      unlock_excel(bf)
    else:
      print('pdf,xlsx以外です。処理を中断します')
      sys.exit


if __name__ == '__main__':
    main()