Чтение потока документа Word (.doc) в Python

Я пытаюсь прочитать документ Word (.doc), чтобы создать CustomWordLoader для LangChain. В настоящее время я могу читать файлы .docx с помощью пакета Python-docx.

Поток создается путем чтения документа Word с сайта Sharepoint.

Вот код для документов:

class CustomWordLoader(BaseLoader):
    """
    This class is a custom loader for Word documents. It extends the BaseLoader class and overrides its methods.
    It uses the python-docx library to parse Word documents and optionally splits the text into manageable documents.
    
    Attributes:
    stream (io.BytesIO): A binary stream of the Word document.
    filename (str): The name of the Word document.
    """
    def __init__(self, stream, filename: str):
        # Initialize with a binary stream and filename
        self.stream = stream
        self.filename = filename

    def load_and_split(self, text_splitter=None):
        # Use python-docx to parse the Word document from the binary stream
        doc = DocxDocument(self.stream)
        # Extract and concatenate all paragraph texts into a single string
        text = "\n".join([p.text for p in doc.paragraphs])

        # Check if a text splitter utility is provided
        if text_splitter is not None:
            # Use the provided splitter to divide the text into manageable documents
            split_text = text_splitter.create_documents([text])
        else:
            # Without a splitter, treat the entire text as one document
            split_text = [{'text': text, 'metadata': {'source': self.filename}}]

        # Add source metadata to each resulting document
        for doc in split_text:
            if isinstance(doc, dict):
                doc['metadata'] = {**doc.get('metadata', {}), 'source': self.filename}
            else:
                doc.metadata = {**doc.metadata, 'source': self.filename}

        return split_text

Мое решение будет развернуто на Docker с использованием «3.11.8-alpine3.18» (упрощенная версия unix).

По соображениям безопасности я не могу загрузить файл локально, поэтому мне действительно нужно иметь возможность читать поток, как в моем примере: doc = DocxDocument(self.stream)

Я пытался найти пакет, эквивалентный Python-docx, который может читать .docx, но не .doc.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
192
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я смог сделать это с помощью Textract. Мне нужно сохранить поток в файл локально, но это единственный способ, который я нашел.

вот мой код:

class CustomWordLoader(BaseLoader):
"""
A custom loader for Word documents, extending BaseLoader. It reads Word documents from a binary stream,
writes them temporarily to disk, and uses textract to extract text. If textract fails, an exception is raised.
"""
def __init__(self, stream, filename: str):
    self.stream = stream
    self.filename = filename

def load_and_split(self, text_splitter=None):
    # Generate a unique filename
    temp_filename = str(uuid.uuid4()) + '.doc'
    
    # Create a temporary directory
    temp_dir = os.path.join(os.getcwd(), 'temp')
    os.makedirs(temp_dir, exist_ok=True)
    
    # Full path to the temporary file
    temp_file_path = os.path.join(temp_dir, temp_filename)
    
    # Write the content of the stream into the temporary file
    with open(temp_file_path, 'wb') as f:
        f.write(self.stream.read())
    
    # Use textract to extract the text from the file
    text = textract.process(temp_file_path).decode('utf-8')
    
    if text_splitter is not None:
        split_text = text_splitter.create_documents([text])
    else:
        split_text = [{'text': text, 'metadata': {'source': self.filename}}]

    for doc in split_text:
        if isinstance(doc, dict):
            doc['metadata'] = {**doc.get('metadata', {}), 'source': self.filename}
        else:
            doc.metadata = {**doc.metadata, 'source': self.filename}

    # Remove the temporary file
    os.remove(temp_file_path)

    return split_text

Я надеюсь, что это может помочь кому-то!

Другие вопросы по теме