Python で MS Word ファイルを操作するために、Windows で使用できる python win32 拡張機能があります。Linuxで同じことを行うにはどうすればよいですか? ライブラリはありますか?
15 に答える
アンチワードのサブプロセス呼び出しを行うことができます。Antiwordは、WordドキュメントからテキストをダンプするためのLinuxコマンドラインユーティリティです。単純なドキュメントには非常にうまく機能します(明らかにフォーマットが失われます)。aptから、おそらくRPMとして入手できます。または、自分でコンパイルすることもできます。
ベンジャミンの答えはかなり良いものです。統合したばかりで...
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 は Python でスクリプト化できます:こちら を参照してください。
OOo はほとんどの MS Word ファイルを問題なくロードできるので、それが最善の策だと思います。
これは古い質問であることは承知していますが、最近、MS ワード ファイルからテキストを抽出する方法を見つけようとしていました。
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.getoput 関数を使用して、いくつかのシェル スクリプト、つまり wvText (Word 文書からテキストを抽出し、cat を使用してファイル出力を読み取る) を実行しています。その後、Word 文書のテキスト全体が out 変数に格納され、すぐに使用できるようになります。
うまくいけば、これは将来同様の問題を抱えている人に役立つでしょう.
.docx ファイルを含む Word 2007 以降のファイルを読み取るには、python-docxパッケージを使用できます。
from docx import Document
document = Document('existing-document-file.docx')
document.save('new-file-name.docx')
Word 2003 以前から .doc ファイルを読み取るには、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))
doc 形式がどのように機能するかを見て、Linux で PHP を使用して Word 文書を作成します。前者は特に便利です。Abiwordは私の推奨ツールです。ただし、制限があります。
ただし、ドキュメントに複雑な表、テキスト ボックス、埋め込みスプレッドシートなどが含まれている場合、期待どおりに機能しない可能性があります。優れた MS Word フィルタを開発するのは非常に難しいプロセスです。Word ドキュメントが正しく開くように取り組んでいますので、しばらくお待ちください。読み込みに失敗した Word ドキュメントがある場合は、Bug を開いてドキュメントを含めてください。インポーターを改善できます。
(注:この質問にも投稿しましたが、ここに関連しているようですので、再投稿をお許しください。)
さて、これはかなり醜く、かなりハックですが、基本的なテキスト抽出にはうまくいくようです。明らかに、これを Qt プログラムで使用するには、そのためのプロセスを生成する必要がありますが、一緒にハッキングしたコマンド ラインは次のとおりです。
unzip -p file.docx | grep '<w:t' | sed 's/<[^<]*>//g' | grep -v '^[[:space:]]*$'
だから〜だ:
unzip -p file.docx : -p == "unzip to stdout"
grep '<w:t' : '<w:t' を含む行だけを取得します (<w:t> は、私が知る限り、「テキスト」の Word 2007 XML 要素です)
sed 's/<[^<] >//g'*: タグ内のすべてを削除
grep -v '^[[:space:]] $'*: 空白行を削除します
これを行うためのより効率的な方法がある可能性がありますが、私がテストしたいくつかのドキュメントではうまくいくようです。
私が知る限り、unzip、grep、および sed はすべて Windows および任意の Unix 用のポートを備えているため、適度にクロスプラットフォームである必要があります。少し醜いハックであるにもかかわらず;)
サブプロセスを呼び出さずに純粋な 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
ただし、コンテンツ文字列をクリーンアップする必要があります。これを行う 1 つの方法は次のとおりです。
# 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 モジュールを使用して、文字列をクリーンアップするためのよりエレガントな方法が確かにあります。お役に立てれば。
COM を使わずにうまくいくかどうかはわかりません。.doc 形式はとてつもなく複雑で、保存時に Word の "メモリ ダンプ" と呼ばれることがよくあります。
Swati では、それは HTML で書かれています。これは立派でおしゃれですが、ほとんどの Word 文書はあまり良くありません!
Unoconv も良い代替手段かもしれません: http://linux.die.net/man/1/unoconv
LibreOffice がインストールされている場合は、コマンド ラインから呼び出してファイルをテキストに変換し、そのテキストを Python に読み込むことができます。
これは古い質問ですか?そんなものは存在しないと信じています。答えられるものと答えられないものだけがあります。これはほとんど回答されていないか、必要に応じて半分回答されています。COM 相互運用機能を使用せずに *.docx (MS Word 2007 以降) ドキュメントを読み取る方法はすべてカバーされています。しかし、Python のみを使用して *.doc (MS Word 97-2000) からテキストを抽出する方法はありません。これは複雑ですか?すること: そうではない、理解すること: まあ、それは別のことです。
完成したコードが見つからないときは、いくつかのフォーマット仕様を読み、提案されたアルゴリズムを他の言語で掘り出しました。
MS Word (*.doc) ファイルは OLE2 複合ファイルです。多くの不必要な詳細に煩わされないように、ファイルに格納されたファイルシステムと考えてください。実際には FAT 構造を使用しているため、定義は成り立ちます。(うーん、Linux でループ マウントできるかも???) この方法で、写真などのファイル内により多くのファイルを保存できます。代わりに ZIP アーカイブを使用して、*.docx でも同じことができます。OLE ファイルを読み取ることができる PyPI で利用可能なパッケージがあります。(olefile、compoundfiles、...) のように、compoundfiles パッケージを使用して *.doc ファイルを開きました。ただし、MS Word 97-2000 では、内部サブファイルは XML または HTML ではなく、バイナリ ファイルです。そして、これだけでは不十分なため、それぞれに他の情報が含まれているため、少なくとも 2 つの情報を読み取り、それに応じて保存された情報を解明する必要があります。完全に理解するには、アルゴリズムの元となった 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())
COMを使用せずに「doc」ファイルを読み取るための単なるオプション:miette。どのプラットフォームでも動作するはずです。