28

为了在 python 中处理 MS word 文件,有 python win32 扩展,可以在 windows 中使用。我如何在linux中做同样的事情?有图书馆吗?

4

15 回答 15

32

使用本机 Python docx 模块。以下是如何从文档中提取所有文本:

document = docx.Document(filename)
docText = '\n\n'.join(
    paragraph.text for paragraph in document.paragraphs
)
print(docText)

请参阅Python DocX 站点

还可以查看提取表格等的Textract 。

使用正则表达式解析 XML 会调用 cthulu。不要这样做!

于 2009-12-30T12:17:09.493 回答
21

您可以对antiword进行子流程调用。Antiword 是一个 linux 命令行实用程序,用于从 word doc 中转储文本。适用于简单文档(显然它会丢失格式)。它可以通过 apt 获得,并且可能以 RPM 的形式提供,或者您可以自己编译。

于 2008-09-24T04:13:03.270 回答
17

本杰明的答案是一个很好的答案。我刚刚巩固了...

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)
于 2009-12-28T03:39:54.190 回答
11

OpenOffice.org 可以使用 Python 编写脚本:请参见此处

由于 OOo 可以完美地加载大多数 MS Word 文件,我认为这是您最好的选择。

于 2008-09-24T03:23:42.873 回答
6

我知道这是一个老问题,但我最近试图找到一种从 MS Word 文件中提取文本的方法,到目前为止我发现的最佳解决方案是使用 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 函数来运行几个 shell 脚本,即 wvText(从 Word 文档中提取文本,并使用 cat 读取文件输出)。之后,Word 文档中的整个文本将在 out 变量中,可供使用。

希望这将有助于将来遇到类似问题的任何人。

于 2009-01-01T01:14:38.260 回答
4

看看doc 格式是如何工作的,并在 linux 中使用 PHP 创建 word 文档。前者特别有用。Abiword是我推荐的工具。但是有一些限制

但是,如果文档包含复杂的表格、文本框、嵌入的电子表格等,那么它可能无法按预期工作。开发好的 MS Word 过滤器是一个非常困难的过程,所以请耐心等待我们努力让 Word 文档正确打开。如果您有一个无法加载的 Word 文档,请打开一个 Bug 并包含该文档,以便我们改进导入器。

于 2008-09-24T03:17:26.960 回答
4

(注意:我也在这个问题上发布了这个,但在这里似乎相关,所以请原谅转发。)

现在,这很丑陋而且很hacky,但它似乎对我来说适用于基本的文本提取。显然,要在 Qt 程序中使用它,您必须为其生成一个进程等,但我一起破解的命令行是:

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

所以那是:

unzip -p file.docx : -p == "解压到标准输出"

grep '<w:t':仅抓取包含 '<w:t' 的行(据我所知,<w:t> 是“文本”的 Word 2007 XML 元素)

sed 's/<[^<] >//g'*:删除标签内的所有内容

grep -v '^[[:space:]] $'*: 删除空行

可能有一种更有效的方法可以做到这一点,但它似乎对我测试过的少数文档有用。

据我所知,unzip、grep 和 sed 都有适用于 Windows 和任何 Unix 的端口,所以它应该是合理的跨平台的。尽管有点丑陋的黑客;)

于 2009-08-11T05:38:51.560 回答
4

如果您打算使用纯 python 模块而不调用子进程,则可以使用 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

但是,您的内容字符串需要清理,这样做的一种方法是:

# 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 模块。希望这可以帮助。

于 2009-11-12T16:18:16.963 回答
4

要读取 Word 2007 及更高版本的文件,包括 .docx 文件,您可以使用python-docx包:

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

要从 Word 2003 及更早版本读取 .doc 文件,请对antiword进行子进程调用。你需要先安装antiword:

sudo apt-get install antiword

然后从你的 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))
于 2016-08-03T18:17:37.073 回答
3

我不确定如果不使用 COM,您是否会很幸运。.doc 格式非常复杂,在保存时通常被称为 Word 的“内存转储”!

在 Swati,那是在 HTML 中,这很好而且很漂亮,但是大多数 word 文档不是那么好!

于 2008-09-24T03:19:53.460 回答
3

Unoconv 也可能是一个不错的选择:http ://linux.die.net/man/1/unoconv

于 2012-05-16T11:35:57.933 回答
3

如果您安装了 LibreOffice,您可以简单地从命令行调用它来将文件转换为 text,然后将文本加载到 Python 中。

于 2015-05-08T11:31:23.600 回答
2

这是一个老问题吗?我相信这样的事情是不存在的。只有回答的和未回答的。如果您愿意,这个问题几乎没有答案,或者回答了一半。好吧,不使用 COM 互操作读取 *.docx(MS Word 2007 及更高版本)文档的方法都已涵盖。但是,仅使用 Python 从 *.doc (MS Word 97-2000) 中提取文本的方法缺乏。这很复杂吗?要做:不是真的,要理解:嗯,那是另一回事。

当我没有找到任何完成的代码时,我阅读了一些格式规范并挖掘了一些其他语言的建议算法。

MS Word (*.doc) 文件是一个 OLE2 复合文件。不要用很多不必要的细节来打扰您,将其视为存储在文件中的文件系统。它实际上使用了FAT结构,所以定义成立。(嗯,也许您可​​以在 Linux 中循环挂载它???)这样,您可以在一个文件中存储更多文件,例如图片等。在 *.docx 中也可以使用 ZIP 存档代替。PyPI 上有可以读取 OLE 文件的包。像(olefile,compoundfiles,...)我使用 Compoundfiles 包打开 *.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())
于 2015-06-01T20:20:14.347 回答
1

只是一个不使用 COM 读取“doc”文件的选项:miette。应该在任何平台上工作。

于 2013-02-12T09:25:30.153 回答
-1

Aspose.Words Cloud SDK for Python是一个独立于平台的解决方案,用于将 MS Word/Open Office 文件转换为文本。它是一个商业产品,但免费试用计划提供每月 150 次 API 调用。

PS:我是 Aspose 的开发人员布道师。

# For complete examples and data files, please go to https://github.com/aspose-words-cloud/aspose-words-cloud-python
# Import module
import asposewordscloud
import asposewordscloud.models.requests
from shutil import copyfile

# Please get your Client ID and Secret from https://dashboard.aspose.cloud.
client_id='xxxxxxx-xxxx-xxxx-xxxxx-xxxxxxxxxx'
client_secret='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

words_api = asposewordscloud.WordsApi(client_id,client_secret)
words_api.api_client.configuration.host='https://api.aspose.cloud'

filename = 'C:/Temp/02_pages.docx'
dest_name = 'C:/Temp/02_pages.txt'
#Convert RTF to text
request = asposewordscloud.models.requests.ConvertDocumentRequest(document=open(filename, 'rb'), format='txt')
result = words_api.convert_document(request)
copyfile(result, dest_name)
于 2021-01-11T16:27:22.480 回答