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

Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  1. Вызов метода экземпляра объекта null.
  2. Доступ или изменение поля объекта null.
  3. Принимая длину null, как если бы это был массив.
  4. Доступ или изменение слотов null, как если бы это был массив.
  5. Бросок null как будто это было значение Throwable.

Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null.

Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html

27
задан Cristian Ciupitu 9 June 2010 в 11:51
поделиться

11 ответов

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

20
ответ дан John Fouhy 28 November 2019 в 04:05
поделиться

Это старый вопрос? Я считаю, что такой вещи не существует. Есть только отвеченные и неотвеченные. Этот довольно без ответа, или наполовину ответили, если хотите. Что ж, способы чтения документов * .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())
2
ответ дан Dalen 28 November 2019 в 04:05
поделиться

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

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

3
ответ дан Steve Barnes 28 November 2019 в 04:05
поделиться

Если у вас установлен LibreOffice, вы можете просто вызвать его из командной строки, чтобы преобразовать файл в текст , а затем загрузить текст в Python.

3
ответ дан Community 28 November 2019 в 04:05
поделиться

Посмотрите , как работает формат doc. и создают текстовый документ с использованием PHP в linux . Первое особенно полезно. Abiword - мой рекомендуемый инструмент. Однако есть ограничения :

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

4
ответ дан Community 28 November 2019 в 04:05
поделиться

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

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

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

5
ответ дан David 28 November 2019 в 04:05
поделиться

Используйте родной модуль 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. Не делай этого!

31
ответ дан mikemaccana 28 November 2019 в 04:05
поделиться

OpenOffice.org может быть написан на Python: см. Здесь .

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

11
ответ дан Dan Lenski 28 November 2019 в 04:05
поделиться

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

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

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

Так вот:

unzip -p file.docx : -p == "unzip to stdout"

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

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

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

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

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

Так вот:

unzip -p file.docx : -p == "unzip to stdout"

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

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

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

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

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

4
ответ дан Community 28 November 2019 в 04:05
поделиться

Если вы намереваетесь использовать только модули Python без вызова подпроцесса, вы можете использовать zipfile python modude.

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

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

# 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. Надеюсь, это поможет.

4
ответ дан 28 November 2019 в 04:05
поделиться

benjamin ответ довольно неплохой. Я только что обобщил...

import zipfile, re

docx = zipfile.ZipFile('/path/to/file/mydocument.docx')
content = docx.read('word/document.xml').decode('utf-8')
cleaned = re.sub('<(.|\n)*?>','',content)
print(cleaned)
14
ответ дан 28 November 2019 в 04:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: