Script python permettant de traduire un long texte
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import PyPDF2
  2. import requests
  3. import json
  4. from reportlab.lib.pagesizes import letter
  5. from reportlab.lib.units import inch
  6. from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
  7. from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
  8. from reportlab.lib.enums import TA_JUSTIFY
  9. from reportlab.pdfbase import pdfmetrics
  10. from reportlab.pdfbase.ttfonts import TTFont
  11. import os
  12. # Configuration
  13. PDF_PATH = "TaniaBorecMemoir(Ukr).pdf" # Fichier original
  14. OLLAMA_MODEL = "traductionUkrainienVersFrancais:latest"
  15. OLLAMA_URL = "http://localhost:11434/api/generate" # URL par défaut d'Ollama
  16. OUTPUT_PDF_PATH = PDF_PATH.replace(".pdf", " (FR).pdf") # Chemin du PDF de sortie
  17. def extract_text_from_pdf(pdf_path):
  18. """Extrait le texte page par page d'un PDF sans les numéros de pages."""
  19. import re
  20. text_by_page = []
  21. with open(pdf_path, "rb") as file:
  22. reader = PyPDF2.PdfReader(file)
  23. for page in reader.pages:
  24. text = page.extract_text()
  25. # Supprime les numéros de pages (nombres seuls en début/fin de ligne)
  26. text = re.sub(r'^\d+\s*\n', '', text, flags=re.MULTILINE)
  27. text = re.sub(r'\n\s*\d+\s*$', '', text, flags=re.MULTILINE)
  28. text_by_page.append(text)
  29. return text_by_page
  30. def send_to_ollama(prompt, model=OLLAMA_MODEL, context_size=128000):
  31. """Envoie une requête à Ollama et retourne la réponse."""
  32. payload = {
  33. "model": model,
  34. "prompt": prompt,
  35. "stream": False,
  36. "options": {"num_ctx": context_size}
  37. }
  38. response = requests.post(OLLAMA_URL, data=json.dumps(payload))
  39. if response.status_code == 200:
  40. return response.json()["response"]
  41. else:
  42. raise Exception(f"Erreur Ollama: {response.text}")
  43. def register_unicode_font():
  44. """Enregistre une police TrueType qui supporte le cyrilique."""
  45. # Recherche une police système qui supporte le cyrilique
  46. font_paths = [
  47. r"C:\Windows\Fonts\DejaVuSans.ttf",
  48. r"C:\Windows\Fonts\Calibri.ttf",
  49. r"C:\Windows\Fonts\arial.ttf",
  50. ]
  51. for font_path in font_paths:
  52. if os.path.exists(font_path):
  53. try:
  54. pdfmetrics.registerFont(TTFont('UnicodeFont', font_path))
  55. return 'UnicodeFont'
  56. except Exception as e:
  57. print(f"Erreur lors de l'enregistrement de {font_path}: {e}")
  58. # Si aucune police spéciale trouvée, utilise Helvetica par défaut
  59. print("Aucune police Unicode trouvée, utilisation d'Helvetica")
  60. return 'Helvetica'
  61. def create_pdf_from_results(results, output_path):
  62. """Crée un PDF à partir des résultats de traduction."""
  63. doc = SimpleDocTemplate(output_path, pagesize=letter, topMargin=inch, bottomMargin=inch)
  64. story = []
  65. # Enregistre une police qui supporte le cyrilique
  66. font_name = register_unicode_font()
  67. # Style personnalisé
  68. styles = getSampleStyleSheet()
  69. title_style = ParagraphStyle(
  70. 'CustomTitle',
  71. parent=styles['Heading1'],
  72. fontSize=16,
  73. textColor='#1f4788',
  74. spaceAfter=0.3*inch,
  75. alignment=TA_JUSTIFY,
  76. fontName=font_name
  77. )
  78. page_style = ParagraphStyle(
  79. 'PageHeading',
  80. parent=styles['Heading2'],
  81. fontSize=12,
  82. textColor='#1f4788',
  83. spaceAfter=0.2*inch,
  84. spaceBefore=0.2*inch,
  85. fontName=font_name
  86. )
  87. body_style = ParagraphStyle(
  88. 'CustomBody',
  89. parent=styles['BodyText'],
  90. fontSize=11,
  91. alignment=TA_JUSTIFY,
  92. spaceAfter=0.2*inch,
  93. fontName=font_name
  94. )
  95. # Titre
  96. story.append(Paragraph("Traduction - Ukrainien vers Français", title_style))
  97. story.append(Spacer(1, 0.2*inch))
  98. # Contenu
  99. for page_num, translation in results.items():
  100. # Préserver la mise en page en convertissant les sauts de ligne
  101. formatted_text = translation.replace("\n", "<br/>")
  102. story.append(Paragraph(formatted_text, body_style))
  103. story.append(Spacer(1, 0.1*inch))
  104. # Construction du PDF
  105. doc.build(story)
  106. print(f"PDF généré avec succès : {output_path}")
  107. def main():
  108. # Extraction du texte
  109. pages = extract_text_from_pdf(PDF_PATH)
  110. print(f"Nombre de pages extraites : {len(pages)}")
  111. # Dictionnaire pour stocker les résultats
  112. results = {}
  113. # Traitement page par page
  114. for i, page_text in enumerate(pages, start=1):
  115. if( i > 2) : # Limite le nombre de pages pour les tests
  116. break
  117. print(f"{15 * '-'} Traduction de la page {i}/{len(pages)}...")
  118. prompt = f"Traduis le texte suivant de l'ukrainien vers le français : {page_text}"
  119. try:
  120. result = send_to_ollama(prompt)
  121. print(f"{result}.")
  122. results[i] = result
  123. except Exception as e:
  124. print(f"Erreur lors du traitement de la page {i} : {e}")
  125. results[i] = f"Erreur lors du traitement de la page {i} : {e}"
  126. # Création du PDF avec tous les résultats
  127. create_pdf_from_results(results, OUTPUT_PDF_PATH)
  128. if __name__ == "__main__":
  129. main()