2008-09-24 22 views

Respuesta

18

Puede hacer una llamada por subproceso al antiword. Antiword es una utilidad de línea de comandos de Linux para volcar texto de un documento de Word. Funciona bastante bien para documentos simples (obviamente pierde formato). Está disponible a través de apt, y probablemente como RPM, o puede compilarlo usted mismo.

+0

antiword puede convertir documentos Word a XML DocBook, lo que preservará (al menos algunos) formateo. –

+0

'catdoc' también funciona si antiword no está disponible. – Xiflado

4

Eche un vistazo a how the doc format works y create word document using PHP in linux. El primero es especialmente útil. Abiword es mi herramienta recomendada. Hay limitations sin embargo:

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.

+0

sólo que sin embargo! Incluso el texto más básico guardado en el formato de Word 97 es casi imposible de obtener fácilmente sin depender de la palabra para hacerlo por usted (COM). ¡La mayoría de los documentos de Word no son HTML! –

+0

Abiword no supone que sea un documento HTML, y teniendo en cuenta la extensión de la herramienta ... No creo que haya sido "fácil" implementarlo. Abiword es una herramienta que te ayuda a leer archivos de MS Word ... y dado que el autor está interesado en la recuperación de texto, esto es suficiente. – Swati

+0

¡Ah, siempre pensé que abiword era solo otro procesador de textos! Hombre, eso me habría ahorrado algunos dolores de cabeza hace un tiempo. –

3

No estoy seguro de si va a tener mucha suerte sin utilizar COM. El formato .doc es ridículamente complejo, y a menudo se denomina "volcado de memoria" de Word en el momento de guardarlo.

En Swati, eso está en HTML, lo que está bien y muy bien, pero la mayoría de los documentos de Word no son tan agradables.

10

OpenOffice.org se puede escribir con Python: see here.

Dado que OOo puede cargar la mayoría de los archivos de MS Word sin problemas, yo diría que esa es su mejor opción.

+10

No es perfecto. Cerca, pero lejos de ser perfecto en mi experiencia (OO 2.0 - 3.0). – SpliFF

+4

Tan impecable como MS Word N + 1 abre archivos MS Words N, y mucho mejor que MS Word N + 1 abre archivos MS Words N-1, IMHO – voyager

5

Sé que esto es una vieja pregunta, pero yo estaba recientemente tratando de encontrar una manera de extraer el texto de los archivos de la palabra del MS, y la mejor solución, con mucho, lo que encontré fue con wvLib:

http://wvware.sourceforge.net/

Después de instalar la biblioteca, usarla en Python es bastante fácil:

import commands 

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

Y eso es todo. Más o menos, lo que estamos haciendo es usar la función commands.getouput para ejecutar un par de scripts de shell, concretamente wvText (que extrae texto de un documento de Word y cat para leer el resultado del archivo). Después de eso, todo el texto del documento de Word estará en la variable de salida, listo para usar.

Esperemos que esto ayude a cualquier persona que tenga problemas similares en el futuro.

4

(Nota: he publicado esto en this question así, pero parece que aquí interesa, así que disculpen el repost.)

Ahora, esto es bastante feo y bastante hacky, pero parece que funciona para mí de extracción de texto básico. Obviamente utilizar esto en un programa Qt que tendría que generar un proceso para ello, etc, pero la línea de comandos que he hackeado es:

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

Así que eso es:

descomprima el archivo -p .docx: -p == "descomprimir a la salida estándar"

grep '< w: t': agarre sólo las líneas que contenga '< w: t' (< w: t > es el elemento XML para Word 2007 "texto", por lo que yo puedo decir)

sed 's/< [^ <]> // g' *: Quitar todo dentro de las etiquetas

-v grep '^ [[: espacio:]] $ '*: Eliminar líneas en blanco

Es probable que haya una forma más eficiente de hacerlo, pero parece funcionar para mí en los pocos documentos con los que lo he probado.

Hasta donde yo sé, descomprímalo, grep y sed todos tienen puertos para Windows y cualquiera de los Unixes, por lo que debe ser razonablemente multiplataforma. A pesar de ser un poco un hack feo;)

4

Si su intención es usar módulos puramente python sin llamar a un subproceso, puede usar el 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 

Su cadena de contenido sin embargo necesita ser limpiado, una forma de hacer esto es:

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

Pero seguramente hay una forma más elegante para limpiar la cadena, probablemente mediante el módulo re . Espero que esto ayude.

+1

Para eliminar entidades XML como   de 'texto': >>> de xml.sax.saxutils importar unescape >>> texto = unescape (contenido) – aitchnyu

+0

Usando módulo re, la limpieza puede ser mucho más fácil : 'stripped_content = re.compile (b '<.*?>').sub (b '', contenido ) # strip tags' Una cosa que no pude entender en su código es, en el fragmento anterior ¿por qué no 'break' dentro del bloque' if'? –

11

La respuesta de benjamin es bastante buena. Acabo consolidado ...

import zipfile, re 

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

Debo reiterar que esto solo funciona para docx (Word 2007 o posterior). Para archivos .doc wvware es su mejor apuesta. Dependiendo de su entorno, puede ser difícil configurarlo, pero lo hace muy bien. – Chad

+3

Para eliminar entidades XML como   de 'text': >>> desde xml.sax.saxutils import unescape >>> text = unescape (limpiado) – aitchnyu

+0

content = docx.read ('word/document.xml'). decode ('utf-8') de lo contrario recibirá un error al limpiar: TypeError: no puede usar un patrón de cadena en un objeto similar a un byte –

29

utilizar el módulo docx nativa de Python. Así es como para extraer todo el texto de un documento:

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

Ver Python DocX site

También puedes ver Textract que se saca mesas, etc.

análisis de XML con regexs invoca cthulu. No lo hagas!

+0

¿está haciendo 'from docx import *' aquí? si no, ¿cómo está obteniendo 'getdocumenttext', etc.? – dbliss

+1

'opendocx' no está en el módulo (tal vez fue en 2009). Los documentos se abren a través de la clase de documento, p. 'import docx; document = docx.Document ('Hello world.docx') '. – egpbos

+0

@egpbos He actualizado el código de ejemplo para usar la generación más nueva python-docx. – mikemaccana

1

sólo una opción para la lectura de archivos 'Doc' sin usar COM: miette. Debería funcionar en cualquier plataforma.

1

Si tiene LibreOffice instalado, you can simply call it from the command line to convert the file to text, cargue el texto en Python.

+1

Ah Philip! Solo buscaba una forma de rechazar las ediciones triviales del estilo que hiciste en otra publicación mía. Traté de contactarlo directamente. ¿Podría indicar más claramente lo que está sugiriendo aquí? Esta respuesta que di aquí es en respuesta a la pregunta. ¿No es eso lo suficientemente bueno? – markling

+1

Re. sus ediciones de estilo y gramática: preferí mi propio estilo y gramática, gracias. Un buen editor no impone su propio estilo. Y realmente, ninguno de nosotros tiene suficiente tiempo libre para hacer un hechizo trivial y una comprobación de la gramática, ¿verdad? Creo que puede encontrar que es un poco excesivo. – markling

1

¿Es esta una pregunta? Creo que tal cosa no existe. Solo hay respuestas y respuestas. Este es bastante sin respuesta, o la mitad respondió si lo desea. Bueno, los métodos para leer documentos * .docx (MS Word 2007 y posteriores) sin usar interoperabilidad COM están cubiertos. Pero los métodos para extraer texto de * .doc (MS Word 97-2000), usando Python solamente, carece. ¿Esto es complicado? Para hacer: no realmente, para entender: bueno, eso es otra cosa.

Cuando no encontré ningún código terminado, leí algunas especificaciones de formato y busqué algunos algoritmos propuestos en otros idiomas.

El archivo MS Word (* .doc) es un archivo compuesto OLE2. Para no molestarte con una gran cantidad de detalles innecesarios, considéralo un sistema de archivos almacenado en un archivo. En realidad, utiliza la estructura FAT, por lo que la definición se cumple. (Hm, ¿quizás puede montarlo en bucle en Linux?) De esta forma, puede almacenar más archivos dentro de un archivo, como imágenes, etc. Lo mismo se hace en * .docx usando el archivo ZIP en su lugar. Hay paquetes disponibles en PyPI que pueden leer archivos OLE. Me gusta (olefile, compoundfiles, ...) Utilicé el paquete de archivos compuestos para abrir el archivo * .doc. Sin embargo, en MS Word 97-2000, los subarchivos internos no son XML o HTML, sino archivos binarios. Y como esto no es suficiente, cada uno contiene información sobre otro, por lo que debe leer al menos dos de ellos y desentrañar la información almacenada en consecuencia. Para comprender completamente, lea el documento PDF del cual tomé el algoritmo.

El siguiente código se compila y compila apresuradamente en un número pequeño de archivos. Por lo que puedo ver, funciona según lo previsto. A veces aparece un galimatías al principio, y casi siempre al final del texto. Y también puede haber algunos caracteres extraños entre ellos.

Aquellos de ustedes que simplemente deseen buscar texto estarán contentos. Aún así, insto a todos los que puedan ayudar a mejorar este código a que lo hagan.


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

Para leer Word 2007 y posteriores, incluyendo archivos .docx, puede utilizar el paquete de python-docx:

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

para leer archivos .doc de Word 2003 y versiones anteriores, hacer una llamada al subproceso antiword. Es necesario instalar primero antiword:

sudo apt-get install antiword 

A continuación, sólo lo llaman de su script en 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)) 
No
Cuestiones relacionadas