извлечение текста из файлов MS Word в Python

для работы с файлами MS Word в Python есть расширения Win32 для Python, которые можно использовать в Windows. Как мне сделать то же самое в Linux? Есть ли библиотека?

 Mawg09 нояб. 2018 г., 10:55
Можете ли вы определить "работать с"? Только чтение или тоже письмо?

Ответы на вопрос(14)

что такой вещи не существует. Есть только отвеченные и неотвеченные. Этот довольно без ответа, или наполовину ответили, если хотите. Что ж, способы чтения документов * .docx (MS Word 2007 и более поздних версий) без использования COM-взаимодействия рассматриваются. Но методы извлечения текста из * .doc (MS Word 97-2000), использующие только Python, отсутствуют. Это сложно? Чтобы сделать: не совсем, чтобы понять: хорошо, что 'Это другая вещь.

Когда я неЧтобы найти какой-либо готовый код, я прочитал некоторые спецификации формата и выкопал некоторые предложенные алгоритмы на других языках.

Файл MS Word (* .doc) является составным файлом OLE2. Чтобы не беспокоить вас множеством ненужных подробностей, думайте об этом как о файловой системе, хранящейся в файле. На самом деле используется структура FAT, поэтому определение верно. (Хм, может быть, вы можете смонтировать его в Linux ???) Таким образом, вы можете хранить больше файлов в файле, например, изображения и т. Д. То же самое можно сделать в * .docx, используя вместо этого ZIP-архив. В PyPI есть пакеты, которые могут читать файлы OLE. Как (olefile, componentfiles, ...) я использовал пакет componentfiles, чтобы открыть файл * .doc. Однако в MS Word 97-2000 внутренние подфайлы - это не XML или HTML, а двоичные файлы. И поскольку этого недостаточно, каждый содержит информацию о другом, так что вам нужно прочитать по крайней мере два из них и соответственно распознать сохраненную информацию. Чтобы полностью понять, прочитайте PDF документ, из которого я взял алгоритм.

Код ниже очень быстро составлен и протестирован на небольшом количестве файлов. Насколько я вижу, все работает как задумано. Иногда в начале появляется некоторая тарабарщина, и почти всегда в конце текста. И между ними могут быть какие-то странные символы.

Те из вас, кто просто хочет искать текст, будут счастливы. Тем не менее, я призываю всех, кто может помочь улучшить этот код, сделать это.


doc2text module:
"""
This is Python implementation of C# algorithm proposed in:
http://b2xtranslator.sourceforge.net/howtos/How_to_retrieve_text_from_a_binary_doc_file.pdf

Python implementation author is Dalen Bernaca.
Code needs refining and probably bug fixing!
As I am not a C# expert I would like some code rechecks by one.
Parts of which I am uncertain are:
    * Did the author of original algorithm used uint32 and int32 when unpacking correctly?
      I copied each occurence as in original algo.
    * Is the FIB length for MS Word 97 1472 bytes as in MS Word 2000, and would it make any difference if it is not?
    * Did I interpret each C# command correctly?
      I think I did!
"""

from compoundfiles import CompoundFileReader, CompoundFileError
from struct import unpack

__all__ = ["doc2text"]

def doc2text (path):
    text = u""
    cr = CompoundFileReader(path)
    # Load WordDocument stream:
    try:
        f = cr.open("WordDocument")
        doc = f.read()
        f.close()
    except: cr.close(); raise CompoundFileError, "The file is corrupted or it is not a Word document at all."
    # Extract file information block and piece table stream informations from it:
    fib = doc[:1472]
    fcClx  = unpack("L", fib[0x01a2l:0x01a6l])[0]
    lcbClx = unpack("L", fib[0x01a6l:0x01a6+4l])[0]
    tableFlag = unpack("L", fib[0x000al:0x000al+4l])[0] & 0x0200l == 0x0200l
    tableName = ("0Table", "1Table")[tableFlag]
    # Load piece table stream:
    try:
        f = cr.open(tableName)
        table = f.read()
        f.close()
    except: cr.close(); raise CompoundFileError, "The file is corrupt. '%s' piece table stream is missing." % tableName
    cr.close()
    # Find piece table inside a table stream:
    clx = table[fcClx:fcClx+lcbClx]
    pos = 0
    pieceTable = ""
    lcbPieceTable = 0
    while True:
        if clx[pos]=="\x02":
            # This is piece table, we store it:
            lcbPieceTable = unpack("l", clx[pos+1:pos+5])[0]
            pieceTable = clx[pos+5:pos+5+lcbPieceTable]
            break
        elif clx[pos]=="\x01":
            # This is beggining of some other substructure, we skip it:
            pos = pos+1+1+ord(clx[pos+1])
        else: break
    if not pieceTable: raise CompoundFileError, "The file is corrupt. Cannot locate a piece table."
    # Read info from pieceTable, about each piece and extract it from WordDocument stream:
    pieceCount = (lcbPieceTable-4)/12
    for x in xrange(pieceCount):
        cpStart = unpack("l", pieceTable[x*4:x*4+4])[0]
        cpEnd   = unpack("l", pieceTable[(x+1)*4:(x+1)*4+4])[0]
        ofsetDescriptor = ((pieceCount+1)*4)+(x*8)
        pieceDescriptor = pieceTable[ofsetDescriptor:ofsetDescriptor+8]
        fcValue = unpack("L", pieceDescriptor[2:6])[0]
        isANSII = (fcValue & 0x40000000) == 0x40000000
        fc      = fcValue & 0xbfffffff
        cb = cpEnd-cpStart
        enc = ("utf-16", "cp1252")[isANSII]
        cb = (cb*2, cb)[isANSII]
        text += doc[fc:fc+cb].decode(enc, "ignore")
    return "\n".join(text.splitlines())

Использоватьродной модуль Python docx, Вот'Как извлечь весь текст из документа:

document = docx.Document(filename)
docText = '\n\n'.join([
    paragraph.text.encode('utf-8') for paragraph in document.paragraphs
])
print docText

УвидетьСайт Python DocX

Также проверьтеTextract который вытаскивает столы и т. д.

Синтаксический анализ XML с помощью регулярных выражений вызывает cthulu. Дон»не делай этого!

 Joyson15 февр. 2018 г., 07:50
здесь у меня есть сценарий получения файла DOCX от http URL для этого, как я могу сделать эту часть
 dbliss08 мая 2015 г., 00:50
ты делаешьfrom docx import * Вот? если нет, то как тыgetdocumenttext, так далее.?
 egpbos05 авг. 2015 г., 07:40
opendocx отсутствует в модуле (возможно, это было в 2009 году). Документы открываются через класс Document, например, ,import docx; document = docx.Document('Hello world.docx')
 mikemaccana05 авг. 2015 г., 12:45
@egpbos I 'Мы обновили пример кода, чтобы использовать Python-Docx нового поколения.
 mikemaccana02 нояб. 2015 г., 12:46
@MyopicVisage проверить официальный сайт - этоВозможно, последняя версия имеет другую подпись.
 Joyson15 февр. 2018 г., 08:01
я создал вопрос вstackoverflow.com/questions/48800385/...
 MyopicVisage02 нояб. 2015 г., 05:10
Этот код привел к ошибке для меня: para.text.encode ('UTF-8') для абзаца в document.paragraphs TypeError: элемент последовательности 0: ожидаемый экземпляр str, найдены байты

что тыбудет много удачи без использования COM. Формат .doc до смешного сложен, и его часто называют "дамп памяти слова во время сохранения!

В Свати этоs в HTML, что хорошо и здорово, но большинство текстовых документов нетак мило!

БенжаминОтвет довольно хороший. Я только что консолидировал ...


docx = zipfile.ZipFile('/path/to/file/mydocument.docx')
content = docx.read('word/document.xml').decode('utf-8')
cleaned = re.sub('<(.|\n)*?>','',content)
print(cleaned)
 Ashutosh Tripathy10 окт. 2017 г., 09:38
content = docx.read ('слово / document.xml») .Decode (»UTF-8') в противном случае вы получите ошибку при очистке: TypeError: нельзя использовать строковый шаблон для объекта, подобного байту
 Jesvin Jose01 авг. 2011 г., 10:06
Чтобы удалить объекты XML, такие как &NBSP; от 'текст ': >>>из xml.sax.saxutils импорт unescape >>>Текст = экранирование в (очищенный)
 Chad28 дек. 2009 г., 04:41
Я должен повторить, что это работает только для DOCX (Word 2007 или более поздней версии). Для файлов .doc wvware - ваш лучший выбор. В зависимости от вашей среды это может быть проблематично при настройке, но это делает очень хорошую работу.
 markling08 мая 2015 г., 16:55
Ах, Филипп! Я просто искал способ отклонить тривиальные изменения стиля, которые вы внесли в другой мой пост. Я пытался связаться с вами напрямую. Пожалуйста, уточните, что вы предлагаете здесь? Этот ответ, который я дал здесь, является ответом на вопрос. Isn»это достаточно хорошо?
 markling08 мая 2015 г., 17:46
Число рейнольдса Ваши правки стиля и грамматики: я предпочел свой собственный стиль и грамматику, спасибо. Хороший редактор не делаетнавязать свой собственный стиль. И действительно, ни у кого из нас нет достаточно свободного времени, чтобы выполнять обычную проверку орфографии и грамматики, не так ли? Я думаю, что вы можете найти это немного чрезмерно. Я

одпроцесса, вы можете использовать модуль Python zipfile.

content = ""
# Load DocX into zipfile
docx = zipfile.ZipFile('/home/whateverdocument.docx')
# Unpack zipfile
unpacked = docx.infolist()
# Find the /word/document.xml file in the package and assign it to variable
for item in unpacked:
    if item.orig_filename == 'word/document.xml':
        content = docx.read(item.orig_filename)

    else:
        pass

Ваша строка содержимого, однако, должна быть очищена, один из способов сделать это:

# Clean the content string from xml tags for better search
fullyclean = []
halfclean = content.split('<')
for item in halfclean:
    if '>' in item:
        bad_good = item.split('>')
        if bad_good[-1] != '':
            fullyclean.append(bad_good[-1])
        else:
            pass
    else:
        pass

# Assemble a new string with all pure content
content = " ".join(fullyclean)

Но, безусловно, есть более элегантный способ очистить строку, возможно, с помощью модуля re. Надеюсь это поможет.

 Vikas Prasad04 сент. 2015 г., 20:13
С помощью повторного модуля очистка может быть намного проще:stripped_content = re.compile(b'').sub(b' ', content ) # strip tags Одна вещь, которую я не мог понять в вашем коде, в предыдущем фрагменте почемут тыbreakвыходя внутрьif блок?
 Jesvin Jose01 авг. 2011 г., 10:05
Чтобы удалить объекты XML, такие как &NBSP; от 'текст ': >>>из xml.sax.saxutils импорт unescape >>>Текст = экранирование в (содержание)

включая файлы .docx, вы можете использоватьпитон-DOCX пакет:

from docx import Document
document = Document('existing-document-file.docx')
document.save('new-file-name.docx')

Чтобы прочитать файлы .doc из Word 2003 и более ранних версий, выполните вызов подпроцесса дляAntiword, Сначала вам нужно установить antiword:

sudo apt-get install antiword

Затем просто вызовите его из скрипта Python:

import os
input_word_file = "input_file.doc"
output_text_file = "output_file.txt"
os.system('antiword %s > %s' % (input_word_file, output_text_file))

посмотреть здесь.

Поскольку OOo может без проблем загружать большинство файлов MS Word, ясказал бы этоВаша лучшая ставка.

 SpliFF26 мая 2009 г., 17:17
Не без нареканий. Близко, но далеко не безупречно в моем опыте (OO 2.0 - 3.0).
 Esteban Küber29 сент. 2009 г., 16:50
Как MS Word N + 1 открывает MS Word N файлов, и лучше, чем MS Word N + 1 открывает MS Word N-1 файлов, IMHO
Решение Вопроса

Antiword, Antiword - это утилита командной строки linux для вывода текста из слова doc. Работает довольно хорошо для простых документов (очевидно, он теряет форматирование). Это'Он доступен через apt и, возможно, как RPM, или вы можете скомпилировать его самостоятельно.

 Marius Gedminas30 сент. 2015 г., 13:38
antiword может конвертировать текстовые документы в DocBook XML, что сохранит (хотя бы немного) форматирование.
 Xiflado13 апр. 2016 г., 22:06
catdoc также работает, если антислово не доступно.

как работает формат doc а такжесоздать текстовый документ с использованием PHP в Linux, Первое особенно полезно.Abiword мой рекомендуемый инструмент. Естьограничения хоть:

Однако если документ содержит сложные таблицы, текстовые поля, встроенные электронные таблицы и т. Д., Он может работать не так, как ожидалось. Разработка хороших фильтров MS Word - очень сложный процесс, поэтому, пожалуйста, будьте терпеливы, когда мы работаем над тем, чтобы документы Word открывались правильно. Если у вас есть документ Word, который не загружается, откройте ошибку и включите документ, чтобы мы могли улучшить импортер.

 William Keller24 сент. 2008 г., 14:11
Ах яЯ всегда думал, что abiword был просто еще одним текстовым процессором! Чувак, это избавило бы меня от головной боли.
 Swati24 сент. 2008 г., 05:42
Abiword не делаетне предположить, что этодокумент HTML, и учитывая, насколько обширный инструмент ... Я нене думаю, что это былолегко" реализовать это. Abiword - это инструмент, который помогает вам читать файлы MS Word ... и, поскольку автор занимается поиском текста, этого достаточно.
 William Keller24 сент. 2008 г., 05:30
Не только это, хотя! Даже самый простой текст, сохраненный в формате Word 97, почти невозможно легко получить, не полагаясь на слово, которое сделает это за вас (COM). Большинство текстовых документов не являются HTML!

этот вопрос также, но здесь это кажется уместным, поэтому, пожалуйста, извините за репост.)

Теперь, это довольно уродливо и довольно хакерски, но мне кажется, что это работает для базового извлечения текста. Очевидно, что для использования этого в программе Qt вы 'Я должен создать процесс для него и т. д., но командная строка I 'взломан вместе это:

unzip -p file.docx | grep '<w:t' |="" sed="" 's="" <[^<]*="">//g' | grep -v '^[[:space:]]*

Чтобы's:

распаковать -p файл.docx: -p == "распаковать на стандартный вывод "

grep '<ш: т»: Захватить только строки, содержащие '<w: t '(<ш: т> является элементом Word 2007 XML для "текст"насколько я могу судить)

седьс / <[^ <]>//г'*: Удалить все внутри тегов

grep -v '^ [[: Пространство:]] $»*: Убрать пустые строки

Вероятно, есть более эффективный способ сделать это, но мне кажется, что он работает для меня в нескольких документах, которые яЯ проверил это с.

Насколько я'На мой взгляд, у всех архивов, unzip, grep и sed есть порты для Windows и любого из Unix, поэтому он должен быть достаточно кроссплатформенным. Невзирая на то, чтобы быть немного уродливым хаком;)

</w:t'>

Чтобы's:

распаковать -p файл.docx: -p == "распаковать на стандартный вывод "

grep '<ш: т»: Захватить только строки, содержащие '<w: t '(<ш: т> является элементом Word 2007 XML для "текст"насколько я могу судить)

седьс / <[^ <]>//г'*: Удалить все внутри тегов

grep -v '^ [[: Пространство:]] $»*: Убрать пустые строки

Вероятно, есть более эффективный способ сделать это, но мне кажется, что он работает для меня в нескольких документах, которые яЯ проверил это с.

Насколько я'На мой взгляд, у всех архивов, unzip, grep и sed есть порты для Windows и любого из Unix, поэтому он должен быть достаточно кроссплатформенным. Невзирая на то, чтобы быть немного уродливым хаком;)

что это старый вопрос, но недавно я пытался найти способ извлечь текст из файлов MS Word, и лучшее решение, на мой взгляд, было с wvLib:

http://wvware.sourceforge.net/

После установки библиотеки использовать ее в Python довольно просто:

import commands

exe = 'wvText ' + word_file + ' ' + output_txt_file
out = commands.getoutput(exe)
exe = 'cat ' + output_txt_file
out = commands.getoutput(exe)

И этосидеть. В значительной степени, что мыОн использует функцию command.getouput для запуска нескольких сценариев оболочки, а именно, wvText (который извлекает текст из документа Word, и cat для чтения выходных данных файла). После этого весь текст из документа Word будет находиться в переменной out, готовой к использованию.

Надеюсь, это поможет любому, кто столкнется с подобными проблемами в будущем.

Miette, Должен работать на любой платформе.

Ваш ответ на вопрос