Advertisement
serhiy1994

split word file into X parts by strings given

Jan 16th, 2025
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.06 KB | None | 0 0
  1. import tempfile
  2. from typing import Generator, List, Tuple, Union
  3.  
  4. from docx import Document
  5. from docx.document import Document as DocType
  6. from docx.oxml.table import CT_Tbl
  7. from docx.oxml.text.paragraph import CT_P
  8. from docx.oxml.xmlchemy import BaseOxmlElement
  9. from docx.text.paragraph import Paragraph
  10.  
  11. import pandas as pd
  12. import os
  13.  
  14. def iterparts(doc_path: str, split_points: List[str], bias: int = 0) -> Generator[Tuple[int, DocType], None, None]:
  15.     """
  16.    Розділяє документ на частини відповідно до масиву рядків split_points.
  17.  
  18.    :param doc_path: Шлях до документа.
  19.    :param split_points: Список текстів, які визначають точки поділу.
  20.    :param bias: Зміщення індексу для розділення.
  21.    :return: Генератор, що повертає частини документа.
  22.    """
  23.     doc = Document(doc_path)
  24.     counter = 0
  25.     while doc:
  26.         split_elem_idx = -1
  27.         doc_body = doc.element.body
  28.         cutted = [doc, None]
  29.         for idx, elem in enumerate(doc_body.iterchildren()):
  30.             if is_split_point(elem, split_points):
  31.                 if split_elem_idx == -1:
  32.                     split_elem_idx = idx
  33.                 else:
  34.                     cutted = split(doc, idx + bias)
  35.                     counter += 1
  36.                     break
  37.         yield (counter, cutted[0])
  38.         doc = cutted[1]
  39.  
  40.  
  41. def is_split_point(element: BaseOxmlElement, split_points: List[str]) -> bool:
  42.     """
  43.    Визначає, чи є елемент точкою поділу відповідно до масиву рядків.
  44.  
  45.    :param element: Елемент документа.
  46.    :param split_points: Список текстів, які визначають точки поділу.
  47.    :return: True, якщо елемент є точкою поділу.
  48.    """
  49.     if isinstance(element, CT_P):
  50.         p = Paragraph(element, element.getparent())
  51.         return p.text.strip() in split_points
  52.     return False
  53.  
  54.  
  55. def split(doc: DocType, cut_idx: int) -> Tuple[DocType, DocType]:
  56.     """
  57.    Розділяє документ на дві частини.
  58.  
  59.    :param doc: Документ для розділення.
  60.    :param cut_idx: Індекс елемента, на якому виконується розділення.
  61.    :return: Кортеж з двох частин документа.
  62.    """
  63.     tmpdocfile = write_tmp_doc(doc)
  64.     second_part = doc
  65.     second_elems = list(second_part.element.body.iterchildren())
  66.     for i in range(0, cut_idx):
  67.         remove_element(second_elems[i])
  68.     first_part = Document(tmpdocfile)
  69.     first_elems = list(first_part.element.body.iterchildren())
  70.     for i in range(cut_idx, len(first_elems)):
  71.         remove_element(first_elems[i])
  72.     tmpdocfile.close()
  73.     return (first_part, second_part)
  74.  
  75.  
  76. def remove_element(elem: Union[CT_P, CT_Tbl]):
  77.     """
  78.    Видаляє елемент з документа.
  79.  
  80.    :param elem: Елемент для видалення (параграф або таблиця).
  81.    """
  82.     elem.getparent().remove(elem)
  83.  
  84.  
  85. def write_tmp_doc(doc: DocType):
  86.     """
  87.    Зберігає документ у тимчасовий файл.
  88.  
  89.    :param doc: Документ для збереження.
  90.    :return: Об'єкт тимчасового файлу.
  91.    """
  92.     tmp = tempfile.TemporaryFile()
  93.     doc.save(tmp)
  94.     return tmp
  95.  
  96.  
  97. def load_key_phrases(file_path):
  98.     """
  99.    Завантажує таблицю ключових фраз із файлу (TXT, XLSX або CSV) та повертає список ключових фраз.
  100.    """
  101.     if file_path.endswith('.csv'):
  102.         key_phrases_df = pd.read_csv(file_path)
  103.     elif file_path.endswith('.xlsx'):
  104.         key_phrases_df = pd.read_excel(file_path, header=None)
  105.     elif file_path.endswith('.txt'):
  106.         key_phrases_df = open(file_path, 'r').read()
  107.     else:
  108.         raise ValueError("Підтримуються лише файли TXT, CSV або XLSX.")
  109.  
  110.     if file_path.endswith('.txt'):
  111.         key_phrases = key_phrases_df.splitlines()
  112.     else:
  113.         key_phrases = key_phrases_df.iloc[:, 0].dropna().str.strip().tolist()
  114.     for phrase in key_phrases:
  115.         phrase.encode(encoding="UTF-8", errors='strict')
  116.     return key_phrases
  117.  
  118.  
  119.  
  120. def process_document(doc_path, key_phrases_path, output_dir='output'):
  121.     if not os.path.exists(output_dir):
  122.         os.makedirs(output_dir)
  123.     key_phrases = load_key_phrases(key_phrases_path)
  124.  
  125.  
  126.     for index, part in iterparts(doc_path, key_phrases):
  127.         part.save(os.path.join(output_dir, f"part_{index}.docx"))
  128.  
  129.  
  130. if __name__ == "__main__":
  131.     document_path = "test.docx"  # Замінить на шлях до вашого файлу
  132.     key_phrases_path = "test_phrases.txt"  # Замініть на шлях до файлу з ключовими фразами
  133.     output_directory = "output"
  134.     process_document(document_path, key_phrases_path, output_directory)
  135.  
  136.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement