MediaWikiAPIを使用して、Wikiの情報を取得してみるよ

おはよう:relaxed:
wikipediaの情報を取得したい時ってあるよね。
そんな時に使えるMediaWikiAPIを使ってみるよ。

###MediaWiki APIとは？
wikiへのログイン・ページの追加や更新、検索などwiki機能を利用することができる
>[公式: MediaWikiAPI](https://www.mediawiki.org/wiki/API:Main_page)



###APIの基本形

```
API: https://ja.wikipedia.org/w/api.php
```

上記URLにparameterの「action」として処理のタイプを持たせることで、検索や更新などいろいろな機能を利用することができるよ。
今回は、基本の「取得（action＝query）」のWiki情報を検索して取得する方法を学ぶよ。


###ページタイトルを指定して、そのページの情報を取得する場合は titles=XXXを設定

```python:getWikiData
import requests
import json


def getWikiData(url, params):
  res = requests.get( url,
                      params = params)
  return res.json()


url      ="https://ja.wikipedia.org/w/api.php"
params = { "action"  : "query",
           "titles"  : "Python",
           "format"  : "json"
         }

print(getWikiData(url,params))
```

【結果】

```python
{
 'batchcomplete': '',
  'query': {
    'pages': {
      '993': {
        'pageid': 993, ##ユニークのID
        'ns': 0,## nameSpace 
        'title': 'Python' ##ページタイトル
      }
    }
  }
}
```


###取得内容を追加する時は、prop=XXXを設定

####例えば・・「Python」というページの基本情報が欲しい場合
>[公式：prop=info (in)](https://www.mediawiki.org/w/api.php?action=help&modules=query%2Binfo)

```python

params = { "action"  : "query",
           "titles"  : "Python",
           "prop"    : "info",
           "format"  : "json"
         }
```


<details><summary>【結果】＊ちょっと長いので折り畳み</summary><div>

```python

{
  'batchcomplete': '',
  'query': {
    'pages': {
      '993': {
        'pageid': 993, 
        'ns': 0,
        'title': 'Python',
        'contentmodel': 'wikitext',
        'pagelanguage': 'ja',
        'pagelanguagehtmlcode': 'ja',
        'pagelanguagedir': 'ltr',
        'touched': '2020-09-21T07:44:48Z',
        'lastrevid': 79623671,
        'length': 50355
      }
    }
  }
}
```
</div></details>

####propごとにさらに詳細なプロパティも指定可能
####例えば・・基本情報＋そのページに訪れた人の数を見たい場合
（大抵 [大項目propの短縮＋prop]が項目名になる）
＊他の項目を取得したい場合は、上記公式：prop=info 〜のページを参照


```python

params = { "action"  : "query",
           "titles"  : "Python",
           "prop"    : "info",##大項目的な立ち位置
           "inprop"  : "watchers",##小項目的な立ち位置
           "format"  : "json"
         }
```

<details><summary>結果＊ちょっと長いので折り畳み</summary><div>

```python

{
  'batchcomplete': '',
  'query': {
    'pages': {
      '993': {
        'pageid': 993,
        'ns': 0,
        'title': 'Python',
        'contentmodel': 'wikitext',
        'pagelanguage': 'ja',
        'pagelanguagehtmlcode': 'ja',
        'pagelanguagedir': 'ltr',
        'touched': '2020-09-21T07:44:48Z',
        'lastrevid': 79623671,
        'length': 50355,
        'watchers': 157 ##ここ
      }
    }
  }
}
```

</div><details>



####例えば・・「Python」というページに含まれる「カテゴリー」と「ソート用のkey項目」を取得したい場合
>[公式:prop=categories (cl)](https://www.mediawiki.org/w/api.php?action=help&modules=query%2Bcategories)
＊他の項目を取得したい場合は、上記ページを参照

```python

params = { "action"  : "query",
           "titles"  : "Python",
           "prop"    : "categories",
           "clprop"  : "sortkey",
           "format"  : "json"
         }

```

<details><summary>結果＊ちょっと長いので折り畳み</summary><div>

```python

{
  'batchcomplete': '',
  'query': {
    'pages': {
      '993': {
        'pageid': 993,
        'ns': 0,
        'title': 'Python',
        'categories': [
          {
            'ns': 14,
            'title': 'Category:Python',
            'sortkey': '2a0a505954484f4e',
            'sortkeyprefix': '*'
          },
          {
            'ns': 14,
            'title': 'Category:オブジェクト指向言語',
            'sortkey': '505954484f4e0a505954484f4e',
            'sortkeyprefix': 'PYTHON'
          },
          {
            'ns': 14,
            'title': 'Category:オープンソースソフトウェア',
            'sortkey': '505954484f4e0a505954484f4e',
            'sortkeyprefix': 'PYTHON'
          },
          {
            'ns': 14,
            'title': 'Category:スクリプト言語',
            'sortkey': '505954484f4e0a505954484f4e',
            'sortkeyprefix': 'PYTHON'
          },
          {
            'ns': 14,
            'title': 'Category:基本情報技術者試験',
            'sortkey': 'e381afe38184e3819de382930a505954484f4e',
            'sortkeyprefix': 'はいそん'
          },
          {
            'ns': 14,
            'title': 'Category:無効な出典が含まれている記事/2018年',
            'sortkey': '420a505954484f4e',
            'sortkeyprefix': 'B'
          }
        ]
      }
    }
  }
}
```
</div></details>



###リストで検索結果を取得する場合はlist=XXXを設定
####例えば・・Wiki上にある全てのカテゴリを取得する場合
>[list=allcategories (ac)](https://www.mediawiki.org/w/api.php?action=help&modules=query%2Ballcategories)
＊他の項目を取得したい場合は、上記ページを参照


```python

params = { "action"  : "query",
           "titles"  : "Python",
           "list"    : "allcategories", 
           "acprop"  : "size", ##リストごと異なるプロパティ
           "aclimit" :  5, ##取得件数の上限 リストごとに項目名がかわる
           "format"  : "json"
         }
```

<details><summary>結果＊ちょっと長いので折り畳み</summary><div>

```python


{
  'batchcomplete': '',
  'continue': {
    'accontinue': '.22_LR_firearms',
    'continue': '-||'
  },
  'query': {
    'pages': {
      '993': {
        'pageid': 993,
        'ns': 0,
        'title': 'Python'
      }
    },
    'allcategories': [
      {
        'size': 1,
        'pages': 1,
        'files': 0,
        'subcats': 0,
        '*': '" + afterCat + "'
      },
      {
        'size': 1,
        'pages': 1,
        'files': 0,
        'subcats': 0,
        '*': '" + afterCat + "$2'
      },
      {
        'size': 2,
        'pages': 2,
        'files': 0,
        'subcats': 0,
        '*': '$1'
      },
      {
        'size': 3,
        'pages': 3,
        'files': 0,
        'subcats': 0,
        '*': '((documentation))の異常な使用があるページ'
      },
      {
        'size': 9,
        'pages': 9,
        'files': 0,
        'subcats': 0,
        '*': '+Ultra'
      }
    ]
  }
}
```

</div></details>

####例えば・・特定のカテゴリに含まれるページをリストで取得する場合

```python
params = { "action"  : "query",
           "titles"  : "Python",
           "list"    : "categorymembers",
           "cmtitle" : "Category:オブジェクト指向言語", ##categorymembersを使用する場合は、必ずここを設定する必要がある。
           "cmlimit" :  5, ##取得件数の上限
           "cmprop"  : "ids|title|sortkey",##取得する項目。[|]区切りで複数を指定できる。
           "format"  : "json"
         }
```


<details><summary>結果＊ちょっと長いので折り畳み</summary><div>

```python
{
  'batchcomplete': '',
  'continue': {
    'cmcontinue': 'page|4345594c4f4e|2496222',
    'continue': '-||'
  },
  'query': {
    'pages': {
      '993': {
        'pageid': 993,
        'ns': 0,
        'title': 'Python'
      }
    },
    'categorymembers': [
      {
        'pageid': 821212,
        'ns': 0,
        'title': 'オブジェクト指向言語の比較',
        'sortkey': '2ae381b2e3818be3818f0ae382aae38396e382b8e382a7e382afe38388e68c87e59091e8a880e8aa9ee381aee6af94e8bc83'
      },
      {
        'pageid': 181337,
        'ns': 0,
        'title': 'ActiveBasic',
        'sortkey': '41435449564542415349430a4143544956454241534943'
      },
      {
        'pageid': 3785500,
        'ns': 0,
        'title': 'Ballerina',
        'sortkey': '42414c4c4552494e41'
      },
      {
        'pageid': 2066745,
        'ns': 0,
        'title': 'Boo (プログラミング言語)',
        'sortkey': '424f4f2028e38397e383ade382b0e383a9e3839fe383b3e382b0e8a880e8aa9e29'
      },
      {
        'pageid': 1503,
        'ns': 0,
        'title': 'C Sharp',
        'sortkey': '43230a43205348415250'
      }
    ]
  }
}

```

</div></details>

###パラメーターの補足
<dl>
  <dt>要素の複数選択</dt>
  <dd>propでinfoとimages(画像情報を取得)など複数の項目を取得したい場合には、[|]パイプで区切ることができる。<br>"prop"    : "info"|"images"　見たいな形になる。
</dd>
</dl>

###戻り値の補足
<dl>
  <dt>ns(namespace)</dt>
  <dd>取得されたページのタイプが表示されている。<br>ns:0のときにはコンテンツページ、ns:14のときにはカテゴリーなど</dd>
  <dt>continue</dt>
  <dd>今回取得した結果に続きがある場合に、この項目が作成される。<br>戻り値に入っている「propの短縮形+continue」の項目を引数として設定すると、その続きからデータを取得することが可能。</dd>
</dl>


###最後に具体的に活用した例
mecabのユーザー辞書を作る際に、該当するカテゴリに含まれる全てのコンテンツタイトルを取得したくて下記のようなコードを作成しました。


```python:makeOwaraiList

import requests
import json
import csv
import re

def getWikiData(url, params):
  res = requests.get( url,
                      params = params)
  return res.json()


fileName = "wikiList"
url      ="https://ja.wikipedia.org/w/api.php"
params   = { "action" : "query",
             "list"   : "categorymembers",
             "cmlimit": "50",
             "format" : "json"
           }

categories = ['日本のお笑いコンビ','日本の女流お笑いコンビ','日本の男女お笑いコンビ','日本のお笑いトリオ','日本のお笑いグループ','日本>の夫婦お笑いコンビ']


with open( fileName + ".csv",'a', encoding="utf-8") as f:
  writer = csv.writer(f)

  for category in categories :
    params['cmtitle'] = 'Category:' + category;
    params['cmcontinue'] = '';
    wikiData = getWikiData(url,params)
    while True:
      for page in wikiData['query']['categorymembers']:
        if page['ns']  == 0:
          title = (re.sub("\(お笑い\)|\(お笑いコンビ\)|\(お笑いトリオ\)|\(タレント\)|\(お笑いグループ\)|\(トリオ\)|\(ユニット\)|\(芸人\)", "" ,page['title'])).strip()
          writer.writerow([title])
      if ('continue' in wikiData and wikiData['continue']['cmcontinue']):
        params['cmcontinue'] = wikiData['continue']['cmcontinue']
        wikiData = getWikiData(url,params)
      else :
        break


```


今回も公式を全面的に信用してAPIのお勉強と活用をしたよ:relaxed:
wikiの情報を活用できる場面は多いはずなので、このAPIが使いこなせるともっと実装が楽しくなりそうだね。