Wikipedia記事の座標を取得&日本語記事の座標が取得できない問題

MediaWiki APIでWikipediaの記事から座標を取得する方法と、MediaWiki APIでWikipedia日本語記事の座標が取得できないことについての説明です。

## WikiLayers
唐突ですが、React+Redux+Material-UI+OpenLayersで[WikiLayers]というWebアプリっぽいものを作りました。  
これは今から紹介するMediaWiki APIでWikipediaの記事から座標を取得しOpenLayersで表示するという内容のアプリです。
MediaWiki APIで記事の座標を取得する実例として試してみてください。

![wikilayers_showcase.png](https://qiita-image-store.s3.amazonaws.com/0/154454/cd96e5b4-51d2-c301-2704-44325c21bad1.png)

**WikiLayers**
https://cieloazul310.github.io/wikilayers/

## Wikipediaの記事の座標

<img width="600" alt="img20180207.png" src="https://qiita-image-store.s3.amazonaws.com/0/154454/2bb955cb-20bc-4907-1965-6a8db9f211da.png">


Wikipediaにはタイトルの右側または本文などに座標が記載されている記事があります。
この座標は地図サービスへのリンク集[GeoHack](https://tools.wmflabs.org/geohack/geohack.php?language=ja&pagename=%E5%81%95%E6%A5%BD%E5%9C%92&params=36_22_23_N_140_27_22_E_region:JP-08_type:landmark_source:dewiki)へのリンクになっていて、手軽にGoogleマップや地理院地図などで記事の座標を表示することができます。

この座標をMediaWiki APIで取得します。

## MediaWiki APIの基礎

**https://${lang}.wikipedia.org/w/api.php?**
にクエリを加えていきます。

### 覚えておくべきクエリ

- __origin=*__: CORS対策です。
- **action=query**: ページの情報を取得するクエリです。
- **format=${format}**: 取得フォーマットをxml,json,phpから選択します。
- **formatversion=2**: データをJSONで取得したい場合は`formatversion=2`をつけた方がいいです。
- **prop=${prop1}|${prop2}|${prop3}...**: 取得するデータの内容を選択。複数選択の場合は縦線`|`で区切ります。
- **redirects**: タイトルが正確でない場合でもリダイレクトをする。

大雑把にしか説明していないのでクエリの詳細な説明を知りたい方がいたら以下のAPIヘルプやAPIサンドボックスを参照してください。

- [MediaWiki API ヘルプ]
- [APIサンドボックス]

### 例

※注 リンク先は返り値を見やすくするためにformat=jsonfmにしてあります。

#### 日本語版で水戸城の概要をプレーンテキストで取得

[https://ja.wikipedia.org/w/api.php?action=query&format=json&formatversion=2&prop=extracts&exintro&explaintext&titles=水戸城](https://ja.wikipedia.org/w/api.php?action=query&format=jsonfm&formatversion=2&prop=extracts&exintro&explaintext&titles=水戸城)

##### prop=extracts

指定されたページをプレーンテキストまたは制限付きhtmlで返すプロパティ。
https://ja.wikipedia.org/w/api.php?action=help&modules=query%2Bextracts

##### extractsのパラメータ

- **&exintro**: 記事の一章目より前の文章のみを返す。
- **&explaintext**: 制限付きhtmlではなくプレーンテキストで返す。

#### 英語版でOtis Reddingのサムネイル画像URLを取得

[https://en.wikipedia.org/w/api.php?action=query&format=json&formatversion=2&prop=pageimages&titles=Otis_Redding](https://en.wikipedia.org/w/api.php?action=query&format=jsonfm&formatversion=2&prop=pageimages&titles=Otis_Redding)

##### prop=pageimages

サムネイルや写真の有無など、ページ上の画像に関する情報を返すプロパティ。
https://ja.wikipedia.org/w/api.php?action=help&modules=query%2Bpageimages

#### 日本語版で水戸ホーリーホックの他国版のタイトルを取得

[https://ja.wikipedia.org/w/api.php?action=query&format=json&formatversion=2&prop=langlinks&titles=水戸ホーリーホック](https://ja.wikipedia.org/w/api.php?action=query&format=jsonfm&formatversion=2&prop=langlinks&titles=水戸ホーリーホック)

## 座標を取得する方法

MediaWiki APIの使い方をざっと覚えたら次は本題の座標の取得方法です。
なんのこっちゃない、上記の方法と同じように`prop=coordinates`で座標を取得できます。

- https://ja.wikipedia.org/w/api.php?action=help&modules=query%2Bcoordinates
- https://www.mediawiki.org/wiki/Extension:GeoData

### 例

#### 日本語版で偕楽園の座標を取得

[https://ja.wikipedia.org/w/api.php?&action=query&format=json&formatversion=2&prop=coordinates&titles=偕楽園](https://ja.wikipedia.org/w/api.php?&action=query&format=jsonfm&formatversion=2&prop=coordinates&titles=偕楽園)

#### 英語版でAbbey Road Studiosの概要と座標を取得

[https://en.wikipedia.org/w/api.php?&action=query&format=json&formatversion=2&prop=extracts|coordinates&exintro&explaintext&titles=Abbey Road Studios&redirects](https://en.wikipedia.org/w/api.php?&action=query&format=jsonfm&formatversion=2&prop=extracts|coordinates&exintro&explaintext&titles=Abbey%20Road%20Studios&redirects)

#### 日本語版で東経140.528162北緯36.533588付近の座標を持つ記事を取得

[https://ja.wikipedia.org/w/api.php?action=query&format=json&formatversion=2&list=geosearch&gsradius=10000&gscoord=36.533588%7C140.528162](https://ja.wikipedia.org/w/api.php?action=query&format=jsonfm&formatversion=2&list=geosearch&gsradius=10000&gscoord=36.533588%7C140.528162)

## 日本語の記事だと座標が取得しにくい問題

さて、実はここからが本題です。

無事Wikipediaから座標が取得できました。めでたしめでたし、とは行かないようで、**何故か日本語の記事では座標が紐付けられているにも関わらず座標を返してくれない事態が度々発生します**。

例えば、「水戸城」を日本語と英語の両方で取得した場合、以下のような結果になります。

1. 日本語版
  - URL: https://ja.wikipedia.org/wiki/水戸城
  - API: [https://ja.wikipedia.org/w/api.php?&action=query&format=json&formatversion=2&prop=coordinates&titles=水戸城](https://ja.wikipedia.org/w/api.php?&action=query&format=jsonfm&formatversion=2&prop=coordinates&titles=水戸城)
  - 結果: **座標なし**
2. 英語版
  - URL: https://en.wikipedia.org/wiki/Mito_Castle
  - API: [https://en.wikipedia.org/w/api.php?&action=query&format=json&formatversion=2&prop=coordinates&titles=Mito%20Castle](https://en.wikipedia.org/w/api.php?&action=query&format=jsonfm&formatversion=2&prop=coordinates&titles=Mito%20Castle)
  - 結果: **座標あり!!!!!!**

この差は一体どんな理由で生じるものなのか、疑問に思いWikipediaの記事のソースなどを調べてみたところ、記事に組み込まれた**座標テンプレートの種類**が違うことに気がつきました。

全世界で使われている汎用的な**[Coord]という座標テンプレートの他に、日本独自？の[ウィキ座標度分秒]や[ウィキ座標2段度分秒]という座標テンプレートが使われていた**のです。
**MediaWiki APIで取得できるのは座標テンプレートが[Coord]のときのみなので、ウィキ座標が多く使われている日本語版の記事は座標の取得がしづらい状況にあります。**

## 対策

### 1. 他国語版で取得する

第一の方法は、ウィキ座標という謎テンプレートが使用されていない他国語版で座標を取得することです。
[WikiLayers]では、日本語版で座標の取得に失敗したら自動的に他言語版で座標を取得する仕組みにしています。

ただし座標が取得できるのは他国語版の記事があるものに限定されてしまいます。

### 2. Wikipediaを編集する 〜ウィキ座標を駆逐せよ！〜

第二の方法は、そもそもウィキ座標という謎のテンプレートを使っているのが悪いのだから、Wikipediaを編集して**ウィキ座標をCoordテンプレートに置き換えてしまおう**というものです。

一つ一つの記事をしらみつぶしに編集していくのは大変ですが、幸い（？）なことにWikipediaの記事はテンプレート（React的な表現だとComponentsがしっくりくる）を多数組み込んだ構造をしています。

Wikipediaのテンプレートでは、あるテンプレートの中に別のテンプレートを組み込むことが可能です。例えば[日本の城郭概要表](https://ja.wikipedia.org/wiki/Template:%E6%97%A5%E6%9C%AC%E3%81%AE%E5%9F%8E%E9%83%AD%E6%A6%82%E8%A6%81%E8%A1%A8)というテンプレートの中には座標テンプレートが組み込まれています。このようにテンプレートの中に組み込まれている座標テンプレートが先述のウィキ座標である場合、そのテンプレートを使用している記事はMediaWiki APIから座標を取得することはできません。
逆に言うと、**テンプレート内の座標テンプレートをウィキ座標からCoordに変更すれば、そのテンプレートを使用している記事はMediaWiki APIの`prop=coordinates`で座標が取得できるようになります**。

[日本の城郭概要表](https://ja.wikipedia.org/wiki/Template:%E6%97%A5%E6%9C%AC%E3%81%AE%E5%9F%8E%E9%83%AD%E6%A6%82%E8%A6%81%E8%A1%A8)というテンプレートは2018年2月5日現在、1446ページで使用されています。このテンプレートには緯度・経度の引数が設定されていて、記事側で数値を設定することによって記事タイトル右側に座標を表示することができます。
しかしここで使われている座標テンプレートは**ウィキ座標度分秒**なので、**日本の城郭概要表テンプレートを使用している1446ページはMediaWiki APIで座標を取得することができません**。
（正確には、日本の城郭概要表テンプレート以外の部分でCoordテンプレートを使用している記事もあり、その座標は取得できます（「[浜松城](https://ja.wikipedia.org/w/api.php?&action=query&format=jsonfm&formatversion=2&prop=coordinates&titles=浜松城)」など））
逆にこの日本の城郭概要表テンプレート一つをウィキ座標からCoordに変更するだけで、このテンプレートを使用している1446ページをMediaWiki APIで座標が取得可能なページに変更することができます。

とはいえ、ウィキ座標を駆逐せよ！とか書いてますが、日本独自のウィキ座標がどのような背景で導入されたものなのか、ウィキ座標を使うことにどのような利点があるのか、ウィキ座標をCoordに置き換えることによってどこにどのような影響があるのかわからないことには編集するのも気が引けるというのが現状です。

>「ウィキ座標」系はどうしようもない駄テンプレートですね。廃止してもよいかもしれない。
> --ラッキースター・キッド ◆Luck.w.AEQ 2010年8月25日 (水) 21:57 (UTC)

と[プロジェクトノート:地理座標][プロジェクトノート]に8年前に書かれた意見を見つけましたが、特に進展なく？座標の付いている記事の半分ほどは未だにウィキ座標が使われています。

2018年2月5日時点での各座標テンプレートの使用数([使用箇所の多いテンプレート](
https://ja.wikipedia.org/w/index.php?title=%E7%89%B9%E5%88%A5:%E4%BD%BF%E7%94%A8%E7%AE%87%E6%89%80%E3%81%AE%E5%A4%9A%E3%81%84%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88&limit=500&offset=0)より)

- **Template:Coord**‏‎ (66,588 ページで使用)
- **Template:ウィキ座標2段度分秒‏‎** (34,598 ページで使用)
- **Template:ウィキ座標度分秒**‏‎ (21,907 ページで使用)

ウィキ座標を使っているテンプレートをCoordに置き換える作業をしたいところですが、初心者ウィキペディアンの自分がそういう大胆な編集をしてしまっていいのか悩ましいところです。（置き換えたい理由も、自分のアプリの使い勝手がよくなるというほとんど私利に近いものですし…）

以上、MediaWiki APIで座標を取得する方法および日本語記事では座標が取得できないものが多い、という話でした。
ウィキ座標という日本独自のテンプレートがどのような経緯で誕生したのか、知っている方がいたら是非教えてください。

<!-- References -->
[WikiLayers]: https://cieloazul310.github.io/wikilayers/
[MediaWiki API ヘルプ]: https://ja.wikipedia.org/w/api.php?&action=help
[APIサンドボックス]: https://ja.wikipedia.org/wiki/特別:ApiSandbox
[Coord]: https://ja.wikipedia.org/wiki/Template:Coord
[プロジェクトノート]: https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E2%80%90%E3%83%8E%E3%83%BC%E3%83%88:%E5%9C%B0%E7%90%86%E5%BA%A7%E6%A8%99
[ウィキ座標度分秒]: https://ja.wikipedia.org/wiki/Template:%E3%82%A6%E3%82%A3%E3%82%AD%E5%BA%A7%E6%A8%99%E5%BA%A6%E5%88%86%E7%A7%92
[ウィキ座標2段度分秒]: https://ja.wikipedia.org/wiki/Template:%E3%82%A6%E3%82%A3%E3%82%AD%E5%BA%A7%E6%A8%992%E6%AE%B5%E5%BA%A6%E5%88%86%E7%A7%92
<!--
地図座標の表示およびナビゲーションページへの誘導のためのテンプレートです。基本的な入力事項は{{ウィキ座標度分秒}}や{{Coord}}と同様ですが、経度と緯度の間に改行を挿入した2段表示に特化しています。主に基礎情報テンプレート内の座標表示に使用されます。
-->