Pregunta

Para trabajar con archivos de MS Word en Python, existen extensiones de Python Win32, que se pueden usar en Windows.¿Cómo hago lo mismo en Linux?¿Hay alguna biblioteca?

¿Fue útil?

Solución

Podrías hacer una llamada de subproceso a antipalabra.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 puedes compilarlo tú mismo.

Otros consejos

Utilizar el módulo docx nativo de Python.A continuación se explica cómo 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 Sitio Python DocX

También echa un vistazo Extracto de texto que saca mesas, etc.

El análisis de XML con expresiones regulares invoca a cthulu.¡No lo hagas!

BenjamínLa respuesta es bastante buena.Me acabo de consolidar...

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)

OpenOffice.org se puede programar con Python: mira aquí.

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

Sé que esta es una vieja pregunta, pero recientemente estuve tratando de encontrar una manera de extraer texto de archivos de MS Word, y la mejor solución 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.Básicamente, 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.

Con suerte, esto ayudará a cualquiera que tenga problemas similares en el futuro.

Echa un vistazo a cómo funciona el formato de documento y crear un documento de Word usando PHP en Linux.El primero es especialmente útil. Abipalabra es mi herramienta recomendada.Hay limitaciones aunque:

Sin embargo, si el documento tiene tablas complicadas, cuadros de texto, hojas de cálculo incrustadas, etc., es posible que no funcione como se esperaba.Desarrollar buenos filtros de MS Word es un proceso muy difícil, así que tenga paciencia mientras trabajamos para que los documentos de Word se abran correctamente.Si tiene un documento de Word que no se carga, abra un error e incluya el documento para que podamos mejorar el importador.

(Nota:Publiqué esto en esta pregunta también, pero parece relevante aquí, así que disculpe la publicación nuevamente).

Ahora bien, esto es bastante feo y complicado, pero parece funcionar para mí para la extracción básica de texto.Obviamente, para usar esto en un programa Qt tendrías que generar un proceso para ello, etc., pero la línea de comando que he pirateado es:

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

Así que eso es:

descomprimir -p archivo.docx:-p == "descomprimir en la salida estándar"

grep '<w:t':Tome solo las líneas que contienen '<w:t' (<w:t> es el elemento XML de Word 2007 para "texto", hasta donde yo sé)

sed's/<[^<]>//g'*:Eliminar todo lo que esté dentro de las etiquetas

grep -v '^[[:espacio:]]psEliminar líneas en blanco

Probablemente exista una forma más eficiente de hacer esto, pero parece funcionar para mí en los pocos documentos con los que lo he probado.

Hasta donde yo sé, unzip, grep y sed tienen puertos para Windows y cualquiera de los Unix, por lo que debería ser razonablemente multiplataforma.A pesar de ser un truco un poco feo;)

Si su intención es utilizar módulos puramente de Python sin llamar a un subproceso, puede usar el modo zipfile de Python.

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

Sin embargo, su cadena de contenido debe limpiarse; una forma de hacerlo 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 manera más elegante de limpiar la cadena, probablemente usando el módulo re.Espero que esto ayude.

Unoconv también podría ser una buena alternativa: http://linux.die.net/man/1/unoconv

Si tienes LibreOffice instalado, simplemente puedes llamarlo desde la línea de comando para convertir el archivo a texto, luego cargue el texto en Python.

No estoy seguro de si tendrás mucha suerte sin usar COM.El formato .doc es ridículamente complejo y, a menudo, se le llama "volcado de memoria" de Word al momento de guardar.

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

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

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, realice una llamada de subproceso a antipalabra.Primero necesitas instalar antiword:

sudo apt-get install antiword

Luego simplemente llámalo desde tu script de 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))

¿Es esta una vieja pregunta?Creo que tal cosa no existe.Sólo las hay contestadas y sin respuesta.Éste está bastante sin respuesta, o medio respondido si lo desea.Bueno, se tratan todos los métodos para leer documentos *.docx (MS Word 2007 y posteriores) sin utilizar interoperabilidad COM.Pero faltan métodos para extraer texto de *.doc (MS Word 97-2000), usando Python únicamente.¿Es esto complicado?Hacer:Realmente no, para entender:bueno, esa es otra cosa.

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

El archivo MS Word (*.doc) es un archivo compuesto OLE2.Para no molestarlo con muchos detalles innecesarios, considérelo como un sistema de archivos almacenado en un archivo.En realidad, utiliza la estructura FAT, por lo que la definición es válida.(Hm, tal vez pueda montarlo en bucle en Linux?) De esta manera, puede almacenar más archivos dentro de un archivo, como imágenes, etc.Lo mismo se hace en *.docx utilizando en su lugar un archivo ZIP.Hay paquetes disponibles en PyPI que pueden leer archivos OLE.Al igual (olfile, componefiles, ...) utilicé el paquete CompoundFiles para abrir *.doc archivo.Sin embargo, en MS Word 97-2000, los subarchivos internos no son XML ni HTML, sino archivos binarios.Y como esto no es suficiente, cada uno contiene información sobre el otro, por lo que debes leer al menos dos de ellos y desentrañar la información almacenada en consecuencia.Para comprenderlo completamente, lea el documento PDF del que tomé el algoritmo.

El código siguiente se compone y prueba muy apresuradamente en una pequeña cantidad de archivos.Por lo que puedo ver, funciona según lo previsto.A veces aparece algún galimatías al principio y casi siempre al final del texto.Y también puede haber algunos personajes extraños en el medio.

Aquellos de ustedes que sólo deseen buscar texto estarán felices.Aún así, insto a cualquiera que pueda ayudar a mejorar este código a que lo haga.


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

Sólo una opción para leer archivos 'doc' sin usar COM: miette.Debería funcionar en cualquier plataforma.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top