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

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

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

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

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

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

Файл MS Word (* .doc) является составным файлом OLE2. Чтобы не беспокоить вас множеством ненужных подробностей, думайте об этом как о файловой системе, хранящейся в файле. На самом деле используется структура FAT, поэтому определение верно. (Хм, может быть, вы можете смонтировать его в Linux ???) Таким образом, вы можете хранить больше файлов в файле, например, картинки и т. Д. То же самое делается в * .docx, используя вместо этого ZIP-архив. В PyPI есть пакеты, которые могут читать файлы OLE. Как (olefile, составные файлы, ...) Я использовал пакет 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())

включая файлы .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))
 08 мая 2015 г., 17:46
Число рейнольдса Ваши правки стиля и грамматики: я предпочел свой собственный стиль и грамматику, спасибо. Хороший редактор не навязывает свой собственный стиль. И действительно, ни у кого из нас нет достаточно свободного времени, чтобы выполнять обычную проверку орфографии и грамматики, не так ли? Я думаю, вы можете найти это немного несерьезным.
 08 мая 2015 г., 16:55
Ах, Филипп! Я просто искал способ отклонить тривиальные изменения стиля, которые вы внесли в другой мой пост. Я пытался связаться с вами напрямую. Пожалуйста, уточните, что вы предлагаете здесь? Этот ответ, который я дал здесь, является ответом на вопрос. Разве это не достаточно хорошо?

native Python docx module, Вот как можно извлечь весь текст из документа:

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. Не делай этого!

 02 нояб. 2015 г., 12:46
@MyopicVisage проверьте официальный сайт - возможно, последняя версия имеет другую подпись.
 05 авг. 2015 г., 12:45
@egpbos Я обновил пример кода, чтобы использовать python-docx нового поколения.
 08 мая 2015 г., 00:50
ты делаешьfrom docx import * Вот? если нет, то как тыgetdocumenttext, так далее.?
 02 нояб. 2015 г., 05:10
Этот код привел к ошибке для меня: абзац.text.encode ("utf-8") для абзаца в document.paragraphs TypeError: элемент последовательности 0: ожидаемый экземпляр str, найдены байты
 05 авг. 2015 г., 07:40
opendocx отсутствует в модуле (возможно, это было в 2009 году). Документы открываются через класс Document, например,import docx; document = docx.Document('Hello world.docx').

одпроцесса, вы можете использовать модуль 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. Надеюсь это поможет.

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

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

However, if the document has complicated tables, text boxes, embedded spreadsheets, and so forth, then it might not work as expected. Developing good MS Word filters is a very difficult process, so please bear with us as we work on getting Word documents to open correctly. If you have a Word document which fails to load, please open a Bug and include the document so we can improve the importer.

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

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

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

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

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

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

Так что

unzip -p file.docx: -p == & quot; распаковать в стандартный вывод & quot;

grep '<w:t': Выберите только строки, содержащие & lt; w: t '; (насколько я могу судить, & lt; w: t & gt; является XML-элементом Word 2007 для "текста")

sed 's/<[^<]& gt; // g & apos; *: удалить все внутри тегов

grep -v '^[[:space:]]$ & apos; *: удалить пустые строки

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

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

Так что

unzip -p file.docx: -p == & quot; распаковать в стандартный вывод & quot;

grep '<w:t': Выберите только строки, содержащие & lt; w: t '; (насколько я могу судить, & lt; w: t & gt; является XML-элементом Word 2007 для "текста")

sed 's/<[^<]& gt; // g & apos; *: удалить все внутри тегов

grep -v '^[[:space:]]$ & apos; *: удалить пустые строки

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

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

Решение Вопроса

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

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

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


docx = zipfile.ZipFile('/path/to/file/mydocument.docx')
content = docx.read('word/document.xml').decode('utf-8')
cleaned = re.sub('<(.|\n)*?>','',content)
print(cleaned)
 01 авг. 2011 г., 10:06
Чтобы удалить объекты XML, такие как & amp; nbsp; из "текста": & gt; & gt; из xml.sax.saxutils импортировать unescape & gt; text = unescape (очищено)
 28 дек. 2009 г., 04:41
Я должен повторить, что это работает только для DOCX (Word 2007 или более поздней версии). Для файлов .doc wvware - ваш лучший выбор. В зависимости от вашей среды это может быть проблематично при настройке, но это делает очень хорошую работу.
 10 окт. 2017 г., 09:38
content = docx.read ("word / document.xml"). decode ("utf-8"), в противном случае вы получите ошибку при очистке: TypeError: не можете использовать строковый шаблон в байтовоподобном объекте

что это старый вопрос, но недавно я пытался найти способ извлечь текст из файлов 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, готовой к использованию.

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

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

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

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

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

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