Advertisement
nicuf

Parse Docx To Html With Processing Styles

Sep 21st, 2023
882
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.40 KB | None | 0 0
  1. # Romanian: https://neculaifantanaru.com/python-parseaza-docx-la-html-cu-procesarea-stilurilor.html
  2. # English: https://neculaifantanaru.com/en/parse-docx-to-html-with-processing-styles.html
  3.  
  4.  
  5. import os
  6. import re
  7. import unidecode
  8. from docx import Document
  9.  
  10.  
  11. # Funcția pentru adăugarea conținutului la tag-ul meta
  12. def add_content_to_meta(html_content, content_to_add):
  13.     meta_pattern = r'<meta name="description" content="(.*?)">'
  14.     match = re.search(meta_pattern, html_content)
  15.     if match:
  16.         old_meta_tag = match.group(0)
  17.         new_content = re.sub(r'<em>(.*?)</em>', r'\1', content_to_add)  # Elimină tag-urile <em>
  18.         new_meta_tag = f'<meta name="description" content="{new_content}">'
  19.         updated_html_content = html_content.replace(old_meta_tag, new_meta_tag)
  20.         return updated_html_content
  21.     else:
  22.         return html_content
  23.  
  24.  
  25. # Funcția pentru conversia stilurilor paragrafelor din DOCX în HTML
  26. def extract_data_from_docx(file_path):
  27.     doc = Document(file_path)
  28.     content = ""
  29.  
  30.     # Parcurge toate paragrafele din document și le adaugă la conținut
  31.     for paragraph in doc.paragraphs:
  32.         content += paragraph.text + "\n"
  33.  
  34.     # Utilizăm regex pentru a găsi titlurile și corpul fiecărui articol
  35.     articles = re.split(r'^([A-Z][\w\s\-\(\)]+)$', content, flags=re.MULTILINE | re.DOTALL)
  36.     articles = [article.strip() for article in articles if article.strip()]
  37.  
  38.     data = []
  39.  
  40.     # Iterăm prin lista de articole pentru a extrage titlul și corpul corespunzător
  41.     for i in range(0, len(articles), 2):
  42.         title = articles[i]
  43.         body = articles[i + 1].strip().split("\n")
  44.         data.append((title, body))
  45.  
  46.     return data
  47.  
  48.  
  49.  
  50. def convert_docx_to_html_style(para):
  51.     result = ""
  52.  
  53.     if para.runs:
  54.         contains_bold = any(run.bold for run in para.runs)
  55.         contains_italic = any(run.italic for run in para.runs)
  56.         contains_regular = any(not run.bold and not run.italic for run in para.runs)
  57.  
  58.         if contains_bold and contains_italic and contains_regular:
  59.             # Cazul 4: Textul conține atât bold, cât și italic și text regulat
  60.             html_para = '<p class="text_obisnuit">'
  61.             is_bold = False
  62.             is_italic = False
  63.             for run in para.runs:
  64.                 if run.bold and not is_bold:
  65.                     html_para += '<span class="text_obisnuit2">'
  66.                     is_bold = True
  67.                 if run.italic and not is_italic:
  68.                     html_para += '<em>'
  69.                     is_italic = True
  70.                 elif not run.bold and is_bold:
  71.                     html_para += '</span>'
  72.                     is_bold = False
  73.                 elif not run.italic and is_italic:
  74.                     html_para += '</em>'
  75.                     is_italic = False
  76.  
  77.                 html_para += run.text
  78.  
  79.             if is_bold:
  80.                 html_para += '</span>'
  81.             if is_italic:
  82.                 html_para += '</em>'
  83.  
  84.             html_para += '</p>\n'
  85.  
  86.         elif contains_bold and contains_regular:
  87.             # Cazul 3: Textul conține atât bold, cât și text regulat
  88.             html_para = '<p class="text_obisnuit">'
  89.             is_bold = False
  90.             for run in para.runs:
  91.                 if run.bold and not is_bold:
  92.                     html_para += '<span class="text_obisnuit2">'
  93.                     is_bold = True
  94.                 elif not run.bold and is_bold:
  95.                     html_para += '</span>'
  96.                     is_bold = False
  97.  
  98.                 html_para += run.text
  99.  
  100.             if is_bold:
  101.                 html_para += '</span>'
  102.  
  103.             html_para += '</p>\n'
  104.  
  105.         elif contains_bold:
  106.             # Cazul 2: Textul conține doar bold
  107.             html_para = '<p class="text_obisnuit2">'
  108.             for run in para.runs:
  109.                 html_para += run.text
  110.             html_para += '</p>\n'
  111.  
  112.         elif contains_italic:
  113.             # Cazul 5: Textul conține doar italic
  114.             html_para = '<p class="text_obisnuit">'
  115.             is_italic = False
  116.             for run in para.runs:
  117.                 if run.italic and not is_italic:
  118.                     html_para += '<em>'
  119.                     is_italic = True
  120.                 elif not run.italic and is_italic:
  121.                     html_para += '</em>'
  122.                     is_italic = False
  123.  
  124.                 html_para += run.text
  125.  
  126.             if is_italic:
  127.                 html_para += '</em>'
  128.  
  129.             html_para += '</p>\n'
  130.  
  131.         else:
  132.             # Cazul 1: Textul este regulat (fără bold sau italic)
  133.             html_para = '<p class="text_obisnuit">'
  134.             for run in para.runs:
  135.                 html_para += run.text
  136.             html_para += '</p>\n'
  137.  
  138.         result += html_para
  139.  
  140.     return result
  141.  
  142.  
  143. def generate_filename(title):
  144.     # Îndepărtează spațiile și caracterele speciale din titlu
  145.     title = title.strip()
  146.     title = re.sub(r'’s|’t', '', title)
  147.     title = re.sub(r'[^a-zA-Z0-9\s]', '', title)
  148.  
  149.     # Transformă titlul în litere mici
  150.     title = title.lower()
  151.  
  152.     title = title.replace(' ', '-')
  153.     # Asigură că numele fișierului are o extensie .html
  154.     filename = title + ".html"
  155.     print("Filename:", filename)  # Afișează numele fișierului
  156.     return filename
  157.  
  158. def update_and_save_html(title, body, template_path, output_directory):
  159.     with open(template_path, "r", encoding="utf-8") as f:
  160.         html_content = f.read()
  161.  
  162.     # Eliminarea sufixului " | Neculai Fantanaru (en)" din titlu
  163.     title_without_suffix = title.replace(" | Neculai Fantanaru (en)", "")
  164.  
  165.     # Înlocuirea titlului în tagul <h1> cu titlul fără sufix
  166.     html_content = html_content.replace('<h1 class="den_articol" itemprop="name">XXX</h1>', f'<h1 class="den_articol" itemprop="name">{title_without_suffix}</h1>')
  167.  
  168.     # Înlocuirea titlului în conținutul HTML
  169.     new_title = title + " | Neculai Fantanaru (en)"
  170.     html_content = html_content.replace("XXX", new_title, 2)
  171.     print("Titlul a fost înlocuit.")
  172.  
  173.     # Găsirea poziției de început și sfârșit a blocului YYY
  174.     start_marker = "<!-- ARTICOL START -->"
  175.     end_marker = "<!-- ARTICOL FINAL -->"
  176.     start = html_content.find(start_marker)
  177.     end = html_content.find(end_marker)
  178.  
  179.     if start != -1 and end != -1:
  180.         # Înlocuirea blocului YYY cu conținutul articolului, respectând formatarea cerută
  181.         article_content = ""
  182.         first_sentence = True
  183.         for line in body:
  184.             line = line.strip()
  185.             # Începe prima propoziție cu <p class="text_obisnuit2">
  186.             if first_sentence:
  187.                 article_content += f'\n\t<p class="text_obisnuit2"><em>{line}</em></p>'
  188.                 first_sentence = False
  189.             elif line.startswith("Leadership:"):
  190.                 article_content += f'\n\t<p class="text_obisnuit2">{line}</p>'
  191.             else:
  192.                 article_content += f'\n\t<p class="text_obisnuit">{line}</p>'
  193.         html_content = html_content[:start + len(start_marker)] + article_content + html_content[end:]
  194.         print("Corpul articolului a fost înlocuit conform cerințelor.")
  195.  
  196.     # Integrarea stilurilor de paragrafe din DOCX în HTML
  197.     doc = Document("bebe.docx")
  198.     for para in doc.paragraphs:
  199.         html_style = convert_docx_to_html_style(para)
  200.         html_content = html_content.replace("<p class=\"text_obisnuit\">{}</p>".format(para.text), html_style)
  201.  
  202.     # Eliminarea caracterelor speciale folosind unidecode
  203.     html_content = unidecode.unidecode(html_content)
  204.  
  205.     # Crearea numelui de fișier bazat pe titlu
  206.     filename = generate_filename(title)
  207.  
  208.     # Înlocuirea "zzz.html" cu numele fișierului generat în fiecare fișier HTML
  209.     html_content = html_content.replace("zzz.html", filename)
  210.  
  211.     # Salvarea modificărilor în UTF-8
  212.     with open(os.path.join(output_directory, filename), "w", encoding="utf-8") as f:
  213.         f.write(html_content)
  214.     print(f"Fișierul a fost salvat ca {filename}")
  215.  
  216. # Extragem datele din bebe.docx
  217. articles_data = extract_data_from_docx("bebe.docx")
  218.  
  219. # Specifică directorul în care dorești să salvezi fișierele HTML
  220. output_directory = "output"
  221.  
  222. # Actualizăm și salvăm fiecare articol într-un fișier HTML separat
  223. for title, body in articles_data:
  224.     update_and_save_html(title, body, "index.html", output_directory)
  225.  
  226.  # Deschide fișierul HTML pentru actualizare
  227.     html_file_path = os.path.join(output_directory, generate_filename(title))
  228.     with open(html_file_path, "r", encoding="utf-8") as html_file:
  229.         html_content = html_file.read()
  230.  
  231.     # Colectează conținutul paragrafelor cu clasa "text_obisnuit2"
  232.     content_to_add = ""
  233.     paragraphs = re.findall(r'<p class="text_obisnuit2">(.*?)</p>', html_content)
  234.     for paragraph in paragraphs:
  235.         content_to_add += paragraph.strip() + ' '
  236.  
  237.     # Elimină tag-urile <em> din conținutul adăugat
  238.     content_to_add_cleaned = re.sub(r'<em>(.*?)</em>', r'\1', content_to_add)
  239.  
  240.     # Adaugă conținutul curățat la tag-ul meta
  241.     updated_html_content = add_content_to_meta(html_content, content_to_add_cleaned)
  242.  
  243.     # Actualizează fișierul HTML cu conținutul adăugat
  244.     with open(html_file_path, "w", encoding="utf-8") as updated_html_file:
  245.         updated_html_file.write(updated_html_content)
  246.  
  247. print("Conținutul a fost adăugat la tag-ul meta în fiecare fișier HTML, eliminând tag-urile <em>.")
  248.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement