extraction de texte à partir de fichiers MS word en python

pour travailler avec des fichiers MS word en python, il y a des extensions win32 de python, qui peuvent être utilisées dans windows. Comment faire la même chose avec linux? Il y a une bibliothèque?

26
demandé sur Cristian Ciupitu 2008-09-24 07:15:13

14 réponses

vous pouvez faire un appel de sous-processus à antiword . Antiword est un utilitaire de ligne de commande linux pour décharger du texte d'un doc word. Fonctionne assez bien pour les documents simples (évidemment il perd le formatage). Il est disponible via apt, et probablement sous forme de RPM, ou vous pouvez le compiler vous-même.

19
répondu John Fouhy 2008-09-24 04:13:03

utilisez le module natif Python docx . Voici comment extraire tout le texte d'un doc:

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

voir Python DocX site

consultez Également Textract qui sort des tables etc.

Parsing XML avec regexs appelle cthulu. Ne pas le faire!

30
répondu mikemaccana 2015-08-05 10:45:18

benjamin 's réponse est assez bonne. Je viens de consolider...

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)
12
répondu Chad 2018-07-12 04:52:49

OpenOffice.org peut être scripté avec Python: voir ici .

puisque OOo peut charger la plupart des fichiers MS Word sans problème, je dirais que c'est votre meilleure option.

11
répondu Dan Lenski 2008-09-24 03:23:42

je sais que c'est une vieille question, mais j'ai récemment essayé de trouver un moyen d'extraire du texte à partir de fichiers MS word, et la meilleure solution de loin que j'ai trouvé était avec wvLib:

http://wvware.sourceforge.net /

après avoir installé la bibliothèque, l'utiliser en Python est assez facile:

import commands

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

Et c'est tout. À peu près, ce que nous faisons, c'est en utilisant les commandes.fonction getouput pour exécuter quelques les scripts shell, à savoir wvText (qui extrait le texte d'un document Word, et cat pour lire la sortie du fichier). Après cela, le texte entier du document de mot sera dans la variable out, prêt à l'emploi.

espérons que cela aidera quiconque ayant des problèmes similaires à l'avenir.

5
répondu David 2009-01-01 01:14:38

regardez comment fonctionne le format doc et créez un document word en utilisant PHP sous linux . Le premier est particulièrement utile. Abiword est mon outil recommandé. Il y a limitations bien que:

cependant, si le document comporte des tableaux compliqués, des boîtes de texte, des feuilles de calcul intégrées, etc., il se peut qu'il ne fonctionne pas comme prévu. Développer une bonne SEP Les filtres de mots est un processus très difficile, alors s'il vous plaît patientez avec nous que nous travaillons à obtenir des documents Word pour ouvrir correctement. Si vous avez un document Word qui ne se charge pas, veuillez ouvrir un Bug et inclure le document afin que nous puissions améliorer l'importateur.

4
répondu Swati 2017-05-23 12:34:21

(Note: j'ai posté ceci sur cette question aussi, mais elle semble pertinente ici, alors veuillez excuser le report.)

Maintenant, c'est assez laid et assez hacky, mais il semble fonctionner pour moi pour le texte de base de l'extraction. De toute évidence, pour utiliser ceci dans un programme Qt, vous devez lancer un processus pour cela, etc, mais la ligne de commande que j'ai hacké ensemble est:

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

donc c'est:

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

grep ' : saisissez simplement les lignes contenant ' est l'élément XML Word 2007 pour "texte", pour autant que je puisse le dire)

sed 's/<[^<] >//g'*: Supprimer tout à l'intérieur de balises

grep-v '^[[[: espace:]] $'*: supprimer les lignes vides

il y a probablement un moyen plus efficace de faire cela, mais il semble fonctionner pour moi sur les quelques docs que j'ai testé avec.

autant que je sache, unzip, grep et sed ont tous des ports pour Windows et N'importe lequel des Unixes, donc il devrait être raisonnablement multiplate-forme. Despit d'être un peu d'un vilain hack ;)

4
répondu Ben Williams 2017-05-23 12:10:01

si votre intention est d'utiliser des modules purement python sans appeler de sous-processus, vous pouvez utiliser le modude 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

votre chaîne de contenu doit cependant être nettoyée, une façon de le faire est:

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

mais il y a sûrement une façon plus élégante de nettoyer la chaîne, probablement en utilisant le module re. Espérons que cette aide.

4
répondu benjamin 2009-11-12 16:18:16

Unoconv pourrait aussi être une bonne alternative: http://linux.die.net/man/1/unoconv

3
répondu fccoelho 2012-05-16 11:35:57

Je ne suis pas sûr que vous allez avoir beaucoup de chance sans utiliser COM. Le. le format doc est ridiculement complexe, et est souvent appelé un "dump mémoire" de mot au moment de sauver!

chez Swati, C'est en HTML, ce qui est très bien, mais la plupart des documents word ne sont pas si beaux!

3
répondu William Keller 2016-06-21 06:32:46

si vous avez LibreOffice installé, vous pouvez simplement l'appeler depuis la ligne de commande pour convertir le fichier en texte , puis Charger le texte en Python.

2
répondu markling 2017-05-23 12:10:01

est-ce une vieille question? Je crois qu'une telle chose n'existe pas. Il n'y a que des réponses et des réponses. Celui-ci est plutôt sans réponse, ou à moitié répondu si vous le souhaitez. Ainsi, les méthodes de lecture *.docx (MS Word 2007 et versions ultérieures) les documents qui n'utilisent pas COM interop sont tous couverts. Mais les méthodes pour extraire le texte de *.doc (MS Word 97-2000), utilisant Python seulement, manque. Est-ce compliqué? Faire: pas vraiment, comprendre: Eh bien, c'est autre chose.

Quand je n'ai pas trouvé de code fini, j'ai lu des spécifications de format et j'ai trouvé des algorithmes proposés dans d'autres langues.

MS Word (*.doc) est un fichier composé de OLE2. De ne pas vous déranger avec beaucoup de détails inutiles, pensez-y comme un système de fichiers stockés dans un fichier. Il utilise en fait la structure de la graisse,donc la définition tient. (HM, peut-être que vous pouvez le monter en boucle sous Linux???) De cette façon, vous pouvez stocker plus de fichiers dans un fichier, comme des images, etc. La même chose est faite en *.docx en utilisant L'archive ZIP à la place. Il y a des paquets disponibles sur PyPI qui peuvent lire des fichiers OLE. Comme (olefile, compoundfiles,...) J'ai utilisé compoundfiles package pour ouvrir *.fichier doc. Cependant, dans MS Word 97-2000, les sous-Fichiers internes ne sont pas XML ou HTML, mais des fichiers binaires. Et comme ce n'est pas suffisant, chaque contient une information sur l'autre, donc vous devez lire au moins deux d'entre eux et déchiffrer les informations stockées en conséquence. Pour comprendre pleinement, lisez le document PDF à partir duquel j'ai pris l'algorithme.

Le Code

ci-dessous est composé à la hâte et testé sur un petit nombre de fichiers. Aussi loin que je peux voir, il fonctionne comme prévu. Parfois, certains charabia apparaît au début, et presque toujours à la fin du texte. Et il peut y avoir des personnages bizarres entre les deux.

ceux d'entre vous qui veulent juste chercher du texte seront heureux. Encore, j'exhorte tous ceux qui peuvent aider à améliorer ce code pour le faire.


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
répondu Dalen 2015-06-01 21:07:18

pour lire Word 2007 et les fichiers suivants, y compris .les fichiers docx, vous pouvez utiliser le paquet python-docx :

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

à lire .les fichiers doc de Word 2003 et plus tôt, font un appel de sous-processus à antiword . Vous devez d'abord installer antiword:

sudo apt-get install antiword

alors appelez-le simplement à partir de votre script 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))
2
répondu Antoine Dusséaux 2016-08-05 07:28:31

Juste une option pour la lecture de 'doc' des fichiers sans utiliser de COM: miette . Ça devrait marcher sur n'importe quelle plateforme.

1
répondu alecxe 2013-02-12 09:25:30