Pythonで長い文章をようやく可能!「sumy」

Python
この記事は約9分で読めます。

みなさんこんにちは!

 

イザナギです!

 

最近、Webニュース記事をよく見ているんですが、

 

疲れていると、長い文章のニュース記事は読む気なくしてしまいますよね…

 

できれば文章を短く要約したいです。

 

そんな時にあるPythonのパッケージを見つけました!

 

その名もsumy

sumy
Module for automatic summarization of text documents and HTML pages.

 

このパッケージは文章を要約してくれる便利なパッケージです!

 

sumy とは?

 

先ほども少し書きましたが、「文章を要約してくれるPythonパッケージ」です。

 

パッケージ管理のpipコマンドでインストールできます。

 

pip install sumy

 

sumyを利用すると長い文章を短くすることができます。

 

例えば、

「行政と市民を結びつけるコード・フォー・ジャパン写真提供関治之新型コロナウイルス感染症の拡大によって、デジタル化の必要性がより一層強く認識されている。そんな中、市民が自らテクノロジーを活用して地域課題を解決する「シビックテック」の動きも見逃せない。日本のシビックテックの先駆者ともいえるのが、一般社団法人コード・フォー・ジャパンの代表理事を務める関治之さんだ。市民コミュニティーとテクノロジーの力を生かした課題解決の方法や、今後のシビックテックの可能性などを聞いた。震災をきっかけに組織を立ち上げシビックテックCivicTechは、「市民の」Civicと「テクノロジー」Techをかけあわせた造語だ。「市民が主体となりテクノロジーを活用して地域課題を解決すること」を指す。これまで地域課題の解決は、主に自治体が担ってきた。しかし、すべての課題を解決するためには、行政や自治体だけでない市民の自主的な取り組み、地域の住民同士のつながり、さまざまな組織との連携が必要になるといわれている。もともとシステム開発に携わるエンジニアだった関さん。シビックテックの活動を始めたきっかけは、2011年の東日本大震災だった。震災直後、災害情報を収集し地図上に表していくサイト「sinsaiinfo」を仲間とともに立ち上げ、SNSで技術者を募り運営。人びとの自発的な協力によるプロジェクトに可能性を感じた関さんは、各地域にコミュニティーをつくりシビックテックの活動をするCodeforAmericaに興味を持ち、日本で同様に活動するべく、2013年にコード・フォー・ジャパンを立ち上げた。同団体が大切にしているのは「ともに考え、ともにつくる」環境づくりだ。行政、市民、企業、研究者など、立場の異なる人びとが垣根を越えて意見交換し、一緒に手を動かせるような場を整えている。さまざまな組織や人びとの間でコミュニケーションを円滑にする「翻訳者」のイメージだ。技術よりも信頼関係の構築が重要同団体の設立から7年、多くの試行錯誤があったという。何より当初は「シビックテック」という概念が知られておらず、説明しても理解してもらえなかったそうだ。」参照:https://news.yahoo.co.jp/articles/9dffd96f173f98200f0e5893d755f6e2fb9b41aa

このように長い文章もsumyを使えば

 

「そんな中、市民が自らテクノロジーを活用して地域課題を解決する「シビックテック」の動きも見逃せない。しかし、すべての課題を解決するためには、行政や自治体だけでない市民の自主的な取り組み、地域の住民同士のつながり、さまざまな組織との連携が必要になるといわれている。人びとの自発的な協力によるプロジェクトに可能性を感じた関さんは、各地域にコミュニティーをつくりシビックテックの活動をするCodeforAmericaに興味を持ち、日本で同様に活動するべく、2013年にコード・フォー・ジャパンを立ち上げた。」

 

このように、短くできます!

  

では実際のコードを見てみましょう!

 

実装

 

今回は以下の環境で実装を行いました。

 

  1. Docker(jupyter/scipy-notebook
  2. Python3.8.6 

 

jupyter/scipy-notebook」を利用することで、Dockerでjupyterノートブックを利用できるようになります。

 

そして以下のツールをインストールします。

 

今回使用する「Mecab」や「sumy」などは事前にコンテナ内には入っていないので、「docker exec -it jupyter bash」などのコマンドでコンテナに入り使用するパッケージをインストールしておいてください!

 

import MeCab
import logging
import json
import requests

from bs4 import BeautifulSoup

from sumy.parsers.plaintext import PlaintextParser
from sumy.nlp.tokenizers import Tokenizer
from sumy.summarizers.lex_rank import LexRankSummarizer

 

次にニュースサイトから記事を取得します。今回はYahooニュースからスクレイピングしてみたいとお思います。

 

# 検索するYahooニュース記事URLを格納する変数
url = ""

# スクレイピングメソッド
def news_scraping_yahoo(url):
    result_news = []

    response = requests.get(url)
    soup = BeautifulSoup(response.text, "html.parser")

    if soup.find(class_='article_body') is not None:
        news_content = soup.find(class_='article_body').text
        news_content = shap_text(news_content)
        if not news_content == "":
            result_news.append([news_content, url])
        else:
            logging.warning("「{}」の記事の内容を要約できませんでした".format(url))
    else:
        logging.warning("「{}」の記事の内容が見つかりませんでした".format(url))

    return result_news

# 記事の整形メソッド
def shap_text(content):
    news_content = "".join(content.splitlines())
    news_content = re.sub(
        r"(https?|ftp)(:\/\/[-_\.!~*\'()a-zA-Z0-9;\/?:\@&=\+$,%#]+)", "", news_content)
    news_content = re.sub(re.compile("[!-/:-@[-`{-~]"), '', news_content)
    news_content = ''.join(
        c for c in news_content if c not in emoji.UNICODE_EMOJI)
    news_content = re.sub(r' ', '', news_content)
    news_content = re.sub(r' ', '', news_content)
    if not len(re.sub(r'[^ ]+\.[^ ]+', '', news_content)) == 0:
        news_content = re.sub(r'[^ ]+\.[^ ]+', '', news_content)
    news_content = re.sub(r'[︰-@]', '', news_content)
    return news_content

text = news_scraping_yahoo(url)[0][0]

 

最後にsumyによる文章要約を行います。

 

# 文章要約メソッド
def summy_test(text):
    # Mecabにて利用する辞書(mecab-ipadic-neologdなど)のURL
    dic_url = ""
    tagger = MeCab.Tagger()
    key = tagger.parse(text)
    corpus = []
    for row in key.split("\n"):
        word = row.split("\t")[0]
        if word == "EOS":
            break
        else:
            corpus.append(word)

    parser = PlaintextParser.from_string(text, Tokenizer('japanese'))

    summarizer = LexRankSummarizer()
    summarizer.stop_words = ['']
    # sentences_countにて、sentence(文章の数)を選びます。
    # 例えばsentences_countを3にすると文章を3文に要約してくれます。
    summary = summarizer(document=parser.document, sentences_count=3)
    b = []
    for sentence in summary:
        b.append(sentence.__str__())
    return "".join(b)

# スクレイピング実行
text = news_scraping_yahoo(url)[0][0]

 

以上を実行すれば、文章が以下のように要約されるはずです!

 

ニュース記事参照:https://news.yahoo.co.jp/articles/9dffd96f173f98200f0e5893d755f6e2fb9b41aa

 

まとめ

 

今回は「sumy」を用いた文章要約について紹介しました。

 

長い文章を短くできるのはとても便利でいいですよね!

 

みなさんもぜひ利用してみてください!

 

それでは今回はここで筆をお置かせていだただきます。

 

最後まで記事をご覧いただきありがとうございました!

コメント

タイトルとURLをコピーしました