おはよう
wikipediaの情報を取得したい時ってあるよね。
そんな時に使えるMediaWikiAPIを使ってみるよ。
MediaWiki APIとは?
wikiへのログイン・ページの追加や更新、検索などwiki機能を利用することができる
APIの基本形
API: https://ja.wikipedia.org/w/api.php
上記URLにparameterの「action」として処理のタイプを持たせることで、検索や更新などいろいろな機能を利用することができるよ。
今回は、基本の「取得(action=query)」のWiki情報を検索して取得する方法を学ぶよ。
ページタイトルを指定して、そのページの情報を取得する場合は titles=XXXを設定
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))
【結果】
{
'batchcomplete': '',
'query': {
'pages': {
'993': {
'pageid': 993, ##ユニークのID
'ns': 0,## nameSpace
'title': 'Python' ##ページタイトル
}
}
}
}
取得内容を追加する時は、prop=XXXを設定
例えば・・「Python」というページの基本情報が欲しい場合
params = { "action" : "query",
"titles" : "Python",
"prop" : "info",
"format" : "json"
}
【結果】*ちょっと長いので折り畳み
{
'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
}
}
}
}
propごとにさらに詳細なプロパティも指定可能
例えば・・基本情報+そのページに訪れた人の数を見たい場合
(大抵 [大項目propの短縮+prop]が項目名になる)
*他の項目を取得したい場合は、上記公式:prop=info 〜のページを参照
params = { "action" : "query",
"titles" : "Python",
"prop" : "info",##大項目的な立ち位置
"inprop" : "watchers",##小項目的な立ち位置
"format" : "json"
}
結果*ちょっと長いので折り畳み
{
'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 ##ここ
}
}
}
}
例えば・・「Python」というページに含まれる「カテゴリー」と「ソート用のkey項目」を取得したい場合
公式:prop=categories (cl)
*他の項目を取得したい場合は、上記ページを参照
params = { "action" : "query",
"titles" : "Python",
"prop" : "categories",
"clprop" : "sortkey",
"format" : "json"
}
結果*ちょっと長いので折り畳み
{
'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'
}
]
}
}
}
}
リストで検索結果を取得する場合はlist=XXXを設定
例えば・・Wiki上にある全てのカテゴリを取得する場合
list=allcategories (ac)
*他の項目を取得したい場合は、上記ページを参照
params = { "action" : "query",
"titles" : "Python",
"list" : "allcategories",
"acprop" : "size", ##リストごと異なるプロパティ
"aclimit" : 5, ##取得件数の上限 リストごとに項目名がかわる
"format" : "json"
}
結果*ちょっと長いので折り畳み
{
'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'
}
]
}
}
例えば・・特定のカテゴリに含まれるページをリストで取得する場合
params = { "action" : "query",
"titles" : "Python",
"list" : "categorymembers",
"cmtitle" : "Category:オブジェクト指向言語", ##categorymembersを使用する場合は、必ずここを設定する必要がある。
"cmlimit" : 5, ##取得件数の上限
"cmprop" : "ids|title|sortkey",##取得する項目。[|]区切りで複数を指定できる。
"format" : "json"
}
結果*ちょっと長いので折り畳み
{
'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'
}
]
}
}
パラメーターの補足
- 要素の複数選択
- propでinfoとimages(画像情報を取得)など複数の項目を取得したい場合には、[|]パイプで区切ることができる。
"prop" : "info"|"images" 見たいな形になる。
戻り値の補足
- ns(namespace)
- 取得されたページのタイプが表示されている。
ns:0のときにはコンテンツページ、ns:14のときにはカテゴリーなど - continue
- 今回取得した結果に続きがある場合に、この項目が作成される。
戻り値に入っている「propの短縮形+continue」の項目を引数として設定すると、その続きからデータを取得することが可能。
最後に具体的に活用した例
mecabのユーザー辞書を作る際に、該当するカテゴリに含まれる全てのコンテンツタイトルを取得したくて下記のようなコードを作成しました。
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のお勉強と活用をしたよ
wikiの情報を活用できる場面は多いはずなので、このAPIが使いこなせるともっと実装が楽しくなりそうだね。