ハシウェブ

Web制作、プログラミングに関する情報を発信するブログ

【PHP】指定したURLからOGPを取得、表示する方法【スクレイピング】

【PHP】指定したURLからOGPを取得、表示する方法【スクレイピング】

「外部リンクをSNSのように表示させたい」
「簡単できれいに外部リンクを表示させたい」

こんな悩みがある人に向けて書いた記事です。

  • PHPを使って指定したURLからOGPを取得、表示する方法

この記事では以上のことがわかります。

目次
  1. 指定したURLからOGPを取得、表示する方法
    1. サンプルコード
    2. 解説
      1. cURL
      2. simplexml_import_dom
      3. xpath
      4. 格納した配列を出力する
  2. まとめ

指定したURLからOGPを取得、表示する方法

サンプルコード

関数にして使いまわしがしやすいようにしています。
WordPressを前提にした場合、以下のコードをfunctions.phpにコピペします。

function get_ogp( $url ){
  $ch = curl_init($url);// urlは対象のページ
  curl_setopt($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);// exec時に出力させない
  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);// リダイレクト許可
  curl_setopt($ch, CURLOPT_MAXREDIRS, 5);// 最大リダイレクト数
  $html = curl_exec($ch);
  $status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  curl_close($ch);

  //リンク先がないとき(404のとき)は処理しない
  if( $status_code !== 404 ):

    $dom_document = new \DOMDocument();
    $from_encoding = mb_detect_encoding($html, ['ASCII', 'ISO-2022-JP', 'UTF-8', 'EUC-JP', 'SJIS'], true);
    if ( ! $from_encoding)
    {
      $from_encoding = 'SJIS';
    }
    @$dom_document->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', $from_encoding));
    $xml_object = simplexml_import_dom($dom_document);
	
    $ogp = [];

    //title
    if( $xml_object->xpath('//meta[@property="og:title"]/@content')[0] ):
      $ogp["title"][] = (string)$xml_object->xpath('//meta[@property="og:title"]/@content')[0];
    elseif( $xml_object->xpath('//title')[0] ):
      $ogp["title"][] = (string)$xml_object->xpath('//title')[0];
    endif;

    //description
    if( $xml_object->xpath('//meta[@property="og:description"]/@content')[0] ):
      $ogp["description"][] = (string)$xml_object->xpath('//meta[@property="og:description"]/@content')[0];
    elseif( $xml_object->xpath('//meta[@name="description"]/@content')[0] ):
      $ogp["description"][] = (string)$xml_object->xpath('//meta[@name="description"]/@content')[0];
    endif;

    //thumbnail
    if( $xml_object->xpath('//meta[@property="og:image"]/@content')[0] ):
      $ogp["thumbnail"][] = (string)$xml_object->xpath('//meta[@property="og:image"]/@content')[0];
    elseif( $xml_object->xpath('//meta[@name="thumbnail"]/@content')[0] ):
      $ogp["thumbnail"][] = (string)$xml_object->xpath('//meta[@name="thumbnail"]/@content')[0];
    else:
      $ogp["thumbnail"][] = get_template_directory_uri() . "/images⁄noimage.jpg";
    endif;
	
    $out = '
      <div class="box-item box-item2">
        <div>
          <a href="' . esc_url( $url ) . '" target="_blank">
            <img class="ofi-cover" src="' . esc_url( $ogp["thumbnail"][0] ) . '" width="200" height="200" alt="' . esc_attr( $ogp["title"][0] ) . '">
          </a>
        </div>
        <div>
          <p>
            <a class="link-external" href="' . esc_url( $url ) . '" target="_blank">' . $ogp["title"][0] . '</a>
          </p>
          <p class="description">' .  esc_html( $ogp["description"][0] ) . '</p>
        </div>
      </div>
    ';
  endif;

  return $out;
}

以下を表示させたい場所にコピペして、「●●●」のところをリンクしたいURLにします。
これでタイトル、説明、画像を表示させることができます。

<?php
  echo get_ogp( "●●●");
?>
POINT
指定したWebサイトに情報が入っていない場合は表示されません。
タイトルはほぼ入っていると思いますが、画像や説明は入っていない可能性もあると思います。

解説

ここからは解説です。

cURL

PHPで外部サイトから情報を取得するときは今まで「file_get_contents」を使っていましたが、今回はじめて「cURL」というものを使ってみました。

  $ch = curl_init($url);// urlは対象のページ
  curl_setopt($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);// exec時に出力させない
  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);// リダイレクト許可
  curl_setopt($ch, CURLOPT_MAXREDIRS, 5);// 最大リダイレクト数
  $html = curl_exec($ch);
  $status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  curl_close($ch);

サンプルコードの関数の中で「cURL」の処理をして外部サイトの情報を取得しています。
この時点で$htmlにHTMLソースが格納されています。

以下のサイトを参考にさせていただきました。

PHPのfile_get_contentsをcURLへ置き換える

PHPのfile_get_contents関数ってチョー手軽でチョー便利ですよね。$html = file_get_contents('test.txt'); こんな風にファイル名を指定するだけで全部読み込んでくれるし。$html = fi

simplexml_import_dom

「simplexml_import_dom」でHTMLをオブジェクトにして返します。

$xml_object = simplexml_import_dom($dom_document);

xpath


xpathを使うとオブジェクトを取得し、OGP情報を配列で格納します。
ogpが指定されていない場合は、titleやdescriptionを格納します。
ogp画像がない場合は、指定したnoimageを表示させます。

    $ogp = [];

    //title
    if( $xml_object->xpath('//meta[@property="og:title"]/@content')[0] ):
      $ogp["title"][] = (string)$xml_object->xpath('//meta[@property="og:title"]/@content')[0];
    elseif( $xml_object->xpath('//title')[0] ):
      $ogp["title"][] = (string)$xml_object->xpath('//title')[0];
    endif;

    //description
    if( $xml_object->xpath('//meta[@property="og:description"]/@content')[0] ):
      $ogp["description"][] = (string)$xml_object->xpath('//meta[@property="og:description"]/@content')[0];
    elseif( $xml_object->xpath('//meta[@name="description"]/@content')[0] ):
      $ogp["description"][] = (string)$xml_object->xpath('//meta[@name="description"]/@content')[0];
    endif;

    //thumbnail
    if( $xml_object->xpath('//meta[@property="og:image"]/@content')[0] ):
      $ogp["thumbnail"][] = (string)$xml_object->xpath('//meta[@property="og:image"]/@content')[0];
    elseif( $xml_object->xpath('//meta[@name="thumbnail"]/@content')[0] ):
      $ogp["thumbnail"][] = (string)$xml_object->xpath('//meta[@name="thumbnail"]/@content')[0];
    else:
      $ogp["thumbnail"][] = get_template_directory_uri() . "/images⁄noimage.jpg";
    endif;

格納した配列を出力する

$outに出力するHTMLタグを格納します。
ここは好きなデザインに調整してください。

    $out = '
      <div class="box-item box-item2">
        <div>
          <a href="' . esc_url( $url ) . '" target="_blank">
            <img class="ofi-cover" src="' . esc_url( $ogp["thumbnail"][0] ) . '" width="200" height="200" alt="' . esc_attr( $ogp["title"][0] ) . '">
          </a>
        </div>
        <div>
          <p>
            <a class="link-external" href="' . esc_url( $url ) . '" target="_blank">' . $ogp["title"][0] . '</a>
          </p>
          <p class="description">' .  esc_html( $ogp["description"][0] ) . '</p>
        </div>
      </div>
    ';

まとめ

指定したURLからOGPを取得、表示する方法を紹介しました。
このページで参照している外部サイトでこの関数を使っています。

参考サイト

PHPでOGPを取得 - Qiita

OGPに括るとライブラリがあるようですのでそちらを使った方が良いかもしれません。 おてがるにOGPのチェッカーを作る - Qiita よく使うのでメモ curl例 $title = ''; $ch = curl_init($u...