【Python】ミニ研究テーマ「論文の要旨の部分だけを抽出して、音声合成を行う」

# この記事は
「Pythonその2 Advent Calendar 2019」の16日目です。

# はじめに
こんにちは。
論文の概要が分かる要旨の部分がスッと頭の中に入ってきたら便利だなと思って、リサーチしました。

この記事では、「論文(PDFファイル)にある要旨の部分だけを抽出し、その部分を音声合成していく」といったプログラムを作っていきます。


# 環境

- Windows 10 home
- Python 3.7.1



# PDFファイルのテキストを抽出

こちらの記事を参考にしました。 → [PDFから全テキストを抽出する方法](https://tech.bita.jp/article/18)

```py
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
from io import StringIO
from glob import glob

def convert_pdf_to_txt(path):
	rsrcmgr = PDFResourceManager()
	retstr = StringIO()
	codec = "utf-8"
	laparams = LAParams()
	laparams.detect_vertical = True # Trueにすることで綺麗にテキストを抽出できる
	device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)
	fp = open(path, "rb")
	interpreter = PDFPageInterpreter(rsrcmgr, device)
	maxpages = 0
	caching = True
	pagenos=set()
	fstr = ""
	for page in PDFPage.get_pages(fp, pagenos, maxpages=maxpages,caching=caching, check_extractable=True):
		interpreter.process_page(page)

		str = retstr.getvalue()
		fstr += str

	fp.close()
	device.close()
	retstr.close()
	return fstr
```

convert_pdf_to_txtメソッドは、pdfファイルのパスを渡してあげることで、そのファイルのテキストを文字列のデータに変換して、返してくれる関数になります。
まず、このメソッドを使って、pdfファイルのテキスト全体を抽出していきます。


# テキストをmp3ファイルに変換し、再生する

以下の記事を参考にしました。

- [Pythonを使って、Google Homeに喋らせてみる](https://qiita.com/attakei/items/c5de47f3c1f53992c353)
- [PythonでMP3音源を再生する](https://qiita.com/kekeho/items/a0b93695d8a8ac6f1028)


```py
from gtts import gTTS #Google Text-to-speech
from mutagen.mp3 import MP3 as mp3
import pygame
import time

def speakAbstract(txt):
	filename = "abstract.mp3" 

	tts = gTTS(text=txt, lang="ja")
	tts.save(filename)

	pygame.mixer.init()
	pygame.mixer.music.load(filename) #音源を読み込み
	mp3_length = mp3(filename).info.length #音源の長さ取得

	pygame.mixer.music.play(1) #再生開始。1の部分を変えるとn回再生(その場合は次の行の秒数も×nすること)
	time.sleep(mp3_length+10) #再生開始後、音源の長さだけ待つ(0.5待つのは誤差解消)
	pygame.mixer.music.stop() #音源の長さ待ったら再生停止
```

speakAbstractメソッドは、テキストデータを渡すと、それをmp3ファイルに変換し、再生するといった処理をする関数です。
このメソッドを使って、要旨の部分だけ抽出されたデータを渡し、音声合成を行います。


# 要旨の部分だけ抽出し、音声合成する

```py
text = convert_pdf_to_txt("論文1.pdf")
resultText = text[text.find("要旨"):text.find("Abstract")]
print(resultText)

speakAbstract(resultText)
```

このプログラムでは、これまで作った、convert_pdf_to_txtメソッドとspeakAbstractメソッドを使って、要旨の部分だけを抽出し、音声合成をしていきます。
まず、convert_pdf_to_txtメソッドに変換したいpdfファイルのパス（ここでは、同じフォルダ内にある論文1.pdfというファイルを指定）を渡してあげます。そして、「要旨」という文字番目から、「Abstract」という文字番目までの文字列をresultTextに格納し、それを出力します。
最後にspeakAbstractメソッドに要旨の部分だけを抽出されたresultTextを渡して、音声合成を行います。
これで一連の流れは終了になります。


# 完成したプログラム

こちらが完成されたプログラムになります。

```speakAbstract.py
# coding=utf8

from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
from io import StringIO
from glob import glob

from gtts import gTTS #Google Text-to-speech
from mutagen.mp3 import MP3 as mp3
import pygame
import time

def convert_pdf_to_txt(path):
	rsrcmgr = PDFResourceManager()
	retstr = StringIO()
	codec = "utf-8"
	laparams = LAParams()
	laparams.detect_vertical = True # Trueにすることで綺麗にテキストを抽出できる
	device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)
	fp = open(path, "rb")
	interpreter = PDFPageInterpreter(rsrcmgr, device)
	maxpages = 0
	caching = True
	pagenos=set()
	fstr = ""
	for page in PDFPage.get_pages(fp, pagenos, maxpages=maxpages,caching=caching, check_extractable=True):
		interpreter.process_page(page)

		str = retstr.getvalue()
		fstr += str

	fp.close()
	device.close()
	retstr.close()
	return fstr

def speakAbstract(txt):
	filename = "abstract.mp3" 

	tts = gTTS(text=txt, lang="ja")
	tts.save(filename)

	pygame.mixer.init()
	pygame.mixer.music.load(filename) #音源を読み込み
	mp3_length = mp3(filename).info.length #音源の長さ取得

	pygame.mixer.music.play(1) #再生開始。1の部分を変えるとn回再生(その場合は次の行の秒数も×nすること)
	time.sleep(mp3_length+10) #再生開始後、音源の長さだけ待つ(0.5待つのは誤差解消)
	pygame.mixer.music.stop() #音源の長さ待ったら再生停止


text = convert_pdf_to_txt("論文1.pdf")
resultText = text[text.find("要旨"):text.find("Abstract")]
print(resultText)

speakAbstract(resultText)
```


# 今後の課題
このプログラムを実際に動かしてみた方はどうだったでしょうか。しっかりと要旨の部分だけを抽出し、音声が再生されたでしょうか。
この記事では、要旨の部分だけを抽出するのに、要旨という文字番目からAbstractという文字番目までという判定で抽出していました。もし、要旨またはAbstractという文字がない論文の場合はどうなるでしょうか。今後はどの論文の場合でも、要旨の部分だけを抽出していくことが課題になるかと思います。

ここまで読んでいただき、ありがとうございました。