ウィキペディアからOGPタグの内容を取得しようとすると、一部の項目しか取得できないことがわかる。 以下はウィキペディアのHTMLソースからOGP情報の部分を抜粋したものだ。
<meta property="og:image" content="https://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/Double-alaskan-rainbow.jpg/1200px-Double-alaskan-rainbow.jpg"/>
<meta property="og:image:width" content="1200"/>
<meta property="og:image:height" content="630"/>
<meta property="og:image" content="https://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/Double-alaskan-rainbow.jpg/800px-Double-alaskan-rainbow.jpg"/>
<meta property="og:image:width" content="800"/>
<meta property="og:image:height" content="420"/>
<meta property="og:image" content="https://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/Double-alaskan-rainbow.jpg/640px-Double-alaskan-rainbow.jpg"/>
<meta property="og:image:width" content="640"/>
<meta property="og:image:height" content="336"/>
<meta property="og:title" content="虹 - Wikipedia"/>
<meta property="og:type" content="website"/>
これを見てわかるようにウィキペディアのページではOGPの情報として画像、ページタイトル、ページ種別の3つしか記述されていない。
多くのサイトでは以下のように説明やサイト名などの項目も記述してあることが多く、ブログカードを作成するときなどはそれらの情報をそのまま表示すれば良いようになっている。
<meta property="og:url" content="https://tabiji.gallery" />
<meta property="og:type" content="website" />
<meta property="og:title" content="旅路 - さぁ、旅に出よう" />
<meta property="og:description" content="旅の中で出会った風景の写真や、写真に関するコラムを公開しています。写真データの販売や額装もおこなっております。" />
<meta property="og:site_name" content="旅路" />
<meta property="og:image" content="https://tabiji.gallery/_content/Tabiji.Core/image/logo-ogp.png" />
<meta property="og:locale" content="ja_JP" />
ではウィキペディアのページごとの説明などは取得できないのかというと、きちんと手段が用意されている。 ウィキペディアでは各ページの情報を取得するAPIを公開しており、それを通じて取得できるようになっている。
この中に、タイトルを指定してその記事の概要を取得できるAPIがある。 以下のようなURLを作成してAPIにアクセスすると、指定したタイトルから記事を検索してその概要をJSON形式で返してくれる。
https://ja.wikipedia.org/api/rest_v1/page/summary/虹
ここでは虹というタイトルを指定してAPIを呼び出してみた。 このURLにアクセスすると以下のようなレスポンスが得られる。
{
"type": "standard",
"title": "虹",
"displaytitle": "<span class=\"mw-page-title-main\">虹</span>",
"namespace": {
"id": 0,
"text": ""
},
"wikibase_item": "Q1052",
"titles": {
"canonical": "虹",
"normalized": "虹",
"display": "<span class=\"mw-page-title-main\">虹</span>"
},
"pageid": 255181,
"thumbnail": {
"source": "https://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/Double-alaskan-rainbow.jpg/320px-Double-alaskan-rainbow.jpg",
"width": 320,
"height": 168
},
"originalimage": {
"source": "https://upload.wikimedia.org/wikipedia/commons/5/5c/Double-alaskan-rainbow.jpg",
"width": 1919,
"height": 1008
},
"lang": "ja",
"dir": "ltr",
"revision": "92137478",
"tid": "d87f0d70-553b-11ed-869e-934fcce27b25",
"timestamp": "2022-10-26T14:38:20Z",
"description": "光が大気中に浮遊する水滴の中を通過する際に屈折・反射することで様々な色が見られる大気工学現象",
"description_source": "central",
"content_urls": {
"desktop": {
"page": "https://ja.wikipedia.org/wiki/%E8%99%B9",
"revisions": "https://ja.wikipedia.org/wiki/%E8%99%B9?action=history",
"edit": "https://ja.wikipedia.org/wiki/%E8%99%B9?action=edit",
"talk": "https://ja.wikipedia.org/wiki/%E3%83%8E%E3%83%BC%E3%83%88:%E8%99%B9"
},
"mobile": {
"page": "https://ja.m.wikipedia.org/wiki/%E8%99%B9",
"revisions": "https://ja.m.wikipedia.org/wiki/Special:History/%E8%99%B9",
"edit": "https://ja.m.wikipedia.org/wiki/%E8%99%B9?action=edit",
"talk": "https://ja.m.wikipedia.org/wiki/%E3%83%8E%E3%83%BC%E3%83%88:%E8%99%B9"
}
},
"extract": "虹 とは、大気中に浮遊する水滴の中を光が通過する際に、分散することで特徴的な模様が見られる大気光学現象である。",
"extract_html": "<p><b>虹</b> とは、大気中に浮遊する水滴の中を光が通過する際に、分散することで特徴的な模様が見られる大気光学現象である。</p>"
}
主要なものをいくつか列挙してみる。
title | タイトル |
---|---|
thumbnail.source | サムネイル画像のURL |
description | 説明 |
content_urls.desktop.page | 記事のURL |
extract | 抜粋 |
この辺りが一般にOGPの情報として使用されるものたちだ。
後はこうして得られたJSON文字列を元に好みのプログラム言語で処理してやればよい。
参考までにC#でウィキペディアのOGPと同等のデータを取得するコードをざっくりと紹介したい。
var apiUrl = "https://ja.wikipedia.org/api/rest_v1/page/summary/虹";
var client = new HttpClient();
var response = await client.GetAsync(apiUrl);
var result = JsonNode.Parse(response.Content.ReadAsStream());
var siteName = "Wikipedia";
var url = result["content_urls"]["desktop"]["page"].ToString();
var title = result["titles"]["canonical"].ToString();
var description = result["extract"].ToString();
var imageUrl = result["thumbnail"]["source"].ToString();
これで一般的にOGPで必要とされる主要な項目を取得できる。
なお細かいチェックなどは省略しているので必要に応じて実装してもらいたい。
あるいは手間を惜しまないのであれば、ウィキペディアのAPIが返すJSONの形式に合わせたクラスを定義して、そこへJsonSerializer.Deserialize<TValue>()
を使いデータをマッピングするという手もある。
例えばウィキペディアのページ概要を取得するAPIのレスポンスデータに合わせた以下のようなクラスを定義する。 なお以下のサンプルはほぼ最低限のプロパティしか定義していないので、他に必要なデータがある場合は適宜プロパティを追加する必要がある。
class WikipediaPageSummary
{
public class Thumbnail
{
public string source { get; set; }
public int width { get; set; }
public int height { get; set; }
}
public class ContentUrls
{
public class ContentUrlItem
{
public string page { get; set; }
}
public ContentUrlItem desktop { get; set; }
}
public string title { get; set; }
public Thumbnail thumbnail { get; set; }
public ContentUrls content_urls { get; set; }
public string extract { get; set; }
}
これを以下のように使用する。
var apiUrl = "https://ja.wikipedia.org/api/rest_v1/page/summary/虹";
var client = new HttpClient();
var response = await client.GetAsync(apiUrl);
var result = JsonNode.Parse(response.Content.ReadAsStream());
var json = await response.Content.ReadAsStringAsync();
var summary = JsonSerializer.Deserialize<WikipediaPageSummary>(json);
var imageUrl = summary.thumbnail.source;
これは想定通りにデータを取得することができる。
マッピング用のクラスを定義するのが若干面倒ではあるが、コードとしては最もわかりやすいものになるだろう。
ちなみに自分もそうだったのだが、中にはJsonSerializer.Deserialize<ExpandoObject>()
を使ってデータを取得しようとする人がいるかもしれない。
しかしこれはほとんどの人にとって想定通りの動作をしてくれないことだろう。
var apiUrl = "https://ja.wikipedia.org/api/rest_v1/page/summary/虹";
var client = new HttpClient();
var response = await client.GetAsync(apiUrl);
var result = JsonNode.Parse(response.Content.ReadAsStream());
var json = await response.Content.ReadAsStringAsync();
dynamic obj = JsonSerializer.Deserialize<ExpandoObject>(json);
// これは想定したようには動かない
var imageUrl = obj.thumbnail.source;
これを実行すると以下のような例外が発生する。
JsonSerializer.Deserialize<ExpandoObject>(json)
の処理自体は成功するのだが、そこで得られたExpandoObject
のインスタンスが保持する各プロパティの値はJsonElement
というクラスのインスタンスで表現されている。
理想を言えば文字列ならstring
に、整数値ならint
に、階層構造を持っていたらそこもExpandoObject
にしてくれればアクセスしやすいのだが、残念ながらそのような結果を返すようにはなっていない。
なぜウィキペディアのOGPはタイトルと画像だけという中途半端な状態になっているのだろうか。 何か理由があるのかもしれないが、それが何なのか気になるところだ。
それはそうとこのウィキペディアに用意されている各種APIはなかなか興味深いものがある。 レスポンスがJSON形式なのでJavaScriptとの相性もいいし、色々と面白い遊び方ができそうな気もする。 時間があればもっとじっくりといじくり回してみたいものだ。