XML論文からキーワードを抽出し、ワードクラウドで表示[Python]

7月 26, 2020

ElsevierやSpringerなどのオンラインジャーナルは、一般的に、論文がXMLで提供されている。XMLで提供された論文からは、タイトルやアブストラクトや本文が取り出しやすいため、テキスト解析に重宝する。

今回はXML論文からキーワードをPositionRankアルゴリズムにより自動抽出し、キーワードをワードクラウドで表示するまでのスクリプトを貼る。

抽出の流れとしては、まず、自作パーサーを使って、XML論文からタイトルとアブストラクトを抽出し、次に、タイトルとアブストラクトをPosition Rankに入力し、キーワードを抽出。最後に、抽出されたキーワードを辞書で表し、ワードクラウド関数に入力し、PNG画像として結果を得ている。

出版社とのライセンス契約があるため、入力の論文XMLと出力のワードクラウドを見せることはできないが、コードだけでもどこかで役に立つと思い、掲示する。

実装に使用したリポジトリは以下である。
PositionRank: https://github.com/ymym3412/position-rank
WordCloud: https://github.com/amueller/word_cloud

import re
from position_rank import position_rank
from tokenizer import StanfordCoreNlpTokenizer
from pathlib import Path
from matplotlib import pyplot as plt
from wordcloud import WordCloud
import collections
from tqdm import tqdm
import pandas as pd

class parse():
    
    def __init__(self):
        pass
    
    def fetch_meta(self, xml: str) -> str:
        title = self._xml_parser(xml, r'<title>(.+?)</title>')
        abst = self._xml_parser(xml, r'<abstract>(.+?)</abstract>')
        
        return title, abst
    
    def _xml_parser(self, xml: str, pattern: str) -> str:
        result = ""
        xml = xml.replace('\n', '')
        matchs = re.finditer(pattern, xml)
        for match in matchs:
            result = match.groups()[0]
            
        result = re.sub(r"<.+?>", "", result)
            
        return result

if __name__ == "__main__":
    
    xml_path = Path("./XML")
    
    tokenizer = StanfordCoreNlpTokenizer("http://localhost", port = 9000)
    
    all_key_word_list = []
    
    parse = parse()
    
    for xml in tqdm(xml_path.glob("*.XML")):
        
        with open(xml, "r") as f:
            xml_str = xml.read_text()
            
        title, abstract = parse.fetch_meta(xml_str)
            
        key_word_list = position_rank(title + abstract, tokenizer)
        
        all_key_word_list += key_word_list
        
    c = collections.Counter(all_key_word_list)
    c = dict(c)
    
    df = pd.DataFrame.from_dict(c, orient='index')
    df.to_csv("./freq.csv")
    
    wc = WordCloud().fit_words(c)
    
    fig = plt.figure(figsize=(16, 12), dpi=800)
    plt.imshow(wc)
    plt.axis('off')
    fig.savefig("wordcloud.png")
    

PythonPython

Posted by vastee