Подтвердить что ты не робот

Извлечение текста из текстовых файлов MS в python

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

4b9b3361

Ответ 1

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

Ответ 2

Используйте собственный модуль docx Python. Здесь, как извлечь весь текст из документа:

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

Ответ 3

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

import zipfile, re

docx = zipfile.ZipFile('/path/to/file/mydocument.docx')
content = docx.read('word/document.xml')
cleaned = re.sub('<(.|\n)*?>','',content)
print cleaned

Ответ 4

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

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

Ответ 5

Я знаю, что это старый вопрос, но я недавно пытался найти способ извлечь текст из текстовых файлов 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 и cat для чтения вывода файла). После этого весь текст из документа Word будет в переменной out, готовой к использованию.

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

Ответ 6

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

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

Ответ 7

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

Теперь, это довольно уродливо и довольно взломанно, но, похоже, для меня это работает для простого извлечения текста. Очевидно, чтобы использовать это в 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 для "текста", насколько я могу судить)

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

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

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

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

Ответ 8

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

Ответ 9

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

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

Ответ 11

Для чтения файлов Word 2007 и более поздних версий, включая файлы .docx, вы можете использовать пакет python-docx:

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

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

sudo apt-get install antiword

Затем просто вызовите его из своего python script:

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))

Ответ 12

Просто вариант для чтения файлов "doc" без использования COM: miette. Должен работать на любой платформе.

Ответ 14

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

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

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