Web ページ内の JSON-LD を Python + PyLD で覗いてみる(Schema.org)

Web ページに組み込まれた JSON-LD を見てざっくりと JSON-LD の雰囲気をつかんで、HTMLから JSON-LD を取り出す方法を見てみます。

【目次】

[1]はじめに

アプリ開発に携わる方々にとって「JSON」は常識的なものだと思いますが、「JSON-LD」 は知らない、という人もいらっしゃるのではないかと思います。

逆に JSON-LD は、Web コンテンツ制作や SEO(検索エンジン最適化) 関係の方々にとって必須知識かもしれません。(JSON-LD より Schema.org のほうが身近な言葉かも。)

一方、SemanticWeb や LOD に関わる人なら「RDFのシリアライズ形式の一つ」の一言で終了かもしれません。

JSON-LD が最も利用されている例は、Google クローラなどに Web コンテンツの内容を伝えたり、リッチな検索結果を表示させるためのメタデータとして Web コンテンツ内に組み込むものだと思います。

しかし、JSON-LD はクローラ向けに特化した仕様ではありません。

実際、記事『Googleナレッジグラフの検索APIを使ってみる(Google Knowledge Graph Search API)』で取り上げた API の戻りデータも JSON-LD でした。

そこで、本ブログではアプリ開発者視点から JSON-LD を見ていきたいと思います。

まず今回は JSON-LDの仕様には深入りせず、実例として Web ページに組み込まれた JSON-LD を見て雰囲気をつかみ、その後HTMLから JSON-LD を取り出す方法を見ておきます。

[2]Web ページに組み込まれた JSON-LD の例

まずは細かいところはおいといて、実例をざっと見てみます。

(1)Wikipedia の例

Wkipedia の JSON-LDのページを見てみます。

上記リンクをクリックすると、英語で書かれた JSON-LD の説明が表示されると思います。

このブラウザに表示される HTML コンテンツは、主に人間が読むためのもので、JSON-LD ではありませんが、このHTMLには JSON-LD が組み込まれています。

この HTML ファイルに組み込まれた JSON-LD は以下の手順で探すことができます。
  1. ブラウザの右クリックで表示されるメニューから「ページのソースを表示」を選択します。すると HTML のソースファイルが表示されます。
  2. ソースファイルの下部にある「<script type="application/ld+json">」から始まり、「</script>」で囲まれた部分が JSON-LD のデータです。
    • Ctrl-F で表示される検索ボックスに「application/ld+json」と入力して検索すると探しやすいと思います。

以下は本ブログ執筆時点の上記ページに組み込まれている JSON-LD です。
後述の抽出プログラムで取得したもので、インデントで整形しています。)

{
  "@context": "https://schema.org",
  "@type": "Article",
  "name": "JSON-LD",
  "url": "https://en.wikipedia.org/wiki/JSON-LD",
  "sameAs": "http://www.wikidata.org/entity/Q6108942",
  "mainEntity": "http://www.wikidata.org/entity/Q6108942",
  "author": {
    "@type": "Organization",
    "name": "Contributors to Wikimedia projects"
  },
  "publisher": {
    "@type": "Organization",
    "name": "Wikimedia Foundation, Inc.",
    "logo": {
      "@type": "ImageObject",
      "url": "https://www.wikimedia.org/static/images/wmf-hor-googpub.png"
    }
  },
  "datePublished": "2011-12-30T17:43:17Z",
  "dateModified": "2022-06-15T04:03:41Z",
  "headline": "a method of encoding Linked Data using JSON"
}

なーんだ、ただのJSONファイルじゃないか、と思われると思いますが、実際、そうです(笑)。

データ内容も直観的に分かるものが多いと思います。

しかし「@」から始まる名前には違和感があるかもしれません。

また、「@type」は何となくイメージできる気がしますが、「@context」は JSON-LD のことを知らないと意味不明かもしれません。

Linked Data の観点では sameAs として WIKIDATA への参照があるのも興味深いところです。(ちなみに、これは owl:sameAs ではありません。)

(2)ブログ(Bloggerの場合) の例

ブログ記事の例として、本ブログのページを見てみます。

先の例と同様に「<script type="application/ld+json">」 から「 </script>」で囲まれた部分を見てみます。

このホーム画面には、最近の記事がいくつかリスト表示されていますが、その記事毎に JSON-LD が組み込まれています。下記は、その一つを取り出したものです。

{
  "@context": "http://schema.org",
  "@type": "BlogPosting",
  "mainEntityOfPage": {
    "@type": "WebPage",
    "@id": "https://technodaifuku.blogspot.com/2022/05/ai-aimaartificial-intelligence-modern.html"
  },
  "headline": "百科事典のようなAI技術の包括的な教科書&#65288;エージェントアプローチ 人工知能&#65295;AIMA&#65306;Artificial Intelligence: A Modern Approach&#65289;",
  "description": "Artificial Intelligence: A Modern Approach  発売日 ‏ ‎ 2020/4/28 Stuart Russell  (著), Peter Norvig (著) 言語 ‏ : ‎ 英語     &#12302;Artificial Intelligence...",
  "datePublished": "2022-05-31T22:00:00+09:00",
  "dateModified": "2022-06-01T00:07:47+09:00",
  "image": {
    "@type": "ImageObject",
    "url": "https://blogger.googleusercontent.com/img/proxy/AVvXsEgszw_vYnXVLyzQ6jBkv1SohYi296rwKsNsc_D87EgxXxl0c8PG403JShtdxnknWsImE0E3Ib3DDt2xLATm33vblz1tG2-ZvAiO7adYGSRZ-xJXfKYtTOSYgeZM0pr5PtTsBuoo3FwpMoocoMxUoiUi7KUyBAsktxO8l0V9IwnFpL9h6LqXih2D1_rUrdAq-oknZi039sCfGTqDhjIrZ8dsg04Hf_57xMdj075ZkSuM1ZekWbcLsqT45bBbSK37kxRIiWhWxPis6SK1syt_Wpay-Tfk1JOiP33gscSInar3mZ5U4NcYPG2GY4-13LwXJOH3OTlEHOuW=w1200-h630-p-k-no-nu",
    "height": 630,
    "width": 1200
  },
  "publisher": {
    "@type": "Organization",
    "name": "Blogger",
    "logo": {
      "@type": "ImageObject",
      "url": "https://lh3.googleusercontent.com/ULB6iBuCeTVvSjjjU1A-O8e9ZpVba6uvyhtiWRti_rBAs9yMYOFBujxriJRZ-A=h60",
      "width": 206,
      "height": 60
    }
  },
  "author": {
    "@type": "Person",
    "name": "テクノ大福"
  }
}

私がブログを投稿する時に、このような JSON-LD を組み込んだ覚えはありませんが(笑)、本ブログで利用している Blogger が自動的に JSON-LD を作って組み込んでくれています。

どうでもいいことですが、これによると “author” が「テクノ大福」という「人」であるという記述になっています(笑)。

私のブログ記事内には、「テクノ大福」が人であるという直接の記述は無いと思いますが、(アカウント情報をもとに?)ひっそりクローラに伝えてくれています。

[3]クローラ向け構造化データとしての JSON-LD

Google をはじめとする検索サービスは、どこも高い技術力を持っていますが、それでもホームページのコンテンツだけから人間が理解するような意味を抽出することは難しいものです。

そこで、人間向けのコンテンツ本体とは別に、コンテンツに関する機械可読な情報、いわばコンテンツに対するメタデータをクローラに提供する方法が用意されています。

これを Google のドキュメントなどでは構造化データといっていて、この構造化データを提供すると、主に以下のようなメリットがあるようです。
  • よりよい検索につなげるため。
  • リッチリザルトなどに対応する。

この構造化データの推奨フォーマットとして、JSON-LD が利用されています。

私はSEO関係は素人以下?なので、詳細は以下を参照して下さい。

[4]Linked Data とシリアライズフォーマット

Google では以下の3種類の構造化データが利用できるようです。

これら JSON-LD、microdata、RDFa はいずれもセマンティックウェブの技術基盤である RDF(Resource Description Framework) に関係しています。

RDF で構造化されたデータを記述し、その構造化されたデータを Web上でリンクすることで、Web をグローバルなデータ空間にするという Linked Data 構想があります。

ざっくりしたイメージとしては、人がブラウザでWeb文書のリンクを辿ってネットサーフィンするように、データのレベルでもリンクをたどってサーフィンできるようにするものといえます。

つまり、WWW の基本アーキテクチャを構造化データに対して適用するものです。

今回はセマンティックウェブ技術や RDF の説明は割愛しますが、割愛するのになぜこんなことを書いているのか?(笑)というと、JSON-LDの「LD」は「Linked Data」の「LD」だからです。
ここには「JSON-LD is a lightweight syntax to serialize Linked Data in JSON [RFC8259]. 」と書かれています。

つまり JSON-LD は、JSON の文法に従った RDF の表現形式なので、JSON ファイルとしても扱うことができます。

RDF の仕様は 、知識を表現する枠組みのようなもので、特定のデータ形式に依存するものではありません。このため RDF を表現する形式はいくつかあり、JSON-LD はその一つです。

実際に、先の Wikipedia のJSON-LDの例は、@context の情報を利用して別の形式に機械的に変換できます。(以下は turtle 形式への変換例です。)

@prefix schema: <http://schema.org/> .

[] a schema:Article ;
    schema:author [ a schema:Organization ;
            schema:name "Contributors to Wikimedia projects" ] ;
    schema:dateModified "2022-06-15T04:03:41Z"^^schema:Date ;
    schema:datePublished "2011-12-30T17:43:17Z"^^schema:Date ;
    schema:headline "a method of encoding Linked Data using JSON" ;
    schema:mainEntity "http://www.wikidata.org/entity/Q6108942" ;
    schema:name "JSON-LD" ;
    schema:publisher [ a schema:Organization ;
            schema:logo [ a schema:ImageObject ;
                    schema:url <https://www.wikimedia.org/static/images/wmf-hor-googpub.png> ] ;
            schema:name "Wikimedia Foundation, Inc." ] ;
    schema:sameAs <http://www.wikidata.org/entity/Q6108942> ;
    schema:url <https://en.wikipedia.org/wiki/JSON-LD> .


上記は JSON-LD を展開した例ですが、microdata や RDFa を使って HTML に同等の内容を組み込んだ場合も、同等のRDFが得られることになります。

SEO の観点からは、JSON-LD が「推奨」と書かれると、JSON-LD で提供するのが良いと思いますが、なぜ JSON-LD が推奨とされるのでしょうか?

理由はいくつかあると思いますが、有力な理由は Web コンテンツ制作との親和性のような気がします。

特に、RDF や JSON-LD を知らなくても、 技術的に JSON として扱えば十分な部分と、データの意味の部分を分離して扱えることは、実際の開発面でメリットは大きそうです。

[5]Schema.org による語彙の定義

ところで、JSON-LD の仕様は、RDF のシリアライズ方法(知識の表現形式)を規程していますが、そこで用いる語彙を定義していません。

具体的には、[2]で見た例にある、"author"、"publisher"、"headline"、 "datePublished"のようなキーにあたる部分と、キーに対してどのような値を記載すべきか、といった語彙に関する規程は JSON-LD の仕様にはありません(RDFにもありません)。

語彙は標準化されたものもありますし、自分で定義することもできますが、クローラのためにWeb コンテンツに組み込む JSON-LD には、クローラが理解できる語彙で記述する必要があります。

このクローラが理解できる語彙を定めているのが Schema.org です。

Schema.org は、Google、Microsoft、Yahoo、Yandex によって設立され、クローラが認識できる語彙などを策定しています。

ところで、セマンティックウェブに詳しい方なら、FOAFなど既存の語彙があるのではないか?と思われるかもしれません。このような疑問の多くは FAQ で回答されています。

さて、実際にクローラ向けに JSON-LD を作成する場合は、Schema.org の定義から考えるよりも、クローラ側の仕様に沿って作成するほうがよいと思います。

Google の場合は、以下のページでコンテンツに応じたサンプルを見ることができます。
テストツールもあります。

これらを見ていると、JSON-LD や RDF を殆ど意識することなくクローラ向けの構造化データを作成できますので、その意味では JSON-LD の目的が達成できているような気がします(裏方に徹してますね)。

[6]JSON-LDをHTMLに組み込む方法

JSON-LD は、type属性が「application/ld+json」であるスクリプト要素に置くことで HTML に組み込むことができます。

<script type="application/ld+json">
JSON-LDの記述
</script>

なお、1つのHTMLの中に複数の「<script type="application/ld+json">~</script>」に分けて JSON-LD を記述することもできます。つまり、1つの HTML 文書内に1つの JSON-LD とは限らず、1つのHTML文書に複数の JSON-LD が含まれることもあります。

詳細については以下の仕様を参照して下さい。

[7]PyLD を使って HTMLから JSON-LD を抽出する

本記事の最後として、HTMLから JSON-LD を抽出するコード例をみておきます。

ざっくり言えば、HTML内にある「<script type="application/ld+json">〇△□</script>」の〇△□の部分を抽出する処理なので、一般的なケースだけならライブラリを持ち出さなくてもよい気がしますが、JSON-LDの仕様を実装してくれているライブラリがあれば安心、便利です。

そこで今回は Python ライブラリ「PyLD」を使って JSON-LD を抽出してみます。

以下は、Google Colaboratory で動作確認しています。

まずは、requests と PyLD をインストールします。(Google Colaboratory なら requests はインストール済みだと思います。)
!pip install requests
!pip install PyLD

続いて、ライブラリをインポートします。
import json
import requests
from pyld import jsonld

以下は、工夫もエラー処理も無い簡単なコードですが、WebページのURLを指定すると、JSON-LDを抽出して(get_jsonld_from_html_url)、整形表示(print_json)します。

def get_jsonld_from_html_url(url, extractAllScripts):
    # 指定のURLのHTMLからJSON-LDを抽出する。
    # extractAllScripts=Trueのとき、JSON-LDのリストを返す。
    # それ以外は先頭のJSON-LD。

    # HTMLの取得
    res = requests.get(url)
    if res.status_code == 200:
        options = {}
        if extractAllScripts:
            options["extractAllScripts"] = True
        # PyLDを利用してHTMLからJSON-LDを抽出
        return jsonld.load_html(res.text,url, None, options)
    else:
        return None

def print_json(jsonld,*,indent=2, ensure_ascii=False):
    # JSONを整形表示する。
    if jsonld is not None:
        print(json.dumps(jsonld, indent=indent, ensure_ascii=ensure_ascii))
    else:
        print("表示するデータがありません")

この関数を使うと、Wikipedia の JSON-LD のページの JSON-LD データを抽出できます。

「2」のWikipedaの例は、以下の実行結果を貼り付けたものです。
print_json( get_jsonld_from_html_url("https://en.wikipedia.org/wiki/JSON-LD", False) )

また、get_jsonld_from_html_url の extractAllScripts 引数を True にすると、HTMLに含まれる JSON-LD を全て取得できます。

コメント

このブログの人気の投稿

VirtualBoxのスナップショット機能

Google Document AIで画像から表形式データを抽出する(Vision API OCRとの違い)

オントロジーエディタ Protégé を使ってみる