Pythonを使用してWordドキュメントからテキストと画像を抽出する

Wordドキュメントからコンテンツを抽出することは、データベースにコンテンツを保存したり、他のプログラムにコンテンツをインポートしたり、AIトレーニングに使用したり、他のドキュメントを作成したりなど、その他の操作を容易にすることができます。[Spire.Doc for Python](https://www.e-iceblue.com/Introduce/doc-for-python.html)を使用すると、大量のコピー&ペースト操作や複雑なコードなしに、Wordドキュメントからテキストと画像のコンテンツを簡単に抽出できます。この記事では、簡単なコードを使用して**Wordドキュメントからテキストと画像のコンテンツを抽出および保存する方法**について説明します。

- **[Wordドキュメントからテキストを抽出してTXTファイルに書き込む](#wordドキュメントからテキストを抽出してtxtファイルに書き込む)**
- **[Wordドキュメントから画像を抽出して保存](#wordドキュメントから画像を抽出して保存)**

### Spire.Doc for Pythonのインポート
このツールを使用してWordドキュメントを操作する前に、プロジェクトにインポートする必要があります。[Spire.Doc for Pythonの公式ウェブサイト]()からダウンロードするか、pipで直接インストールできます。コードは次のとおりです:
```python
pip install Spire.Doc
pip install plum-dispatch==1.7.4
```

**サンプル文書**
![Pythonを使用してWordドキュメントからテキストと画像を抽出する](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/3453b2d8-1a89-660b-3df4-a9c121de2a43.png)

## Wordドキュメントからテキストを抽出してTXTファイルに書き込む
Spire.Doc for Pythonの **Document.GetText()** メソッドを使用すると、Wordドキュメント内のすべてのテキストを取得して文字列を返すことができます。返された文字列をテキストファイルに書き込んで保存できます。操作手順は次のとおりです:
- **Document** のオブジェクトを作成します。
- **Document.LoadFromFile()** メソッドを使用してWordドキュメントを読み込みます。
- **Document.GetText()** メソッドを使用してドキュメント内のテキストを取得します。
- 取得したテキストをテキストファイルに書き込みます。

**コードサンプル**
**Python**
```python
from turtle import st
from spire.doc import *
from spire.doc.common import *

def WriteAllText(fname:str,text:List[str]):
        fp = open(fname,"w")
        for s in text:
            fp.write(s)
        fp.close()

inputFile = "サンプル.docx"
outputFile =  "取得したテキスト.txt"
     
#Documentのオブジェクトを作成
document = Document()

#Wordドキュメントを読み込み
document.LoadFromFile(inputFile)

#ドキュメント内のテキストを取得
text = document.GetText()

#テキストをテキストファイルに書き込み
WriteAllText(outputFile, text)
document.Close()
```

**抽出されたテキスト**
![Wordドキュメントからテキストを抽出してTXTファイルに書き込む](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/c64f700b-1095-72e7-7732-cdf98ee27b73.png)


## Wordドキュメントから画像を抽出して保存

画像の抽出は少し複雑で、ドキュメント要素の子オブジェクトが画像かコンポジットオブジェクトかを判断する必要があります。画像の場合は保存し、コンポジットオブジェクトの場合は子オブジェクトに画像が含まれているかどうかをさらに判断する必要があります。操作手順は次のとおりです:
- **Document** のオブジェクトを作成します。
- **Document.loadFromFile()** メソッドを使用してWordドキュメントを読み込みます。
- コンポジットオブジェクトのキューを作成し、ドキュメント要素をそこに入れます。
- 抽出された画像を保存するリストを作成します。
- ドキュメント要素を反復処理し、各ノードの子オブジェクトをトラバースしてコンポジットオブジェクトまたは画像オブジェクトかをチェックします。
- 子要素が画像オブジェクトかどうかを確認します。そうであれば、画像データを抽出して抽出された画像リストに追加します。
- 子要素がコンポジットオブジェクトかどうかを確認します。そうであれば、キューに追加してさらに判断を続けます。
- 画像をフォルダに保存します。

**コードサンプル**
**Python**
```python
import queue
from spire.doc import *
from spire.doc.common import *
import os

outputPath = "画像/" 
inputFile = "サンプル.docx"

if not os.path.exists(outputPath):
    os.makedirs(outputPath)

#Documentのオブジェクトを作成
document = Document()

#Wordドキュメントを読み込み
document.LoadFromFile(inputFile)

#キューを作成してドキュメント要素を入れる
nodes = queue.Queue()
nodes.put(document)

#リストを作成
images = []

#ドキュメント要素をループして処理
while nodes.qsize() > 0:
    node = nodes.get()
    for i in range(node.ChildObjects.Count):
        #ドキュメント要素の子オブジェクトを取得
        child = node.ChildObjects.get_Item(i)
        #子オブジェクトが画像か判断
        if child.DocumentObjectType == DocumentObjectType.Picture:
            picture = child if isinstance(child, DocPicture) else None
            dataBytes = picture.ImageBytes
            #リストに追加
            images.append(dataBytes)
        #子オブジェクトがコンポジットオブジェクトか判断 
        elif isinstance(child, ICompositeObject):
            #キューに追加
            nodes.put(child if isinstance(child, ICompositeObject) else None)

#画像を保存
for i, item in enumerate(images):
    fileName = "画像-{}.png".format(i)
    with open(outputPath+fileName,'wb') as imageFile:
        imageFile.write(item)
document.Close()
```

**抽出された画像**
![Wordドキュメントから画像を抽出して保存](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/f157a686-ca84-f36f-cd33-726dfae01314.png)

抽出されたテキストは保存時に評価情報が付加されるので、テキスト冒頭の評価情報を直接削除することができます。抽出された画像には透かしは入りません。

> **以上がSpire.Doc for Pythonを使用してWordドキュメントからテキストと画像を抽出する方法の紹介です。 Spire.Doc for Pythonは他にもたくさんのドキュメント操作がサポートされています。オフィシャルサイトをチェックしたり、[Spire.Docフォーラム](https://www.e-iceblue.com/forum/spire-doc-f6.html)でディスカッションに参加したりできます。**