Created
May 6, 2025 21:42
-
-
Save me-suzy/1639167b6e488f03a23c64e91d619300 to your computer and use it in GitHub Desktop.
convert rtf to pdf 3.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import subprocess | |
import psutil | |
import win32com.client | |
from PyPDF2 import PdfReader, PdfWriter | |
import pikepdf | |
import logging | |
import tempfile | |
import shutil | |
import ctypes | |
import time | |
import threading | |
import json # Adăugat pentru a salva dicționarul în JSON | |
# Configurare logging | |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') | |
# Specificați căile complete pentru utilitarele externe | |
WKHTMLTOPDF_PATH = r"c:\Program Files (x86)\wkhtmltopdf\bin\wkhtmltopdf.exe" | |
EBOOK_CONVERT_PATH = r"C:\Program Files\Calibre2\ebook-convert.exe" | |
DDJVU_PATH = r"c:\Program Files (x86)\DjVuLibre\ddjvu.exe" | |
LIBREOFFICE_PATH = r"D:\Program Files\LibreOffice\program\soffice.exe" # Calea către LibreOffice | |
# Creare lock pentru conversiile Word (poate fi eliminat dacă nu mai folosim Word) | |
word_conversion_lock = threading.Lock() | |
def is_admin(): | |
try: | |
return ctypes.windll.shell32.IsUserAnAdmin() | |
except: | |
return False | |
def kill_word_processes(): | |
"""Închide toate procesele Word rămase active.""" | |
try: | |
for proc in psutil.process_iter(['name']): | |
if proc.info['name'] in ['WINWORD.EXE', 'OfficeClickToRun.exe', 'SDXHelper.exe']: | |
try: | |
proc.kill() | |
except: | |
pass | |
time.sleep(2) # Așteaptă să se închidă procesele | |
except: | |
pass | |
def check_and_close_office_processes(): | |
processes_to_close = ["OfficeClickToRun.exe", "SDXHelper.exe", "WINWORD.EXE"] | |
for proc_name in processes_to_close: | |
for proc in psutil.process_iter(['name']): | |
if proc.info['name'] == proc_name: | |
try: | |
proc.terminate() | |
proc.wait(timeout=10) | |
logging.info(f"Procesul {proc_name} a fost închis.") | |
except psutil.TimeoutExpired: | |
try: | |
proc.kill() | |
logging.info(f"Procesul {proc_name} a fost închis forțat.") | |
except psutil.AccessDenied: | |
if is_admin(): | |
logging.error(f"Nu s-a putut închide procesul {proc_name} chiar cu drepturi de administrator.") | |
else: | |
logging.warning(f"Nu s-a putut închide procesul {proc_name}. Încercați să rulați scriptul ca administrator.") | |
except Exception as e: | |
logging.error(f"Eroare la închiderea procesului {proc_name}: {str(e)}") | |
time.sleep(2) | |
if psutil.pid_exists(proc.pid): | |
logging.warning(f"Procesul {proc_name} încă rulează. Continuăm cu avertisment.") | |
else: | |
logging.info(f"Procesul {proc_name} a fost închis cu succes.") | |
def modify_trust_center_settings(word_app, enable_protected_view=False, enable_file_block=False): | |
pass # Funcția nu mai este necesară, dar o păstrez goală pentru compatibilitate | |
def convert_with_libreoffice(input_file, output_file, conversion_type): | |
""" | |
Funcție unificată pentru conversiile LibreOffice (DOC, DOCX, RTF) | |
""" | |
try: | |
# Verifică dacă LibreOffice este disponibil | |
if not os.path.exists(LIBREOFFICE_PATH): | |
logging.error(f"LibreOffice nu a fost găsit la {LIBREOFFICE_PATH}") | |
raise Exception("LibreOffice nu este instalat sau calea este incorectă") | |
# Construiește comanda pentru conversie | |
command = [ | |
LIBREOFFICE_PATH, | |
"--headless", | |
"--convert-to", "pdf", | |
"--outdir", os.path.dirname(output_file), | |
input_file | |
] | |
logging.info(f"Începe conversia {conversion_type}: {input_file} -> {output_file}") | |
start_time = time.time() | |
result = subprocess.run(command, capture_output=True, text=True, check=True, timeout=120) | |
logging.info(f"Conversia finalizată în {time.time() - start_time:.2f} secunde") | |
logging.info("Ieșire comandă:", result.stdout) | |
if result.stderr: | |
logging.warning("Erori comandă:", result.stderr) | |
# Verifică dacă fișierul PDF a fost creat | |
temp_pdf_name = os.path.splitext(os.path.basename(input_file))[0] + ".pdf" | |
temp_pdf_path = os.path.join(os.path.dirname(output_file), temp_pdf_name) | |
if os.path.exists(temp_pdf_path) and temp_pdf_path != output_file: | |
shutil.move(temp_pdf_path, output_file) | |
if os.path.exists(output_file): | |
logging.info(f"Conversie {conversion_type} reușită: {input_file} -> {output_file}") | |
else: | |
raise Exception(f"Fișierul PDF nu a fost creat pentru {input_file}") | |
except subprocess.CalledProcessError as e: | |
logging.error(f"Eroare la conversia {conversion_type}: {input_file}. Detalii: {e.stderr}") | |
raise | |
except Exception as e: | |
logging.error(f"Eroare neașteptată la conversia {conversion_type}: {input_file}. Detalii: {str(e)}") | |
raise | |
def convert_doc_to_pdf(input_file, output_file): | |
convert_with_libreoffice(input_file, output_file, "DOC") | |
def convert_docx_to_pdf(input_file, output_file): | |
convert_with_libreoffice(input_file, output_file, "DOCX") | |
def convert_rtf_to_pdf(input_file, output_file): | |
convert_with_libreoffice(input_file, output_file, "RTF") | |
def convert_epub_to_pdf(input_file, output_file): | |
try: | |
subprocess.run([EBOOK_CONVERT_PATH, input_file, output_file], check=True, capture_output=True, text=True) | |
logging.info(f"Conversia EPUB la PDF reușită: {input_file} -> {output_file}") | |
except subprocess.CalledProcessError as e: | |
logging.error(f"Eroare la conversia EPUB la PDF: {input_file}. Detalii: {e.stderr}") | |
raise | |
except Exception as e: | |
logging.error(f"Eroare neașteptată la conversia EPUB la PDF: {input_file}. Detalii: {str(e)}") | |
raise | |
def convert_mobi_to_pdf(input_file, output_file): | |
try: | |
subprocess.run([EBOOK_CONVERT_PATH, input_file, output_file, | |
"--pdf-page-numbers", | |
"--paper-size", "a4", | |
"--pdf-add-toc", | |
"--margin-top", "72", | |
"--margin-right", "72", | |
"--margin-bottom", "72", | |
"--margin-left", "72"], | |
check=True, capture_output=True, text=True) | |
logging.info(f"Conversia MOBI la PDF reușită: {input_file} -> {output_file}") | |
except subprocess.CalledProcessError as e: | |
logging.error(f"Eroare la conversia MOBI la PDF: {input_file}. Detalii: {e.stderr}") | |
raise | |
except Exception as e: | |
logging.error(f"Eroare neașteptată la conversia MOBI la PDF: {input_file}. Detalii: {str(e)}") | |
raise | |
def convert_djvu_to_pdf(input_file, output_file): | |
try: | |
subprocess.run([DDJVU_PATH, '-format=pdf', input_file, output_file], check=True, capture_output=True, text=True) | |
logging.info(f"Conversia DJVU la PDF reușită: {input_file} -> {output_file}") | |
except subprocess.CalledProcessError as e: | |
logging.error(f"Eroare la conversia DJVU la PDF: {input_file}. Detalii: {e.stderr}") | |
raise | |
except Exception as e: | |
logging.error(f"Eroare neașteptată la conversia DJVU la PDF: {input_file}. Detalii: {str(e)}") | |
raise | |
def convert_lit_to_pdf(input_file, output_file): | |
try: | |
epub_file = tempfile.mktemp(suffix='.epub') | |
subprocess.run([EBOOK_CONVERT_PATH, input_file, epub_file], check=True, capture_output=True, text=True) | |
subprocess.run([EBOOK_CONVERT_PATH, epub_file, output_file, | |
"--pdf-page-numbers", | |
"--paper-size", "a4", | |
"--pdf-add-toc", | |
"--margin-top", "72", | |
"--margin-right", "72", | |
"--margin-bottom", "72", | |
"--margin-left", "72"], | |
check=True, capture_output=True, text=True) | |
os.remove(epub_file) | |
logging.info(f"Conversia LIT la PDF reușită: {input_file} -> {output_file}") | |
except subprocess.CalledProcessError as e: | |
logging.error(f"Eroare la conversia LIT la PDF: {input_file}. Detalii: {e.stderr}") | |
raise | |
except Exception as e: | |
logging.error(f"Eroare neașteptată la conversia LIT la PDF: {input_file}. Detalii: {str(e)}") | |
raise | |
def convert_txt_to_pdf(input_file, output_file): | |
try: | |
with open(input_file, 'r', encoding='utf-8') as file: | |
content = file.read() | |
html_content = f""" | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<style> | |
body {{ font-family: Arial, sans-serif; font-size: 12px; line-height: 1.6; }} | |
pre {{ white-space: pre-wrap; }} | |
</style> | |
</head> | |
<body> | |
<pre>{content}</pre> | |
</body> | |
</html> | |
""" | |
with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.html', encoding='utf-8') as temp_html: | |
temp_html.write(html_content) | |
temp_html_path = temp_html.name | |
subprocess.run([WKHTMLTOPDF_PATH, temp_html_path, output_file], check=True, capture_output=True, text=True) | |
os.remove(temp_html_path) | |
logging.info(f"Conversia TXT la PDF reușită: {input_file} -> {output_file}") | |
except subprocess.CalledProcessError as e: | |
logging.error(f"Eroare la conversia TXT la PDF: {input_file}. Detalii: {e.stderr}") | |
raise | |
except Exception as e: | |
logging.error(f"Eroare neașteptată la conversia TXT la PDF: {input_file}. Detalii: {str(e)}") | |
raise | |
def repair_and_reconvert_pdf(input_file, output_file): | |
try: | |
with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as temp_file: | |
temp_path = temp_file.name | |
with pikepdf.open(input_file, allow_overwriting_input=True) as pdf: | |
pdf.save(temp_path) | |
shutil.move(temp_path, output_file) | |
logging.info(f"PDF reparat cu succes folosind pikepdf: {input_file} -> {output_file}") | |
except Exception as e: | |
logging.error(f"Eroare la repararea PDF-ului cu pikepdf {input_file}: {str(e)}") | |
try: | |
reader = PdfReader(input_file) | |
writer = PdfWriter() | |
for page in reader.pages: | |
writer.add_page(page) | |
with open(temp_path, 'wb') as f: | |
writer.write(f) | |
shutil.move(temp_path, output_file) | |
logging.info(f"PDF reparat cu succes folosind PyPDF2: {input_file} -> {output_file}") | |
except Exception as e2: | |
logging.error(f"Eroare la repararea PDF-ului {input_file} cu PyPDF2: {str(e2)}") | |
raise | |
def pdf_exists(input_file, output_dir): | |
file_name = os.path.basename(input_file) | |
file_name_without_ext = os.path.splitext(file_name)[0] | |
pdf_file = os.path.join(output_dir, file_name_without_ext + '.pdf') | |
exists = os.path.exists(pdf_file) | |
if exists: | |
logging.info(f"PDF-ul există deja: {pdf_file}") | |
return exists | |
def try_alternative_conversion(input_file, output_file, conversion_type): | |
""" | |
Încercă metoda alternativă de conversie folosind LibreOffice pentru fișierele problematice. | |
""" | |
logging.info(f"Încercăm metoda alternativă de conversie pentru {input_file}") | |
try: | |
# Creăm un fișier temporar pentru a evita probleme cu fișierele blocate | |
temp_dir = tempfile.mkdtemp() | |
temp_file_name = os.path.basename(input_file) | |
temp_file_path = os.path.join(temp_dir, temp_file_name) | |
# Copiem fișierul în locația temporară | |
shutil.copy2(input_file, temp_file_path) | |
logging.info(f"Fișier copiat în locația temporară: {temp_file_path}") | |
# Metoda alternativă: Folosește LibreOffice | |
libreoffice_path = LIBREOFFICE_PATH | |
if os.path.exists(libreoffice_path): | |
logging.info(f"Încercăm conversia cu LibreOffice pentru {temp_file_path}") | |
cmd = [ | |
libreoffice_path, | |
"--headless", | |
"--convert-to", "pdf", | |
"--outdir", os.path.dirname(output_file), | |
temp_file_path | |
] | |
subprocess.run(cmd, check=True, capture_output=True, text=True, timeout=120) | |
# Verifică dacă s-a creat PDF-ul și redenumește-l dacă este necesar | |
temp_pdf_name = os.path.splitext(temp_file_name)[0] + ".pdf" | |
temp_pdf_path = os.path.join(os.path.dirname(output_file), temp_pdf_name) | |
if os.path.exists(temp_pdf_path) and temp_pdf_path != output_file: | |
shutil.move(temp_pdf_path, output_file) | |
if os.path.exists(output_file): | |
logging.info(f"Conversie alternativă reușită cu LibreOffice: {input_file} -> {output_file}") | |
return True | |
else: | |
logging.error(f"LibreOffice nu a fost găsit la {libreoffice_path}") | |
return False | |
# Curățare | |
try: | |
shutil.rmtree(temp_dir) | |
except: | |
pass | |
return False | |
except Exception as e: | |
logging.error(f"Eroare la conversia alternativă pentru {input_file}: {str(e)}") | |
return False | |
def convert_file(input_file, output_dir, problematic_files): | |
file_name = os.path.basename(input_file) | |
file_name_without_ext = os.path.splitext(file_name)[0] | |
output_file = os.path.join(output_dir, file_name_without_ext + '.pdf') | |
logging.info(f"Procesare fișier: {input_file}") | |
if pdf_exists(input_file, output_dir): | |
logging.info(f"Fișierul PDF există deja pentru {input_file}. Se omite conversia.") | |
return | |
_, extension = os.path.splitext(input_file) | |
extension = extension.lower() | |
try: | |
# Verifică și închide procesele Office înainte de fiecare conversie de document Office | |
if extension in ['.doc', '.docx', '.rtf']: | |
check_and_close_office_processes() | |
time.sleep(2) # Așteaptă să se închidă toate procesele | |
success = False | |
if extension == '.docx': | |
convert_docx_to_pdf(input_file, output_file) | |
success = True | |
elif extension == '.doc': | |
try: | |
convert_doc_to_pdf(input_file, output_file) | |
success = True | |
except Exception as e: | |
logging.warning(f"Prima încercare de conversie a eșuat pentru {input_file}: {str(e)}") | |
success = try_alternative_conversion(input_file, output_file, "DOC") | |
elif extension == '.rtf': | |
try: | |
convert_rtf_to_pdf(input_file, output_file) | |
success = True | |
except Exception as e: | |
logging.warning(f"Prima încercare de conversie a eșuat pentru {input_file}: {str(e)}") | |
success = try_alternative_conversion(input_file, output_file, "RTF") | |
elif extension == '.epub': | |
convert_epub_to_pdf(input_file, output_file) | |
success = True | |
elif extension == '.mobi': | |
convert_mobi_to_pdf(input_file, output_file) | |
success = True | |
elif extension == '.djvu': | |
convert_djvu_to_pdf(input_file, output_file) | |
success = True | |
elif extension == '.pdf': | |
repair_and_reconvert_pdf(input_file, output_file) | |
success = True | |
elif extension == '.lit': | |
convert_lit_to_pdf(input_file, output_file) | |
success = True | |
elif extension == '.txt': | |
convert_txt_to_pdf(input_file, output_file) | |
success = True | |
else: | |
logging.warning(f"Formatul {extension} nu este suportat pentru fișierul: {input_file}") | |
return | |
if success and os.path.exists(output_file): | |
logging.info(f"Procesat cu succes: {input_file} -> {output_file}") | |
else: | |
logging.warning(f"Nu s-a putut procesa: {input_file}") | |
problematic_files[input_file] = "Conversia nu a reușit - fișier PDF nu a fost creat" | |
except Exception as e: | |
logging.error(f"Eroare la procesarea {input_file}: {str(e)}") | |
problematic_files[input_file] = str(e) | |
def process_directory(input_dir, output_dir): | |
supported_extensions = ['.docx', '.doc', '.rtf', '.epub', '.mobi', '.djvu', '.pdf', '.lit', '.txt'] | |
skipped_files = [] | |
failed_files = [] | |
processed_files = [] | |
problematic_files = {} # Dicționar pentru fișierele problematice | |
# Verifică și închide procesele Office înainte de a începe conversia | |
check_and_close_office_processes() | |
# Obține doar fișierele din directorul curent (fără recursivitate) | |
files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))] | |
total_files = len(files) | |
logging.info(f"Total fișiere de procesat: {total_files}") | |
# Procesează mai întâi fișierele non-Office | |
for file_index, file in enumerate(files): | |
input_file = os.path.join(input_dir, file) | |
_, extension = os.path.splitext(file) | |
# Verifică dacă este un format suportat | |
if extension.lower() not in supported_extensions: | |
logging.info(f"Fișierul {file} are un format nesuportat: {extension}. Se omite.") | |
continue | |
# Verifică dacă PDF-ul există deja | |
if pdf_exists(input_file, output_dir): | |
logging.info(f"[{file_index+1}/{total_files}] Se omite {file} - PDF-ul există deja") | |
skipped_files.append(file) | |
continue | |
# Procesează fișier | |
logging.info(f"[{file_index+1}/{total_files}] Procesare {file}") | |
if any(file.lower().endswith(ext) for ext in ['.epub', '.mobi', '.djvu', '.pdf', '.lit', '.txt']): | |
try: | |
convert_file(input_file, output_dir, problematic_files) | |
processed_files.append(file) | |
except Exception as e: | |
failed_files.append(file) | |
logging.error(f"Eroare la procesarea {file}: {str(e)}") | |
problematic_files[input_file] = str(e) | |
# Apoi procesează fișierele Office | |
for file_index, file in enumerate(files): | |
if any(file.lower().endswith(ext) for ext in ['.doc', '.docx', '.rtf']): | |
input_file = os.path.join(input_dir, file) | |
# Verifică din nou dacă PDF-ul există deja | |
if pdf_exists(input_file, output_dir): | |
if file not in skipped_files: | |
logging.info(f"[{file_index+1}/{total_files}] Se omite {file} - PDF-ul există deja") | |
skipped_files.append(file) | |
continue | |
logging.info(f"[{file_index+1}/{total_files}] Procesare {file}") | |
try: | |
convert_file(input_file, output_dir, problematic_files) | |
processed_files.append(file) | |
except Exception as e: | |
failed_files.append(file) | |
logging.error(f"Eroare la procesarea {file}: {str(e)}") | |
problematic_files[input_file] = str(e) | |
# Adaugă o pauză între conversiile Office | |
time.sleep(3) | |
# Salvează fișierele problematice în JSON | |
if problematic_files: | |
json_path = os.path.join(output_dir, "fisiere_problematice.json") | |
with open(json_path, 'w', encoding='utf-8') as json_file: | |
json.dump(problematic_files, json_file, ensure_ascii=False, indent=4) | |
logging.info(f"Fișierele problematice au fost salvate în: {json_path}") | |
# Afișează sumarul | |
logging.info("\n=== SUMAR CONVERSIE ===") | |
logging.info(f"Total fișiere: {total_files}") | |
logging.info(f"Fișiere procesate cu succes: {len(processed_files)}") | |
logging.info(f"Fișiere omise (există deja): {len(skipped_files)}") | |
logging.info(f"Fișiere cu erori: {len(failed_files)}") | |
if skipped_files: | |
logging.info("\nFișiere omise (există deja în directorul de ieșire):") | |
for file in skipped_files: | |
logging.info(f"- {file}") | |
if failed_files: | |
logging.warning("\nFișiere care nu au putut fi procesate:") | |
for file in failed_files: | |
logging.warning(f"- {file}") | |
def disable_registry_file_block_settings(): | |
pass # Funcția nu mai este necesară, dar o păstrez goală pentru compatibilitate | |
# Dezactivăm setările de registru global (nu mai este necesar) | |
disable_registry_file_block_settings() | |
# Directorul de intrare și ieșire | |
input_dir = "D:\\3" | |
output_dir = "D:\\3\\Input" | |
# Ne asigurăm că directorul de ieșire există | |
os.makedirs(output_dir, exist_ok=True) | |
# Procesăm toate fișierele din directorul de intrare | |
process_directory(input_dir, output_dir) | |
logging.info("Procesarea tuturor fișierelor a fost finalizată.") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment