AstroでOGP付きのリンクを生成する


DE-TEIUです。ブログに外部サイトのリンクを貼る時、OGP情報を表示させたくなりました。 試しにやってみます。

open-graph-scraper

open-graph-scraperというライブラリがあります。これを使うと、URLからOGP情報を取得できるようです。

今回はこちらを使ってみます。

ということでインストール。

$ npm install open-graph-scraper --save

Astroのコンポーネント内で呼んでみる。

import openGraphScraper from "open-graph-scraper";

~~~

async function getOpenGraphData(url: string) {
  const option = { url, onlyGetOpenGraphInfo: false };
  const { result } = await openGraphScraper(option);
  return result;
}

ちょっとQiitaの適当な記事のURLを渡して動かしてみる。するとこんなJSONが返ってきた。 色々取れているが、とりあえず以下の情報が拾えているのでok。

  • ogTitle:タイトル
  • ogDescription:説明
  • ogImage: 画像
{
  success: true,
  twitterCard: 'summary_large_image',
  twitterSite: '@Qiita',
  twitterCreator: '@de_teiu_tkg',
  ogType: 'article',
  ogTitle: '無い国の難読地名クイズに挑戦できるクソアプリ - Qiita',
  ogDescription: 'クソアプリ Advent Calendar 2024 1日目の記事です。前置きおはようございます。DE-TEIUです。次の新1万円札の裏面のデザインはクソアプリアドベントカレンダーになるらしい…',
  ogUrl: 'https://qiita.com/de_teiu_tkg/items/66dbf1dce7be5af14623',
  ogSiteName: 'Qiita',
  ogImage: [
    {
      url: 'https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Fadvent-calendar-ogp-background-7940cd1c8db80a7ec40711d90f43539e.jpg%3Fixlib%3Drb-4.0.0%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnFpaXRhLWltYWdlLXN0b3JlLnMzLmFtYXpvbmF3cy5jb20lMkYwJTJGMTczMjcyJTJGcHJvZmlsZS1pbWFnZXMlMkYxNDk1NDY2MjU1P2l4bGliPXJiLTQuMC4wJmFyPTElM0ExJmZpdD1jcm9wJm1hc2s9ZWxsaXBzZSZmbT1wbmczMiZzPWIyYzEyNGIyMWNhZTBiNmJjMWQwZmEwMDYwOWRjYjM1%26blend-x%3D120%26blend-y%3D467%26blend-w%3D82%26blend-h%3D82%26blend-mode%3Dnormal%26s%3D0bdbd40db1005e80e1b2e5189d8d1fff?ixlib=rb-4.0.0&w=1200&fm=jpg&mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTk2MCZoPTMyNCZ0eHQ9JUU3JTg0JUExJUUzJTgxJTg0JUU1JTlCJUJEJUUzJTgxJUFFJUU5JTlCJUEzJUU4JUFBJUFEJUU1JTlDJUIwJUU1JTkwJThEJUUzJTgyJUFGJUUzJTgyJUE0JUUzJTgyJUJBJUUzJTgxJUFCJUU2JThDJTkxJUU2JTg4JUE2JUUzJTgxJUE3JUUzJTgxJThEJUUzJTgyJThCJUUzJTgyJUFGJUUzJTgyJUJEJUUzJTgyJUEyJUUzJTgzJTk3JUUzJTgzJUFBJnR4dC1hbGlnbj1sZWZ0JTJDdG9wJnR4dC1jb2xvcj0lMjMzQTNDM0MmdHh0LWZvbnQ9SGlyYWdpbm8lMjBTYW5zJTIwVzYmdHh0LXNpemU9NTYmdHh0LXBhZD0wJnM9NTA1NDY3YTI2YTBmYjg3NmNlYTFlZmMwNjgyYWMyOTI&mark-x=120&mark-y=112&blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTgzOCZoPTU4JnR4dD0lNDBkZV90ZWl1X3RrZyZ0eHQtY29sb3I9JTIzM0EzQzNDJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTM2JnR4dC1wYWQ9MCZzPWEzMGQ1YjE1OGZiZTJlYTliNzYwYWY3MjgyMTQ0YmI2&blend-x=242&blend-y=480&blend-w=838&blend-h=46&blend-fit=crop&blend-crop=left%2Cbottom&blend-mode=normal&s=b582fdd7a27b1711828ebf3be0b6f337'
    }
  ],
  ogLocale: 'ja',
  ogDate: '2024-11-30T22:03:37Z',
  favicon: 'https://cdn.qiita.com/assets/favicons/public/production-c620d3e403342b1022967ba5e3db1aaa.ico',
  charset: 'utf-8',
  jsonLD: [
    {
      '@context': 'http://schema.org',
      '@type': 'BreadcrumbList',
      itemListElement: [Array]
    },
    {
      '@context': 'http://schema.org',
      '@type': 'Article',
      datePublished: '2024-11-29T22:55:04.000+09:00',
      dateModified: '2024-12-01T07:03:37.000+09:00',
      headline: '無い国の難読地名クイズに挑戦できるクソアプリ',
      image: 'https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Fadvent-calendar-ogp-background-7940cd1c8db80a7ec40711d90f43539e.jpg%3Fixlib%3Drb-4.0.0%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnFpaXRhLWltYWdlLXN0b3JlLnMzLmFtYXpvbmF3cy5jb20lMkYwJTJGMTczMjcyJTJGcHJvZmlsZS1pbWFnZXMlMkYxNDk1NDY2MjU1P2l4bGliPXJiLTQuMC4wJmFyPTElM0ExJmZpdD1jcm9wJm1hc2s9ZWxsaXBzZSZmbT1wbmczMiZzPWIyYzEyNGIyMWNhZTBiNmJjMWQwZmEwMDYwOWRjYjM1%26blend-x%3D120%26blend-y%3D467%26blend-w%3D82%26blend-h%3D82%26blend-mode%3Dnormal%26s%3D0bdbd40db1005e80e1b2e5189d8d1fff?ixlib=rb-4.0.0&w=1200&fm=jpg&mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTk2MCZoPTMyNCZ0eHQ9JUU3JTg0JUExJUUzJTgxJTg0JUU1JTlCJUJEJUUzJTgxJUFFJUU5JTlCJUEzJUU4JUFBJUFEJUU1JTlDJUIwJUU1JTkwJThEJUUzJTgyJUFGJUUzJTgyJUE0JUUzJTgyJUJBJUUzJTgxJUFCJUU2JThDJTkxJUU2JTg4JUE2JUUzJTgxJUE3JUUzJTgxJThEJUUzJTgyJThCJUUzJTgyJUFGJUUzJTgyJUJEJUUzJTgyJUEyJUUzJTgzJTk3JUUzJTgzJUFBJnR4dC1hbGlnbj1sZWZ0JTJDdG9wJnR4dC1jb2xvcj0lMjMzQTNDM0MmdHh0LWZvbnQ9SGlyYWdpbm8lMjBTYW5zJTIwVzYmdHh0LXNpemU9NTYmdHh0LXBhZD0wJnM9NTA1NDY3YTI2YTBmYjg3NmNlYTFlZmMwNjgyYWMyOTI&mark-x=120&mark-y=112&blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTgzOCZoPTU4JnR4dD0lNDBkZV90ZWl1X3RrZyZ0eHQtY29sb3I9JTIzM0EzQzNDJnR4dC1mb250PUhpcmFnaW5vJTIwU2FucyUyMFc2JnR4dC1zaXplPTM2JnR4dC1wYWQ9MCZzPWEzMGQ1YjE1OGZiZTJlYTliNzYwYWY3MjgyMTQ0YmI2&blend-x=242&blend-y=480&blend-w=838&blend-h=46&blend-fit=crop&blend-crop=left%2Cbottom&blend-mode=normal&s=b582fdd7a27b1711828ebf3be0b6f337',
      mainEntityOfPage: 'https://qiita.com/de_teiu_tkg/items/66dbf1dce7be5af14623',
      author: [Object],
      publisher: [Object]
    }
  ],
  requestUrl: 'https://qiita.com/de_teiu_tkg/items/66dbf1dce7be5af14623'
}

しかしAmazonの商品ページのURLを渡してみると、ogImageに複数の画像のURLが入っており、この中から正しい商品画像を探す必要がある。 そこで、Amazonの短縮URLからOG画像取得するという記事を参考に、URLに “/I/”“_SX”“_SY” を含む画像を探し、それを表示するようにした。

OGP情報を表示するコンポーネントを作成する

適当にTailwindのclassを使って、OGP情報を表示するコンポーネントを作成する。

<div class="flex m-3 p-2 bg-slate-300 flex-col ssm:flex-row hover:shadow-lg">
  <a href="{url}" target="_blank">
    <div class="flex items-center justify-center h-full">
      <img class="image" src="{ogImage}" alt="{ogTitle}" />
    </div>
  </a>
  <a
    href="{url}"
    target="_blank"
    class="flex flex-col p-2 text-black hover:text-black grow"
  >
    <p class="font-bold">{ogTitle}</p>
    <hr />
    <p class="italic text-xs">{ogDescription}</p>
  </a>
</div>

<style>
  .image {
    width: auto;
    height: auto;
    max-height: 180px;
    max-width: 100%;
  }
</style>

OGP付きリンクを表示してみる

ということで試しにOGP付きのリンクを貼ってみる。

Amazonならこんな感じ。

Qiitaならこう。

YouTubeの動画リンクも貼れる。

ついでにOGP画像が無いページを読み込んだ時はNoImage画像を表示するようにしてみた。

良さそう。

参考文献