wikidata を情報源として、SPARQL 経由で会社名から子会社名一覧を取得した

# 概要
- やりたかったことはタイトルの通り
- [wikidata](https://www.wikidata.org/wiki/Wikidata:Main_Page) では、記事を識別するのに「単語」ではなくQやPから始まるID（`entity ID`）を利用しているため、その考慮が必要であった
    - wikidata においては、「トヨタ自動車」みたいな文字列は `Label` などに相当する
    - 「トヨタ自動車」の`entity ID` は [Q53268](https://www.wikidata.org/wiki/Q53268)
- 企業名の表記ゆれも吸収してあげる必要があった
    - 「トヨタ自動車」のラベルはあるが、「トヨタ」のラベルは無い
    - でも、「トヨタ」で問い合わせても子会社一覧を取得できてほしい
    - 例えば、「トヨタ自動車」に対して、wikidata 上の表記ゆれ情報（`alias`、`alos known as`）には、以下の通りで「トヨタ」も含まれている
      ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535074/eb310c6e-cbf8-fcc2-eb7f-26852083eff5.png)
- 言語（`language`）の情報もしっかり与えないとうまく結果表示されなかったので注意
- それらを考慮して得られたのが以下の結果とクエリ
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535074/236a6f8f-044d-5c8c-8a58-7e50fdbdfe95.png)
    - [ここ](https://query.wikidata.org/#SELECT%20%20%3FitemLabel%20%3Fsubitem%20%3FsubitemLabel%20%3FsubitemAltLabel%20%3FitemDescription%20WHERE%20%7B%0A%20%20%3Fitem%20wdt%3AP31%20wd%3AQ4830453.%0A%20%20%20%23%20%28%20skos%3AaltLabel%20%7C%20rdfs%3Alabel%20%29%20%3FitemLabel.%0A%20%20%3Fitem%20%20skos%3AaltLabel%20%3Faltabel%20.%0A%20%20%3Fitem%20rdfs%3Alabel%20%20%3Flabel%20.%0A%20%20FILTER%28%3Flabel%20%3D%20%22%E3%83%88%E3%83%A8%E3%82%BF%E8%87%AA%E5%8B%95%E8%BB%8A%22%40ja%20%7C%7C%20%3Faltabel%20%3D%20%22%E3%83%88%E3%83%A8%E3%82%BF%E8%87%AA%E5%8B%95%E8%BB%8A%22%40ja%20%29%0A%20%20%3Fsubitem%20wdt%3AP31%20wd%3AQ4830453.%0A%20%20%3Fsubitem%20wdt%3AP749%20%3Fitem%0A%20%20SERVICE%20wikibase%3Alabel%20%7B%20bd%3AserviceParam%20wikibase%3Alanguage%20%22ja%2Cen%22.%20%7D%0A%7D%0ALIMIT%20100) から以下のクエリ相当がどなたでもブラウザ経由で実行できます
        - 「トヨタ自動車」を「トヨタ」に変えても結果が得られます
        - というか、「富士通」などに変えてもうまくいきます

``` SPARQL
SELECT  ?itemLabel ?subitem ?subitemLabel ?subitemAltLabel ?itemDescription WHERE {
  ?item wdt:P31 wd:Q4830453.
  ?item  skos:altLabel ?altabel .
  ?item rdfs:label  ?label .
  FILTER(?label = "トヨタ自動車"@ja || ?altabel = "トヨタ自動車"@ja )
  ?subitem wdt:P31 wd:Q4830453.
  ?subitem wdt:P749 ?item
  SERVICE wikibase:label { bd:serviceParam wikibase:language "ja,en". }
}
LIMIT 100
```

# 詳細

## 事前知識
wikidata 周りに関する基本中の基本情報のみ

### wikidata について
- wikipediaなどを運用している、[wikimedia財団](https://ja.wikipedia.org/wiki/%E3%82%A6%E3%82%A3%E3%82%AD%E3%83%A1%E3%83%87%E3%82%A3%E3%82%A2%E8%B2%A1%E5%9B%A3) のプロジェクトの１つ
- 知識ベースの辞典みたいな感じ
- こういう知識ベース的なものはいろんなところで作られたりはするけど、オープンで知名度が高いといえば wikidata が最有力候補かも
- [言語に依存しない方法でウィキペディアの記事を作成するプロジェクトにもwikidataが使われるとか](https://gigazine.net/news/20200703-abstract-wikipedia/)
- SPARQLを用いて、wikidataのデータを探索することができる
    - 業務で使うようなRDBへのSQLのクエリより、もう少し抽象化された、もはやQAシステム的な探索というか問い合わせもできる
    - 例えば、「[もっとも多くの俳優に演じられたキャラクターは?](https://twitter.com/WikidataFacts/status/720026371527942144?s=20)」みたいな問い合わせをすることができる
        - この回答は、ドラキュラが正解そう？
        - あくまでも、wikidata上のデータをソースとしての暫定的な回答であることに注意

### SPARQL について

- RDFクエリ言語の１つ
    - クエリ言語なので、SQLのように、何かしらのデータ集合から特定のデータ（集合）を検索するためのものである
    - 上で述べたように、抽象的な問い合わせを作ることができる
    - RDFについては後述するが、RDFのクエリ言語であるため、クエリの形もRDFの性質に則してる
- Prolog 触ったことある人なら、似た印象を感じるかも
- Python などから実行できるライブラリもいくつかあるぽい

### RDF について
- 主語、述語、目的語の形でリソースに関する情報を表す枠組み
- W3Cによって、規格化されている
    - 余談だが、 [RDFにも意味論が与えられており](https://www.w3.org/TR/rdf-mt/) 、これはかなり Prolog の宣言的意味論に近い感じがする
- もともとは、セマンティックwebのための規格であったが、知識ベースを操るうえでも基本的な枠組みとしてよく採用されている感じがする

### WikidataQueryService（WQS）について
- ブラウザからwikidataへのSPARQLクエリを誰でも手軽に試せるやつ
- 例題も豊富
    - [猫ちゃんであるもの（猫のインスタンス）一覧を出す] (https://query.wikidata.org/#%23%E3%83%8D%E3%82%B3%0ASELECT%20%3Fitem%20%3FitemLabel%20%0AWHERE%20%0A%7B%0A%20%20%3Fitem%20wdt%3AP31%20wd%3AQ146.%0A%20%20SERVICE%20wikibase%3Alabel%20%7B%20bd%3AserviceParam%20wikibase%3Alanguage%20%22%5BAUTO_LANGUAGE%5D%2Cen%22.%20%7D%0A%7D) とか
- 画像とかグラフとかのUIもあってマジすごい
    - [大統領の関係グラフ](https://query.wikidata.org/#%23US%20presidents%20and%20spouses%0A%23defaultView%3AGraph%0ASELECT%20%3Fp%20%3FpLabel%20%3Fppicture%20%3Fw%20%3FwLabel%20%3Fwpicture%0AWHERE%20%0A%7B%0A%09wd%3AQ30%20p%3AP6%2Fps%3AP6%20%3Fp%20.%0A%09%3Fp%20wdt%3AP26%20%3Fw%20.%0A%20%20%20OPTIONAL%7B%0A%20%20%20%20%3Fp%20wdt%3AP18%20%3Fppicture%20.%0A%20%20%20%20%3Fw%20wdt%3AP18%20%3Fwpicture%20.%0A%20%20%20%20%7D%0A%09SERVICE%20wikibase%3Alabel%20%7B%0A%09%09bd%3AserviceParam%20wikibase%3Alanguage%20%22en%22%20.%0A%09%7D%0A%7D%0ALIMIT%2010) とか
- クエリによっては、timeout になりがちなので、その場合は limit を入れると結果を（限定的かもしれないけど）得られるのでお試しを
    - って[この動画](https://www.youtube.com/watch?v=kJph4q0Im98)でお聞きしました 
- URLにSPARQLのクエリが埋め込まれるので、自分が作ったクエリはURLでやり取りができて便利


## 試行錯誤の記録
後で書く

# 考察
- [PythonコードからSPARQLを呼び出すライブラリ](https://people.wikimedia.org/~bearloga/notes/wdqs-python.html)などを用いて、企業名を自由変数としてクエリ文字列に埋め込んで Python コードとして実行するともっと柔軟になりそう
    - その際には、en OR ja も一緒に与えたほうが良さそう
- 今回、子会社を抽出するのに、 [wdt:P749（上部組織）](https://www.wikidata.org/wiki/Property:P749) の述語を用いたが、ここは別の述語を試してそれとのORを取るほうがいいかも
    - 資本提携とか、そういう関係で定義されている子会社的企業もありそうなので