Search Console - ホーム 検索での見え方というメニューに、
構造化データというものがあり、気になっていたので、詳細を調べてみました。

どうも検索エンジンにいい感じにサイトを表示してもらえるようになるらしく、そして JSON-LD という形式で書けるので、
JSON-LD を自ブログに組み込んでみます。


0. 前提

以下の環境で実行しています。

  • OS
    CentOS release 6.7 (Final)

  • Python Version
    Python 2.7.8

  • Package (必要そうなものだけ抜粋)
    Django (1.10.5)
    Mezzanine (4.2.3)


1. 参考にしたもの


2. python の json-ld ライブラリ

JSON-LD を出力する python ライブラリで、 PyLDいうのがあり、
install して少し使ってみましたが、記法がわからずで使用するのはやめておきました。
今回は、json モジュールを使ったtemplatetag を作成してそれで出力するようにしています。


3. Blog の記事詳細ページに埋め込む json-ld について

blog の詳細ページには、BlogPosting埋め込みます。
それにあたって、mezzanine の blogpost が どんな属性をもっているのかわからなかったので、
以下、スクリプトをコンソール実装して、どんな属性を保持しているのか確認してみました。

BlogPost の Molde Field 属性を取得する

  • command

    python2.7 manage.py shell
    

  • script

    from mezzanine.blog.models import BlogPost
    import pprint
    blogpost = BlogPost.objects.all()[0]
    pprint.pprint([f.name for f in blogpost._meta.get_fields()])
    ------------------------------------
    [u'id',
     u'comments_count',
     u'keywords_string',
     u'rating_count',
     u'rating_sum',
     u'rating_average',
     'site',
     'title',
     'slug',
     '_meta_title',
     'description',
     'gen_description',
     'created',
     'updated',
     'status',
     'publish_date',
     'expiry_date',
     'short_url',
     'in_sitemap',
     'content',
     'user',
     'allow_comments',
     'featured_image',
     'categories',
     'related_posts',
     'rating',
     'comments',
     'keywords']
    
    ------------------------------------
    

Model の 保持する Filed は、model.meta.get_fields()取得できるようです。
Django: Get list of model fields? - Stack Overflow

作成したTemplatetag

  • mezzanine_extentions_tags.py 作成したTemplatetag以下になります。
    JSON-LD Blog Post Example Code | Steal our JSON-LDベースに作成した後、
    構造化データ テストツールテストしたところ、
    エラー、警告が出ていたので、警告に対して対処しています。1
    [1] 具体的に、publisherimage必須エラー(これはshema.orgの型が違うエラー)、 mainEntityOfPage付けなさいと警告が出力されました。

    # -*- coding: utf-8 -*-                                                                                                                                                             
    from __future__ import unicode_literals
    from mezzanine import template
    from mezzanine.blog.models import BlogPost, BlogCategory
    import json
    
    @register.as_tag
    def conv_blog_post_to_json_ld(blog=None):
        """
        Get blogpost JSON-LD
        """
        result_dict = {
        "@context": "http://schema.org", 
        "@type": "BlogPosting",
        "headline": blog.title,
        "author": {"@type": "Person", "name": blog.user.first_name},
        "publisher": {"@type" : "Organization", 
                      "url" : "https://www.monotalk.xyz", 
                      "name" : blog.user.first_name, 
                      "logo" : { "@type" : "ImageObject", "url" : "https://drive.google.com/uc?export=view&id=0By5O5w7iwOMOVE5pTEcyeE40WlE" }
                  },
        "image": { "@type" : "ImageObject", "url" : "https://drive.google.com/uc?export=view&id=0By5O5w7iwOMOMDdhaDhHdXBVTHc","height": 450, "width": 800 },
        "mainEntityOfPage":{
            "@type":"WebPage",
            "@id": blog.get_absolute_url_with_host(),
        },
        "genre": ' '.join(map(lambda n:n.title, blog.categories.all())),
        "wordcount": str(len(blog.content)),
        "datePublished": str(blog.publish_date),
        "dateCreated": str(blog.created),
        "dateModified": str(blog.updated),
        "description": blog.description
        }
        json_o = json.dumps(result_dict, ensure_ascii=True)
        return json_o 
    

  • blog_post_detail.html
    blog の記事詳細テンプレートに以下、記述を追加しました。
    {% load i18n mezzanine_tags mezzanine_extentions_tags %}タグ名は、
    mezzanine_extentions_tags は、conv_blog_post_to_json_ld メソッドの記述先を記載してください。

    {% block blog_post_json_ld %}
        {% load i18n mezzanine_tags mezzanine_extentions_tags %}
        {% conv_blog_post_to_json_ld blog=blog_post as json_ld %}
        {% if json_ld %}
            <script type="application/ld+json">
            {% autoescape off %}
            {{ json_ld }}
            {% endautoescape %}
            </script>
        {% endif %}
    {% endblock %}
    

  • 出力結果
    以下のような、スクリプトが出力されます。
    構造化テストツールのテストは通りましたが、認識までに時間がかかるのか、Google Search Console 上は認識されておらず、
    もう少し様子をみようかと思います。

    <script type="application/ld+json">
    {
        "@context": "http://schema.org", 
        "@type": "BlogPosting", 
        "author": {
            "@type": "Person", 
            "name": "kem"
        }, 
        "dateCreated": "2017-03-15 15:14:38.754503+00:00", 
        "dateModified": "2017-03-15 15:14:38.754503+00:00", 
        "datePublished": "2017-03-15 15:12:51+00:00", 
        "description": "PageNavigator の 表示要素として、 PageableListView を使用していたのを、
    DataView に書き換えて、Limit Offset を指定できるようにした話を書きます。  ", 
        "genre": "wicket", 
        "headline": "Wicket PageNavigator で表示要素の Limit Offset を指定する", 
        "image": {
            "@type": "ImageObject", 
            "height": 450, 
            "url": "https://drive.google.com/uc?export=view&id=0By5O5w7iwOMOMDdhaDhHdXBVTHc", 
            "width": 800
        }, 
        "mainEntityOfPage": {
            "@id": "http://www.monotalk.xyz/blog/wicket-pagenavigator-%E3%81%A7%E8%A1%A8%E7%A4%BA%E8%A6%81%E7%B4%A0%E3%81%AE-limit-offset-%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B/", 
            "@type": "WebPage"
        }, 
        "publisher": {
            "@type": "Organization", 
            "logo": {
                "@type": "ImageObject", 
                "url": "https://drive.google.com/uc?export=view&id=0By5O5w7iwOMOVE5pTEcyeE40WlE"
            }, 
            "name": "kem", 
            "url": "https://www.monotalk.xyz"
        }, 
        "wordcount": "7849"
    }
    </script>
    

以上です。

コメント