Skip to content

Instantly share code, notes, and snippets.

@me-suzy
Created May 7, 2025 02:37
Show Gist options
  • Save me-suzy/cf299c4932765e72a75daf5dad413d73 to your computer and use it in GitHub Desktop.
Save me-suzy/cf299c4932765e72a75daf5dad413d73 to your computer and use it in GitHub Desktop.
convert all to pdf GROK.py
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