TutorBot / doc_preproc.py
erokou's picture
on going
61cb8cf
Raw History Blame Contribute Delete
4.82 kB
import os
import shutil
import sys
import logging
from datetime import datetime
# Set up logging
logging.basicConfig(
filename=f"conversion_log_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log",
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
)
# For DOC/DOCX conversion
try:
from docx2pdf import convert as docx_convert
except ImportError:
logging.error("docx2pdf not installed. Run 'pip install docx2pdf'.")
sys.exit(1)
# For Word-based conversion
try:
import win32com.client
except ImportError:
logging.error("pywin32 not installed. Run 'pip install pywin32'.")
sys.exit(1)
try:
import comtypes.client
except ImportError:
logging.warning("comtypes not installed. Run 'pip install comtypes' for fallback.")
def check_irm_status(filepath):
"""Check if IRM is enabled on a DOC/DOCX file."""
try:
word_app = win32com.client.Dispatch("Word.Application")
doc = word_app.Documents.Open(os.path.abspath(filepath), ReadOnly=True, Visible=False)
irm_enabled = doc.Permission.Enabled
doc.Close()
word_app.Quit()
return irm_enabled
except Exception as e:
logging.error(f"Failed to check IRM for {filepath}: {e}")
return None
def convert_docx_docx2pdf(filepath, output_pdf):
"""Attempt DOC/DOCX to PDF conversion using docx2pdf."""
try:
docx_convert(filepath, output_pdf)
logging.info(f"Converted {filepath} to {output_pdf} using docx2pdf.")
return True
except Exception as e:
logging.error(f"docx2pdf failed for {filepath}: {e}")
return False
def convert_docx_win32(filepath, output_pdf):
"""Attempt DOC/DOCX to PDF conversion using win32com SaveAs."""
try:
word_app = win32com.client.Dispatch("Word.Application")
doc = word_app.Documents.Open(os.path.abspath(filepath), ReadOnly=True, Visible=False)
doc.SaveAs(output_pdf, FileFormat=17) # 17 = wdFormatPDF
doc.Close()
word_app.Quit()
logging.info(f"Converted {filepath} to {output_pdf} using win32com SaveAs.")
return True
except Exception as e:
logging.error(f"win32com SaveAs failed for {filepath}: {e}")
return False
def convert_docx_comtypes(filepath, output_pdf):
"""Attempt DOC/DOCX to PDF conversion using comtypes SaveAs."""
try:
word_app = comtypes.client.CreateObject("Word.Application")
doc = word_app.Documents.Open(os.path.abspath(filepath), ReadOnly=True, Visible=False)
doc.SaveAs(output_pdf, FileFormat=17) # 17 = wdFormatPDF
doc.Close()
word_app.Quit()
logging.info(f"Converted {filepath} to {output_pdf} using comtypes SaveAs.")
return True
except Exception as e:
logging.error(f"comtypes SaveAs failed for {filepath}: {e}")
return False
def main(input_dir, output_dir):
if not os.path.isdir(input_dir):
logging.error(f"{input_dir} is not a directory.")
sys.exit(1)
os.makedirs(output_dir, exist_ok=True)
for root, _, files in os.walk(input_dir):
rel_dir = os.path.relpath(root, input_dir)
target_subdir = os.path.join(output_dir, rel_dir)
os.makedirs(target_subdir, exist_ok=True)
for file in files:
filepath = os.path.join(root, file)
base, ext = os.path.splitext(file)
output_pdf = os.path.join(target_subdir, base + '.pdf')
try:
if ext.lower() in ['.doc', '.docx']:
# Check IRM status
irm_status = check_irm_status(filepath)
if irm_status is not None:
logging.info(f"IRM enabled for {filepath}: {irm_status}")
# Try docx2pdf first (simpler, faster)
if not convert_docx_docx2pdf(filepath, output_pdf):
# Fallback to win32com
if not convert_docx_win32(filepath, output_pdf):
# Fallback to comtypes if available
if 'comtypes' in sys.modules and not convert_docx_comtypes(filepath, output_pdf):
logging.warning(f"Failed to convert {filepath}. Likely IRM or strict restrictions.")
elif not 'comtypes' in sys.modules:
logging.warning(f"Failed to convert {filepath}. Install comtypes for additional fallback.")
elif ext.lower() == '.pdf':
shutil.copy(filepath, output_pdf)
logging.info(f"Copied {filepath} to {output_pdf}")
except Exception as e:
logging.error(f"Error processing {filepath}: {e}")
if __name__ == "__main__":
main("ToAdd", "ConvertedFiles")