固有表現抽出APIを使ってニュースの場所や時間などの情報を抜き出す

# 概要
[cotoha api](https://api.ce-cotoha.com/contents/index.html)には固有表現抽出APIがあり、いつどこでみたいな情報が取れるらしい。
今回は[Twitterのニュース](https://twitter.com/i/moments?category_id=1)から、いつ、誰がみたいな情報を抽出した。

## 抽出例
こんな感じの情報がとれました。

- アメリカの俳優のキャメロン・ボイスさんが20歳で亡くなりました。

```
LOC:アメリカ　
PSN:キャメロン・ボイス　
Position_Vocation:俳優　
Title_Other:さん　
Age:20歳
```

# APIの詳細
> 固有表現抽出APIは、入力として日本語で記述された文を受け取り、人名や地名、日付表現(時間、日付)、組織名、量的表現(金額、割合)、人工物の8種類の固有表現と、200種類以上のクラス数を持つ拡張固有表現を出力します。
(https://api.ce-cotoha.com/contents/reference.html#api-Ne から引用)

入力文に対し、[固有表現クラス](https://api.ce-cotoha.com/contents/reference-detail.html#ne-class-list)がつけられ、存在すればより詳細な[拡張固有表現クラス](https://api.ce-cotoha.com/contents/reference-detail.html#ne-exclass-list)が付与される。
例えば、「俳優」に対しては固有表現でART、拡張固有表現でPosition_Vocationがつけらえる。

# ソースコード
基本的なソースコードは、前回の[「自然言語処理のためにMeCabを入れるのに疲れたのでCOTOHA APIを使った」](https://qiita.com/rubberduck/items/e39a46f5460830e77d02)と同じです。

あと、URLで付与している「ne」はたぶん固有表現抽出のことです。
> 固有表現抽出
読み方：こゆうひょうげんちゅうしゅつ
【英】named entity extraction, named entity recognition
(https://www.weblio.jp/content/%E5%9B%BA%E6%9C%89%E8%A1%A8%E7%8F%BE%E6%8A%BD%E5%87%BA を引用)


```python
import re
import sys
import json
import requests
from pprint import pprint

import numpy as np

token_url = "https://api.ce-cotoha.com/v1/oauth/accesstokens"
BASE_URL = "https://api.ce-cotoha.com/api/dev/nlp/"
CLIENT_ID = "id"
CLIENT_SECRET = "secret"

def auth(client_id, client_secret):
        
    headers = {
        "Content-Type": "application/json",
        "charset": "UTF-8"
    }

    data = {
        "grantType": "client_credentials",
        "clientId": client_id,
        "clientSecret": client_secret
    }
    r = requests.post(token_url,
                      headers=headers,
                      data=json.dumps(data))
    
    return r.json()["access_token"]

def predict(sentence, access_token):
    base_url = BASE_URL
    
    headers = {
        "Content-Type": "application/json",
        "charset": "UTF-8",
        "Authorization": "Bearer {}".format(access_token)
    }
    
    data = {
        "sentence": sentence,
    }
    
    r = requests.post(base_url + "v1/ne",
                      headers=headers,
                      data=json.dumps(data))
    return r.json()

access_token = auth(CLIENT_ID, CLIENT_SECRET)

txt = "千葉県で震度3の地震が発生しました"
response = predict(txt, access_token)
pprint(response["result"])
```

## 出力結果
```
[{'begin_pos': 0,
  'class': 'LOC',
  'end_pos': 3,
  'extended_class': '',
  'form': '千葉県',
  'source': 'basic',
  'std_form': '千葉県'},
 {'begin_pos': 4,
  'class': 'NUM',
  'end_pos': 7,
  'extended_class': 'Seismic_Intensity',
  'form': '震度3',
  'source': 'basic',
  'std_form': '震度3'}]
```

## 出力をシンプルにする
出力がこのままだとわかりにくいので、より簡素にしましょう。

```python
txt = "千葉県で震度3の地震が発生しました"
response = predict(txt, access_token)

for line in response["result"]:
    if line.get("extended_class"):
        print("{}:{}".format(line["extended_class"], line["form"]))
    else:
        print("{}:{}".format(line["class"], line["form"]))
```

### 出力結果
いろいろ入力して試しましょう。

- 千葉県で震度3の地震が発生しました

```
LOC:千葉県
Seismic_Intensity:震度3
```

- アメリカの俳優のキャメロン・ボイスさんが20歳で亡くなりました。

```
LOC:アメリカ
PSN:キャメロン・ボイス
Position_Vocation:俳優
Title_Other:さん
Age:20歳
```

- 警視庁によれば、7日午前0時50分ごろ、東京都荒川区にある和菓子店の冷蔵庫の中から女子大学生が遺体で発見されました。

```
ORG:警視庁
DAT:7日
LOC:東京都荒川区
Time:午前0時50分ごろ
Dish:和菓子
School_Age:女子大学生
```

- 警視庁新宿署は4日、セブンペイで20万円分の電子たばこを購入しようとしたとして、中国籍の男2人を詐欺未遂の疑いで逮捕しました。

```
ORG:警視庁新宿署
DAT:4日
MNY:20万円
Organization:セブンペイ
Product_Other:電子たばこ
Organization:中国籍
N_Person:2人
Offense:詐欺未遂
```

# まとめ
拡張固有表現があると思ってたよりいろいろ抽出できました。
キーワード抽出と違って、とれたキーワードにタグがつくのが便利だと思いました。