=========================================================== Twitter/Facebookへのページシェアでコンテンツを埋め込む(OGP) =========================================================== .. note:: OGPを生成する機能のSphinx本体への組み込みが `PR#7974 `_ で検討されましたが、 `sphinxext-opengraph `_ 拡張を利用すれば良さそうなため見送られました。 Sphinx-users.jp 自体のOGP生成も独自実装(本ページで紹介しているコード)から、sphinxext-opengraphに切り替えました。差分はこちらです: https://github.com/sphinxjp/sphinx-users.jp/pull/103 概要 ==== Sphinxで作成したページのURLをTwitterやFacebookといったSNSに投稿することがあります。このとき、そのページの内容数行と画像が投稿内容に自動的に表示されれば、その投稿を見た人が内容により興味を持ってくれるかもしれません。 このような、SNS投稿にコンテンツ内容を表示するための仕組みとして、 `Open Graph protocol (OGP) `__ という仕組みがあります。OGPは、HTMLのメタタグを適切に持たせることで、投稿先SNS等が表示するべきコンテンツ内容を把握し、その情報を表示してくれる仕組みです。 .. figure:: sphinx-ogp.png OGP対応ページの投稿 この拡張が出力するmetaタグ ========================== この拡張は、以下のHTMLタグを出力します。 .. code-block:: html .. note:: このタグが出力されるためには、Sphinxテーマで使っているテンプレートが ``metatags`` を出力している必要があります。Sphinx組み込みのテーマ、alabaster, sphinx_rtd_theme はこの出力に対応しています。 コード ====== 以下の内容をそれぞれのファイル名でSphinxプロジェクトに組み込んでください。 .. code-block:: python :caption: conf.py import sys import os sys.path.append(os.path.abspath('_ext')) extensions = [ 'ogtag', ] og_site_url = 'http://sphinx-users.jp/' og_twitter_site = '@sphinxjp' ``conf.py`` の ``og_site_url`` には、HTML公開先のドキュメントルートのURLを記載します。 .. code-block:: python :caption: _ext/ogtag.py from docutils import nodes from sphinx import addnodes from urllib.parse import urljoin class Visitor: def __init__(self, document): self.document = document self.text_list = [] self.images = [] self.n_sections = 0 def dispatch_visit(self, node): # toctreeは飛ばす if isinstance(node, addnodes.compact_paragraph) and node.get('toctree'): raise nodes.SkipChildren # 画像を収集 if isinstance(node, nodes.image): self.images.append(node) # 3つ目のセクションまではテキスト収集する if self.n_sections < 3: # テキストを収集 if isinstance(node, nodes.paragraph): self.text_list.append(node.astext()) # セクションに来たら深さを追加 if isinstance(node, nodes.section): self.n_sections += 1 def dispatch_departure(self, node): pass def get_og_description(self): # TODO: 何文字までが良いのか? text = ' '.join(self.text_list) if len(text) > 200: text = text[:197] + '...' return text def get_og_image_url(self, page_url): # TODO: 必ず最初の画像で良いのか if self.images: return urljoin(page_url, self.images[0]['uri']) else: return None def get_og_tags(context, doctree, config): # page_url site_url = config['og_site_url'] page_url = urljoin(site_url, context['pagename'] + context['file_suffix']) # collection visitor = Visitor(doctree) doctree.walkabout(visitor) # og:description og_desc = visitor.get_og_description() # og:image og_image = visitor.get_og_image_url(page_url) ## OGP tags = ''' '''.format(ctx=context, desc=og_desc, page_url=page_url, cfg=config) if og_image: tags += ''.format(url=og_image) return tags def html_page_context(app, pagename, templatename, context, doctree): if not doctree: return context['metatags'] += get_og_tags(context, doctree, app.config) def setup(app): app.add_config_value('og_site_url', None, 'html') app.add_config_value('og_twitter_site', None, 'html') app.connect('html-page-context', html_page_context) return { 'version': '0.1', 'parallel_read_safe': True, 'parallel_write_safe': True, } Twitterでの追加手順 =================== Twitterの場合、ogタグのあるページを検証サイトに入力して、承認してもらう必要があります。詳しくは以下のページにある「検証ツールでURLを実行して申請」を参照してください。 * https://dev.twitter.com/ja/cards/overview 参考 ======== * https://dev.twitter.com/ja/cards/overview * https://developers.facebook.com/docs/opengraph/getting-started/ * `https://get.slack.help/hc/ja/articles/204399343-Slack-でリンクを共有する- `__ * http://ogp.me/