0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PythonでPowerPointからテキストを抽出する方法|スライド・表・ノート・コメント対応

0
Posted at

PowerPointのテキストは、スライド上のテキストボックスだけに入っているわけではありません。表のセルや発表者ノート、コメントなどにもテキストが含まれています。

プレゼン資料の内容を検索したり、議事録や社内資料に再利用したりするとき、これらのテキストをまとめて取得できると便利です。特にファイル数が多い場合は、Pythonで自動化しておくと手作業をかなり減らせます。

この記事では、Spire.Presentation for Python を使って、PowerPointから次の4種類のテキストを抽出する方法を紹介します。

  • スライド上のテキスト
  • 表のセル内のテキスト
  • 発表者ノート
  • コメント

最後に、書式情報を一緒に取得する方法と、複数のPowerPointをまとめて処理する方法も紹介します。

環境

今回は Spire.Presentation for Python を使います。

PowerPointのスライドや図形だけでなく、表、ノート、コメントなどにもアクセスできるので、PowerPoint内のさまざまなテキストを扱うのに便利です。

まずはインストールします。

pip install Spire.Presentation

インストール後、Pythonから読み込みます。

from spire.presentation.common import *
from spire.presentation import *

スライドからテキストを抽出する

まずは、もっとも基本的なスライド上のテキストを取得してみます。

PowerPointでは、テキストボックスやテキストを含む図形は IAutoShape として扱われます。各Shapeを確認し、TextFrame.Paragraphs から段落ごとのテキストを取得します。

from spire.presentation.common import *
from spire.presentation import *

inputFile = "./Data/ExtractText.pptx"
outputFile = "ExtractText.txt"

presentation = Presentation()
presentation.LoadFromFile(inputFile)

sb = []

# 各スライドのテキストを取得
for slide in presentation.Slides:
    for shape in slide.Shapes:
        if isinstance(shape, IAutoShape):
            for tp in shape.TextFrame.Paragraphs:
                sb.append(tp.Text)

# テキストファイルに保存
with open(outputFile, "w", encoding="utf-8") as fp:
    for s in sb:
        fp.write(s + "\n")

presentation.Dispose()

ポイントは IAutoShape のチェックです。

スライドには画像や表、グラフなど、さまざまなShapeが含まれています。ここではテキストを持つ IAutoShape を対象にして、TextFrame.Paragraphs から文字列を取り出しています。

Paragraph.Text を使えば、段落単位でテキストを取得できます。

また、テキストファイルは encoding="utf-8" を指定して保存しています。日本語を含むPowerPointでも、そのまま扱いやすくなります。

表のセルからテキストを抽出する

スライドに表がある場合、表のセルに入っているテキストも別途取得できます。

表は ITable として扱われます。セルには table[col, row] でアクセスでき、セル内のテキストは TextFrame.Text から取得できます。

from spire.presentation.common import *
from spire.presentation import *

inputFile = "./Data/Template_Ppt_1.pptx"

presentation = Presentation()
presentation.LoadFromFile(inputFile)

sb = []

# 1枚目のスライドから表を取得
for shape in presentation.Slides[0].Shapes:
    if isinstance(shape, ITable):
        table = shape

        # 表のすべてのセルを取得
        for row in range(table.RowsCount):
            for col in range(table.ColumnsCount):
                cell_text = table[col, row].TextFrame.Text
                if cell_text:
                    sb.append(f"[{row},{col}] {cell_text}")

with open("TableText.txt", "w", encoding="utf-8") as fp:
    for s in sb:
        fp.write(s + "\n")

presentation.Dispose()

ここで注意したいのが、table[col, row] の順番です。

第1引数が、第2引数がを表します。

そのため、行数と列数を取得して二重ループでセルを順番に処理します。

今回は抽出したテキストの前に [row,col] を付けています。こうしておけば、後から見たときに元の表のどの位置にあったテキストなのか確認しやすくなります。

必要なければ、単純に cell_text だけを保存しても問題ありません。

発表者ノートを抽出する

PowerPointには、スライド本体とは別に発表者用のノートを追加できます。

このノートは通常の slide.Shapes からは取得できません。NotesSlide にアクセスして、NotesTextFrame.Text を取得します。

from spire.presentation.common import *
from spire.presentation import *

inputFile = "./Data/Template_Ppt_1.pptx"

presentation = Presentation()
presentation.LoadFromFile(inputFile)

sb = []

# 各スライドのノートを取得
for i, slide in enumerate(presentation.Slides):
    ns = slide.NotesSlide

    if ns is not None:
        note_text = ns.NotesTextFrame.Text

        if note_text.strip():
            sb.append(f"--- Slide {i + 1} Notes ---")
            sb.append(note_text)

with open("SpeakerNotes.txt", "w", encoding="utf-8") as fp:
    for s in sb:
        fp.write(s + "\n")

presentation.Dispose()

NotesSlide が存在しないスライドもあるため、ここでは None かどうかを確認しています。

ノート全体をそのまま取得したい場合は、NotesTextFrame.Text を使うだけなので比較的シンプルです。

今回はスライド番号を付けています。複数のスライドからノートを抽出する場合、このように区切りを入れておくと、どのスライドのノートなのか分かりやすくなります。

コメントを抽出する

PowerPointのコメントも、スライドに含まれるテキスト情報の一つです。

コメントは slide.Comments から取得できます。コメント本文は Text プロパティで取得できます。

from spire.presentation.common import *
from spire.presentation import *

inputFile = "./Data/Template_Ppt_5.pptx"

presentation = Presentation()
presentation.LoadFromFile(inputFile)

cs = []

# 1枚目のスライドからコメントを取得
comments = presentation.Slides[0].Comments

i = 0
while i < len(comments):
    cs.append(comments[i].Text)
    i += 1

with open("ExtractComments.txt", "w", encoding="utf-8") as fp:
    for s in cs:
        fp.write(s + "\n")

presentation.Dispose()

slide.Comments には、そのスライドに付けられたコメントが入っています。

コメント本文だけでなく、作成者や作成日時などの情報も必要なら、コメントオブジェクトからそれらのプロパティを取得できます。

たとえばレビュー内容を整理する場合は、コメント本文だけでなく、誰がいつ追加したコメントなのかも一緒に保存しておくと便利です。

なお、上の例では1枚目のスライドだけを対象にしています。すべてのスライドからコメントを取得したい場合は、スライドのループ内で slide.Comments を処理すればOKです。

もう少し実用的に使う

ここまでで、スライド上のテキスト、表、ノート、コメントをそれぞれ取得できました。

用途によっては、単なる文字列だけでなく、書式情報を取得したり、複数のPowerPointをまとめて処理したりすることもあります。

テキストと書式情報も取得する

テキストの内容だけでなく、フォント名やサイズなども必要な場合は、Paragraph.TextRanges を利用できます。

from spire.presentation.common import *
from spire.presentation import *

presentation = Presentation()
presentation.LoadFromFile("./Data/ExtractText.pptx")

sb = []

for slide in presentation.Slides:
    for shape in slide.Shapes:
        if isinstance(shape, IAutoShape):
            for p in shape.TextFrame.Paragraphs:
                for tr in p.TextRanges:
                    line = f"Text: {tr.Text} | Font: {tr.LatinFont.FontName} | Size: {tr.FontHeight}"
                    sb.append(line)

with open("TextWithFormat.txt", "w", encoding="utf-8") as fp:
    for s in sb:
        fp.write(s + "\n")

presentation.Dispose()

1つの段落内でフォントなどの書式が変わっている場合、テキストは複数の TextRange に分かれていることがあります。

そのため、TextRanges を順番に処理すれば、テキストと一緒に各部分の書式情報も取得できます。

ここでは LatinFont.FontName からフォント名、FontHeight からフォントサイズを取得しています。

書式まで含めて分析したい場合や、PowerPointの内容を別の形式に変換したい場合にも使える方法です。

複数のPowerPointをまとめて処理する

PowerPointが1ファイルだけなら、ここまでのコードで十分です。

一方、社内資料などのように複数の .pptx ファイルをまとめて処理したい場合は、os と組み合わせると簡単に自動化できます。

import os
from spire.presentation.common import *
from spire.presentation import *

input_dir = "./Data/Presentations"
output_file = "AllText.txt"

with open(output_file, "w", encoding="utf-8") as fp:
    for filename in os.listdir(input_dir):
        if filename.endswith((".pptx", ".ppt")):
            fp.write(f"=== {filename} ===\n")

            ppt = Presentation()
            ppt.LoadFromFile(os.path.join(input_dir, filename))

            for i, slide in enumerate(ppt.Slides):
                fp.write(f"--- Slide {i + 1} ---\n")

                for shape in slide.Shapes:
                    if isinstance(shape, IAutoShape):
                        for tp in shape.TextFrame.Paragraphs:
                            if tp.Text.strip():
                                fp.write(tp.Text + "\n")

            ppt.Dispose()

この例では、指定したフォルダ内にあるPowerPointを順番に読み込み、1つの AllText.txt にまとめています。

ファイル名とスライド番号も一緒に書き出しているので、後から検索したときに元の資料を特定しやすくなります。

たとえば、複数のプレゼン資料を対象にキーワード検索をしたい場合や、抽出したテキストを後続の処理に渡したい場合に使えます。

ファイル数が多い場合でも、各ファイルの処理が終わるたびに Dispose() を呼び出しておけば、不要になったPowerPointオブジェクトを解放できます。

まとめ

PowerPointのテキストは、スライド上のテキストボックスだけでなく、表のセル、発表者ノート、コメントなどにも含まれています。

Spire.Presentation for Pythonを使えば、これらをそれぞれのAPIから取得して、テキストファイルにまとめることができます。

単一のPowerPointから必要なテキストを取り出すだけでなく、複数ファイルをまとめて処理することもできるので、資料の検索やデータ整理、議事録作成など、PowerPointの内容を再利用したい場面でも活用できます。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?