LINUX.ORG.RU

Декодировать строку байтов?

 


0

2

Я использую Python 3. Пытаюсь извлечь текст из файлов doc (Word 1997-2003). С этой целью установил olefile:

Python 3.4.2 (default, Oct  8 2014, 13:14:40) 
[GCC 4.9.1] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import olefile
>>> import os
>>> file='/tmp/abc.doc'
>>> os.path.exists(file)
True
>>> olefile.isOleFile(file)
True
>>> ole=olefile.OleFileIO(file)
>>> ole.exists('WordDocument')
True
>>> ole.openstream('WordDocument').read()

В файле написано «test = тест» (не важно, генератор - MSO или OO, проблема сохраняется). В результате же read() получаю на входе поток байтов (привожу фрагмент):

b'\xec\xa5\x01\x01M \t\x04\x00\x00\xf0\x12\xbf\x00
Пытаюсь раскодировать:
>>> ole.openstream('WordDocument').read().decode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 0-1: invalid continuation byte
Игнорирую ошибки:
ole.openstream('WordDocument').read().decode('utf-8',errors='ignore')
Получаю (фрагмент):
'\x01\x01M \t\x04\x00\x00\x12\x00\x00\x00\x00
Как мне это правильно раскодировать?

Deleted

так не факт, что это utf8, я бы сказал даже, слабо на него похоже, больше скорее какой-нибудь cp1251, cp1252, cp866 или вообще, китайское чего

Dred ★★★★★
()

Пытаюсь раскодировать

Зачем? Это же бинарный файл, там нет текста в чистом виде.

mashina ★★★★★
()

Я не работал с olefile, но вангую, что ты что-то не так делаешь. Судя по всему, ole.openstream('WordDocument').read() возвращает не чистый текст, а непонятно что. Может, над этими данными надо ещё какое-то действие проделать, чтобы вычленить текст?

proud_anon ★★★★★
()

Вообще такие штуки раскодируются с помощью codecs.decode(BYTES, «unicode_escape»), но в данном случае это не даст того результата, который ожидается

Balantay
()
Ответ на: комментарий от proud_anon

Я взял методику отсюда. WordDocument - это бинарный поток, который, как выясняется, требует парсера, который неизвестно откуда взять. Перед тем, как я понял, что olefile используется для чтения/записи OLE-потоков, а не чистого текста, я пытался преобразовать байты в строку, и, на примере текста на английском, получилось вполне неплохо, только в начале и в конце было много мусора.

Deleted
()
Ответ на: комментарий от Balantay

Наверное, можно. Но мне хотелось сделать кроссплатформенно, к тому же, python-docx уже есть и извлекает текст весьма неплохо, потому что анализируется XML. А блоб doc еще и распарсить нужно суметь, несмотря на то, что ему уже много лет, и, по идее, проблем c наличием парсеров быть не должно.

Deleted
()

А что говорит chardet?

E ★★★
()

У меня вот так получилось

import olefile
import os

file='test2.doc'

ole = olefile.OleFileIO(file)
doc = ole.openstream('WordDocument')
doc.seek(2048) # skip header
data = doc.read(25)      
print(data.decode('utf-16-le',errors='ignore'))
ole.close()

ThePretender
()
Ответ на: комментарий от Deleted

Честно, хз. Надо в hex`е смотреть. Там либо стоп-бит какой нибудь, либо размер в ole.get_size('WordDocument') указан.

ThePretender
()

subprocess + catdoc

olefile тебя не спасёт. DOC достаточно запутанный формат, для того чтобы попытки читать по конкретному смещению и «стоп-биту» были удачны только на конкретном файле.

frob ★★★★★
()
Ответ на: комментарий от Balantay

Под Python 3 его не нашел. К тому же, насколько я понял по описанию, это просто набор утилит, аналогичный subprocess.call.

Deleted
()
Ответ на: комментарий от Balantay

Сделал так. Как выясняется, извлечение текста по скорости равнозначно запуску Word, разве что Word иногда тупит на шаблонах. При этом, извлечение из docx с помощью python-docx быстрее. А вот с бинарным doc пока не разобрался.

Deleted
()
Ответ на: комментарий от Deleted

Повторять как они ты всё равно не захочешь =)

Вероятно самый простой вариант — catdoc. Но если тебе так хочется python, да ещё и LO, то можно попробовать питоньи биндинги к UNO.

frob ★★★★★
()
Ответ на: комментарий от frob

Повторять как они ты всё равно не захочешь =)

Такие жесткие костыли? :)

Вероятно самый простой вариант — catdoc.

Пробовал то ли catdoc, то ли antiword, какой-то из них терял фрагменты текста. К тому же, что-то кроссплатформенное, желательно, без subprocess.call, все равно лучше - по работе нужна и винда, а не только линукс.

Но если тебе так хочется python, да ещё и LO

Все, что нужно, написано на питоне, поэтому логично было бы продолжать на питоне. LO интересен только в плане парсинга, думал, есть какие-то универсальные алгоритмы или библиотеки для парсинга doc/rtf.

Deleted
()
Ответ на: комментарий от frob

Спасибо за ссылку.

fcStshfOrig
lcbStshfOrig
fcStshf
lcbStshf
fcPlcffndRef
lcbPlcffndRef
fcPlcffndTxt
lcbPlcffndTxt
fcPlcfandRef

fcPgdMotherOldOld
lcbPgdMotherOldOld
fcBkdMotherOldOld
lcbBkdMotherOldOld

Это ж надо было так упороться...

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Deleted

Если приспособиться, то в этих верблюдах начинает проглядывать система. А так бардак редкостный и ковыряться в нём удовольствия мало.

frob ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.