WebDesign Dackel

PHPでアメーバブログのRSSから記事と記事内の画像を表示する

PHPでアメーバブログのRSSから記事と記事内の画像を表示する

Hatena0
Google+0
Pocket0
Feedly0

運営中のサイトとは別にブログを書いていて、その情報をサイトのTOPへ載せたい、 といった要望があがることがあります。
そのブログサービスが提供するRSSを取得して表示する、というのが簡単で一般的かと思います。

以前、アメーバブログのRSSを取得して情報を載せるところまでは問題なかったのですが、記事の中にある最初の画像をサムネイルとして出したい!といった時に詰まったので、RSSの取得から画像を表示するところまでの工程を共有したいと思います。

注意点

掲載しているソースコードにある、正規表現の一部がWPでの投稿時消えてしまっている箇所があり、そのままではうまく動かない場合があります。
正しいコードは、サンプルコードをご確認下さい。

サンプルファイルをダウンロード

まずは動作確認から

RSS取得サンプル
サンプルブログ:http://ameblo.jp/webdesign-dackel/

サンプルブログの記事を取得して、最新の記事を画像付きで表示する、といったものとなっています。

実装の流れ

実装は下記のような流れになります。

  1. ブログのRSSを取得
  2. 記事の内容から最初の画像を抜粋
  3. 画像を<img>タグとして表示する

というシンプルなものですが、アメーバブログの画像をそのまま<img>タグとして出力すると、何かの制限がかかっているらしく、画像が壊れた様な表示になってしまいます。

壊れた画像の例

なんじゃこりゃっ! と色々試していると、同じ画像でもブラウザで直接URLを叩くと画像が表示されることがわかったので、PHPのget_flie_contents()などでリソースを取得すれば…、と思い試した結果表示が出来ました。

ブログのRSSを取得

まずは実装したメインの関数から。

/**
 * get_ameba_rss
 * アメーバブログから指定件数のRSS情報を取得します
 * @param string $url
 * @param integer $limit 全て取得する場合は「-1」
 * @return array SimpleXMLElement
 */
function get_ameba_rss( $url, $limit=5 )
{
  $rss = curl_get_contents($url);
  $rss = simplexml_load_string($rss);
  $results = array();

  foreach( $rss->channel->item as $item ){

    // PR: から始まる広告、指定数以上の記事は除く
    if( preg_match("/^PR:.+/",$item->title) || ($limit >= 0 && count($results) >= $limit) ){
      continue;
    }

    // 画像がなかった場合のデフォルト画像を指定しておきます
    $now_url = (empty($_SERVER["HTTPS"]) ? "http://" : "https://") . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
    $item->thumbnail = trim($now_url,"/") . "/images/noimage.jpg";

    // 記事の中で最初に使われている画像を検索、設定する
    if( preg_match_all('/<img(.+?)>/is', $item->description, $matches) ){
      foreach( $matches[0] as $img ){
        if( preg_match('/src=[\'"](.+?jpe?g)[\'"]/', $img, $m) ){
          $item->thumbnail = $m[1];
        }
      }
    }

    // レスポンス用のPHPへのパスへ設定する
    $data = array("f" => (string)$item->thumbnail);
    $item->thumbnail = sprintf("response.php?%s", http_build_query($data));

    $results[] = $item;
  }

  return $results;
}

RSSを取得する時に使用するsimplexml_load_file()ですが、エラーが出てしまい使えませんでしたので、一度file_get_contents()で文字列として取得、XMLへ変換するという方法で実装しました。

ほとんどの場合ブログRSSへのパスはhttp://から始まるかと思います。単純にget_file_contents()を使ってしまうと「allow_url_fopen」の設定がOffになっているとエラーが出てしまいます。(セキュリティ的にallow_url_fopenはOffにするのが推奨されます。)

なので、cUrlを使った下記の関数を代替として使用しました。

/**
 * curl_get_contents
 * file_get_contentsの代替関数。
 * allow_url_fopen=off時にURLからファイル内容を取得する際に使用します
 * @param string $url
 * @param integer $timeout
 * @return string
 * @link http://blog.mach3.jp/2010/12/21/use-curl-for-filegetcontents.html
 */
function curl_get_contents( $url, $timeout=60 )
{
    $ch = curl_init();
    curl_setopt( $ch, CURLOPT_URL, $url );
    curl_setopt( $ch, CURLOPT_HEADER, false );
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
    curl_setopt( $ch, CURLOPT_TIMEOUT, $timeout );
    $result = curl_exec( $ch );
    curl_close( $ch );
    return $result;
}

参考サイト:PHPメモ : file_get_contentsの代替にcURLを使う Mach3.laBlog

広告は表示させない

RSSを取得すると、記事タイトルが「PR:」で始まる広告が入ってきます。これは記事の一覧を表示する時に不要なので取得結果から除外します。

// PR: から始まる広告、指定数以上の記事は除く
if( preg_match("/^PR:.+/",$item->title) || ($limit >= 0 && count($results) >= $limit) ){
  continue;
}

記事中の最初の画像を取得、表示用のPHPへ値を渡す

直接<img>タグを出力しても制限がかかっているのか表示されなかったので、レスポンスを返すPHPを用意して、そこへ画像ファイルのパスを値として渡すようにしています。

// 画像がなかった場合のデフォルト画像を指定しておきます
$now_url = (empty($_SERVER["HTTPS"]) ? "http://" : "https://") . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
$item->thumbnail = trim($now_url,"/") . "/images/noimage.jpg";

// 記事の中で最初に使われている画像を検索、設定する
if( preg_match_all('/<img(.+?)>/is', $item->description, $matches) ){
    foreach( $matches[0] as $img ){
        if( preg_match('/src=[\'"](.+?jpe?g)[\'"]/', $img, $m) ){
            $item->thumbnail = $m[1];
        }
    }
}


// レスポンス用のPHPへのパスへ設定する
$data = array("f" => (string)$item->thumbnail);
$item->thumbnail = sprintf("response.php?%s", http_build_query($data));

レスポンス用のPHPを用意

上記で渡ってきた画像ファイルのパスから、画像のレスポンスを返すためのphpを別途用意します。

response.php

$f = isset($_GET["f"]) ? $_GET["f"] : "";
$file_uri = str_replace("\0", "", $f);

// 値を取得
if( $file = curl_get_contents($file_uri) ){
  $mime = get_mime_type($file_uri);
  header("Content-Type: {$mime}");
  print $file;
  exit();
}

print "Error";
exit();

取得した情報をHTMLへ出力する

ここまでくれば、最初に書いたget_ameba_rss()を使って情報を取得して、配列を回してHTMLを出力していきます。

<div class="rss-list">
  <?php
  // RSS情報を取得する
  $rss = get_ameba_rss("http://feedblog.ameba.jp/rss/ameblo/webdesign-dackel/rss20.xml");
  foreach( $rss as $item ) : ?>
  <a href="<?php print $item->link; ?>" target="_blank">
    <p class="rss-image"><img src="<?php print $item->thumbnail; ?>" alt="<?php print $item->title; ?>"></p>
    <p class="rss-title"><?php print $item->title; ?></p>
  </a>
  <?php endforeach; ?>
</div>

ここまでで、サンプルと同じ動作になっています。なんかごちゃごちゃと書いてしまい分かりづらい箇所があるかと思いましたのでサンプルと、サンプルファイル一式をダウンロード出来るようにしました。

RSS取得サンプル
サンプルファイルをダウンロード

ところどころ説明を省いた箇所なんかもありますが、分かりづらい箇所はサンプルファイルを追ってみると良いかもです。

ファイルを一度取得して、書き出し直すという泥臭いことをやっているため、なんだかスッキリとしませんがとりあえず上記の方法で実現が出来たので今回はよしとしました。

ブログを読んでいただいた方に、 他にもっと良い方法をご存知の方がいたら是非ご教授頂けたら思いますっ!

更新履歴

追記:2015年1月17日

冒頭に正規表現部分について、注意書きを追加しました。

追記:2014年9月29日

Wodpressでの組み込んだ際に表示が出来ないよ、とのコメントを頂きましたので、Wordpressへ組み込む際の変更箇所について追記いたします。

get_ameba_rss()

get_ameba_rss()の中で指定している、noimage.jpgresponse.phpへのパスをWP用に変更することで解決できます。

/**
 * get_ameba_rss
 * アメーバブログから指定件数のRSS情報を取得します
 * @param string $url
 * @param integer $limit 全て取得する場合は「-1」
 * @return array SimpleXMLElement
 */
function get_ameba_rss( $url, $limit=5 )
{
  $rss = curl_get_contents($url);
  $rss = simplexml_load_string($rss);
  $results = array();

  foreach( $rss->channel->item as $item ){

    // PR: から始まる広告、指定数以上の記事は除く
    if( preg_match("/^PR:.+/",$item->title) || ($limit >= 0 && count($results) >= $limit) ){
      continue;
    }

    // ↓ noimage.jpgへのパスを変更
    // $now_url = (empty($_SERVER["HTTPS"]) ? "http://" : "https://") . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"];
    // $item->thumbnail = trim($now_url,"/") . "/images/noimage.jpg";
    $item->thumbnail = get_bloginfo("template_url") . "/images/noimage.jpg";

    // 記事の中で最初に使われている画像を検索、設定する
    if( preg_match_all('/<img(.+?)>/is', $item->description, $matches) ){
      foreach( $matches[0] as $img ){
        if( preg_match('/src=[\'"](.+?jpe?g)[\'"]/', $img, $m) ){
          $item->thumbnail = $m[1];
        }
      }
    }

    // レスポンス用のPHPへのパスへ設定する
    $data = array("f" => (string)$item->thumbnail);

    // ↓ response.phpへのパスを変更
    // $item->thumbnail = sprintf("%s/response.php?%s", get_bloginfo("template_url"), http_build_query($data));
    $item->thumbnail = sprintf("%s/response.php?%s", get_bloginfo("template_url"), http_build_query($data));

    $results[] = $item;
  }

  return $results;
}

response.php

あともう一点、response.phpの最上部でfunctions.phpを読み込んでいる箇所を下記のようにwp-load.phpを読み込むように変更します。

// include_once(dirname(__FILE__)."/functions.php");
include_once(dirname(__FILE__) . "/../../../wp-load.php");

例としてあげていますが、お使いのディレクトリ構成に合わせてパスを調整してください。
ちなみに、wp-load.phpはWordPressの一番上の階層、wp-config.phpなどと同じ階層にあります。

追記:2015年5月29日

コメントよりご指摘いただき、response.php内でwp-load.phpを読み込む必要がありましたので記事を修正しました。

追記:2015年10月16日

コメントよりご指摘いただいた、記事中の最初の画像を取得する部分を修正しています。

Hatena0
Google+0
Pocket0
Feedly0

Recent Posts

Comments

  • あんだんて

    Sep 29, 2014

    はじめまして。
    記事を読ませていただきました。
    アメブロの画像を表示したかったので、参考になりました。

    ひとつお聞きしたいのですが、
    これはwordpressへの組み込みも可能でしょうか。
    下層ページでの実現はできたのですが、
    トップページで表示しようとすると同じパスなのですが、
    画像が表示されません。

    不勉強で申し訳ありませんが、ご教授いただけると幸いです。
    よろしくお願いします。

    返信

  • dackel

    Sep 29, 2014

    あんだんてさん
    はじめまして、コメントありがとうございます!
    WPで表示されない原因についてですが、恐らく画像を表示するための response.php へのパスが通っていないのかなぁと思いました。
    こちらはローカル環境でしか確認出来ていませんが、パスを変更することで表示できることを確認しました。
    変更箇所については記事に追記させていただきました。

    上記の変更でも表示がされないようでしたら、まだご相談頂ければと思います!

    返信

  • くろひげ

    Jan 14, 2015

    はじめまして。
    Wordpressでアメブロの画像を表示したく検索しておりましたところ
    まさに、これだと思い、サンプルファイルをダウンロードさせて頂き
    設置しようとこころみておりますが
    Parse error: syntax error, unexpected T_CONSTANT_ENCAPSED_STRING in 省略~
    のエラーになってしまいます。
    該当の行は
    if( preg_match(‘/src=‘”[‘”]/’, $img, $m) ){
    なのですが、phpはほとんどできないので原因がわかりません。
    私なりにこの構文をいじってみましたがシンタックスエラーはなくなっても
    画像がnoimageが表示されます。
    大変、お忙しいところ恐れ入りますが、ご教授頂けたら幸いです。

    返信

  • くろひげ

    Jan 14, 2015

    たびたび、すみません。該当行が投稿したら
    変わってしまいました。29行目です。
    if( preg_match(‘/src=‘”[‘”]/’, $img, $m) ){

    返信

    • dackel

      Jan 17, 2015

      くろひげさんコメントありがとうございます!
      返信が遅くなってしまって申し訳ありません。
      シンタックスエラーの件は、解決出来たとのことでよかったです。

      ただ、画像がnoimageになってしまうとのことで、27行目にある$matchesの中身が正しく入っているでしょうか?
      例えば、var_dump($matches);のようにすることで、正規表現でマッチした中身が正しく入っているか確認することが出来ます。
      もしここに値が入っていないとなるとまた別の箇所が原因になっていることも考えられますので、一度確認してみてまたコメント頂けたらと思います。

    • くろひげ

      Jan 18, 2015

      dackel 様
      返信ありがとうございます。
      var_dump($matches);を27行目の次の行にいれましたが、何も表示されませんでした。
      ちなみにシンタックスエラーは29行目preg_matchの[‘”]を両方とも消すとエラーはなくなります。
      お忙しいところすみません。

    • dackel

      Jan 20, 2015

      くろひげさん
      何も表示されませんでしたか…。。

      そうすると、27行目のpreg_match_allでうまく値が取得できていない気がします。
      聞きそびれてしまっていたのですが、記事のタイトルやリンク自体は表示されるでしょうか?
      もしそれも表示されていないとなると、RSSの情報自体がとれていない可能性があります。
      タイトルなどは表示されていて画像だけが表示されていない場合は、27行目のif( preg_match_all~よりも前でvar_dump($item->description);の様にRSSの内容を確認してみてください。(どんな内容が出力されるでしょうか?)

      出力された文字列の中に<img>タグがある場合、27行目の正規表現に誤りがあってマッチング出来ていないのかもしれません…。

    • くろひげ

      Jan 20, 2015

      dackel様

      返信ありがとうございます。
      タイトルやリンクは問題なく取得できております。
      画像だけnoimage.jpgが表示されます。
      27行目( preg_match_all~よりも前の行にvar_dump($item->description);をいれてみましたところ
      下記が表示されました
      object(SimpleXMLElement)#2969 (0) { } object(SimpleXMLElement)#2968 (0) { } object(SimpleXMLElement)#2967 (0) { } object(SimpleXMLElement)#2966 (0) { } object(SimpleXMLElement)#2965 (0) { }
      よろしくお願い致します。

    • dackel

      Jan 21, 2015

      くろひげさん
      大変失礼致しました。前回入れて頂いたvar_dump($item->description);ですが、var_dump( (string)$item->description );のように変更してもう一度ご確認いただけないでしょうか?
      もしこれで、該当記事の内容が出力された場合、27行目のpreg_match_all()に指定している$item->descriptionを、(string)$item->descriptionに変えてみて下さい。
      もしかしたら、文字列にキャストしていないためにpreg_match_all()で値がうまく処理出来ていないのかもしれないと考えました。

      的を得たアドバイスができず申し訳ありませんが、うまく表示出来るように協力したいと思いますのでよろしくお願い致します。

  • くろひげ

    Jan 21, 2015

    dackel 様
    結論から申しますと、おかげさまで、問題なく取得できるようになりました
    var_dump( (string)$item->description );で記事内容が出力されましたが
    27行目のpreg_match_all()に指定している$item->descriptionを、(string)$item->descriptionに変えてもダメだったので、
    27行目のpreg_match_allの正規表現の部分を適当にかえたら値が取得できました。

    phpがわからない当方に対して親切丁寧に数々のアドバイスありがとうございました。

    返信

    • dackel

      Jan 21, 2015

      くろひげさん
      よかったです、無事に表示できたのですね!
      正規表現が原因でしたか。。また見当違いのアドバイス失礼しました。

      今後とも当ブログをよろしくお願いします。

  • みん

    Feb 04, 2015

    dackel様
    初めまして、みんと申します。
    記事読ませていただきました。
    現在アメブロの画像表示方法で、手こずっており大変勉強になりました。

    おひとつご質問がございまして、コメントに投稿させて頂きました。
    記事では1アカウントのアメブロ画像表示方法でしたが、こちらを複数のアカウントの記事の画像を表示したい場合はどのようにすればいいのでようか?
    ご教授お願い致します。

    返信

    • dackel

      Feb 05, 2015

      みん さん
      コメントありがとうございます。

      時間が無く試せてはいないのですが、下記の方法で複数アカウントの表示が出来るのではないかと思いますので参考にしてみてください。

      取得した情報をHTMLへ出力するのセクションでHTMLを出力しています。ここで使用しているget_ameba_rss()に、アカウント毎のRSSフィードを指定することで情報を取得できます。
      サンプルコードです。これも参考程度でお願いします。

      // アカウント1,2のRSSをそれぞれ上限3件を取得
      $rss1 = get_ameba_rss("アカウント1のRSS", 3);
      $rss2 = get_ameba_rss("アカウント2のRSS", 3);
      
      // それぞれのアカウントを任意の場所で出力
      foreach( $rss1 as $item ){
        // ここでアカウント1のHTMLを出力
      }
      
      foreach( $rss2 as $item ){
        // ここでアカウント2のHTMLを出力
      }
      

      基本的にこちらの方法で出来るかと思うのですが、問題ありましたらまたコメントください。

  • みん

    Feb 06, 2015

    ご返信ありがとうございます。

    お教えくださった様にしたら複数アカウント表示に成功したのですが、
    上から記事を更新した順に表示したいのですけれども、そちらは可能でしょうか?

    返信

    • dackel

      Feb 08, 2015

      みん さん

      記事を並び替える方法ですが、とりあえず簡単に実現するなら下記の方法でできるかなと思います。

      例えば下記の様な関数を用意しておきます。

      // RSSを日付毎に並び替えます
      function sort_ameba_rss($rss, $order="DESC"){
        $order = $order === "DESC" ? SORT_DESC : $order;
        $order = $order === "ASC" ? SORT_ASC : $order;
        $keys = array();
        foreach( $rss as $item ){
          $keys[] = date("YmdHis", strtotime($item->pubDate));
        }
        array_multisort($keys, $order, $rss);
        return $rss;
      }
      

      取得したRSSをこの関数を通すことで並び替えをするというものです。
      ASCの部分をDESCにすることで、古いものが上にきます。

      $rss1 = get_ameba_rss("アカウント1のRSS", 3);
      $rss1 = sort_ameba_rss($rss, "ASC"); //新しい日付のものが上にきます
      

      あまりいいやり方では無いかもしれませんが、上記のようなものでどうでしょうか?

    • みん

      Feb 12, 2015

      ありがとうございます。
      無事解決いたしました!

    • dackel

      Feb 12, 2015

      みん さん
      解決できたようでよかったです、また何かあったらよろしくお願いします!

  • pp

    Feb 09, 2015

    dackel様
    初めまして、ppと申します。
    質問なのですが、表示される画像が最後のものになってると思うんですが
    最初のものにするにはどのようにしたらよいでしょうか?

    返信

    • dackel

      Feb 09, 2015

      pp さん
      はじめまして、コメントありがとうございます。
      記事中の一番最初の画像、ということであっていますか?
      get_ameba_rss()の中の27行目付近のコードを下記のように変更することで、対応できるかと思います。

      // ↓変更後のコード
      if( preg_match_all("/<img>/i", $item->description, $matches) ){
          $item->thumbnail = array_shift($matches[1]);
      }
      
      // ↓変更前のコード
      // if( preg_match_all('/<img>/is', $item->description, $matches) ){
      //  foreach( $matches[0] as $img ){
      //      if( preg_match('/src=[\'"](.+?jpe?g)[\'"]/', $img, $m) ){
      //          $item->thumbnail = $m[1];
      //      }
      //  }
      // }
      

      すいません、コメントに投稿すると正規表現の一部が消えてしまうみたいなので、変更したファイルをzipにまとめたので参考にしてみてください。

      Ver2 サンプルファイル

      もし動かなかったり、不明点な点などありましたらコメント頂けたらとおもいます。

  • pp

    Feb 12, 2015

    ありがとうございます、記事中の一番最初の画像表示されるようになりました。^^

    返信

    • dackel

      Feb 12, 2015

      pp さん
      動くかなぁと心配でしたが、無事表示されてよかったです!
      また機会があればよろしくお願いします。

  • us

    May 27, 2015

    はじめまして、usと申します。
    広告削除の方法など、大変助かりました。

    ただ、WordPress 4.2.2 で試してみたのですが、画像がうまく表示されませんでした。
    表示されたタグを見てみると、画像のURLは

    http://ドメイン/wp-content/themes/テーマ名/response.php?f=http%3A%2F%2Fstat.ameba.jp%2Fuser_images%2F20150526%2F23%2Fアメブロユーザー名%2Fb1%2F31%2Fj%2F画像名.jpg

    ↑となっていており、こちらをブラウザでみると、

    Fatal error: Call to undefined function get_template_directory() in /home/users/2/……./functions.php on line 43

    というエラーがでていました。
    お忙しいところ恐れ入りますが、ご教授頂けたら幸いです。

    返信

    • dackel

      May 27, 2015

      us さん
      はじめまして、コメントありがとうございます。

      エラーの内容からテンプレートのURLを取得している箇所で、エラーが出ているのではという感じがします。
      get_bloginfo("template_url")が非推奨になってしまっているみたいなので、もしかしたらそれが原因かも知れません。

      ちゃんと確認出来ていないので勘になってしまいますが、下記のようにget_bloginfo("template_url")が使用されている箇所を、get_stylesheet_directory_uri()に置き換えて試してみていただけるでしょうか?

      // $item->thumbnail = get_bloginfo("template_url") . "/images/noimage.jpg";
      $item->thumbnail = get_stylesheet_directory_uri() . "/images/noimage.jpg";
      
      // ...省略
      
      // $item->thumbnail = sprintf("%s/response.php?%s", get_bloginfo("template_url"), http_build_query($data));
      $item->thumbnail = sprintf("%s/response.php?%s", get_stylesheet_directory_uri(), http_build_query($data));
      

      もし上記でも動かなかった場合、差し支えない範囲で構いませんのでテーマ内のファイル構成など教えて頂けますと何か分かるかもしれません。

  • us

    May 28, 2015

    dackel様

    ご返信ありがとうございます。
    上記2点を変更してみましたが、表示されませんでした。

    テーマですが、公式テーマのtwentyfourteenを使用しています。

    ただ、間違って更新してしまわないように、
    フォルダ名とstyles.css内のテーマの説明についての記述の箇所だけを変更しています。
    function.php内のtwentyfourteenと記述があっても、そのままにしてある状態です。

    function.phpの43行目あたりには以下が書かれていました。

    /**
    * Twenty Fourteen only works in WordPress 3.6 or later.
    */
    if ( version_compare( $GLOBALS[‘wp_version’], ‘3.6’, ‘<‘ ) ) {
    require get_template_directory() . ‘/inc/back-compat.php’;
    }
    if ( ! function_exists( ‘twentyfourteen_setup’ ) ) :
    )

    themes>ustheme(テーマ名)
     ——-index.php(ここに// RSS情報を取得するのコードを入れてあります)
     ——-function.php
     ——-response.php

    ファイル構成、っということですが
    こんな情報しかわからず、すみません….よろしくお願いいたします。

    返信

    • dackel

      May 28, 2015

      us さん
      状況を教えてくださりありがとうございます!
      ustheme/response.phpの上部でファイルを読み込んでいる箇所を、下記のように変更してみて頂けますか?

      // include_once(dirname(__FILE__)."/functions.php");
      include_once(dirname(__FILE__) . "/../../../wp-load.php");
      

      単純にWordPressの関数群が読み込まれておらず、get_template_directory()が無いとのエラーが出ているのかと考えました。
      上記ではwp-load.phpを読み込み、WordPressの初期化を行って関数やクラスなどが使用できる状態にしています。

  • us

    May 29, 2015

    dackel様

    教えていただいた通りに変更しますと、表示されました!
    本当に丁寧に教えてくださり、ありがとうございました!

    ただnoimageの画像が表示されず、画像の置く場所が違うのだとは思うのですが….

    themes
     >ustheme(テーマ名)
      ——-index.php(ここに// RSS情報を取得するのコードを入れてあります)
      ——-function.php
      ——-response.php
      ——-noimage.jpg
     >image
      ——-noimage.jpg

    と置いてみたのですが、どれもうまく表示されませんでした。
    何度も申し訳ありません。デフォルト画像はどこに置いておけばいいのでしょうか?

    返信

    • dackel

      May 29, 2015

      us さん
      とりあえず表示出来てよかったです! こちらで試した環境が相当シンプルなものだったので検証不足でした。
      あとでこの内容は記事に追記しないとですね…

      noimage.jpgですが、imageに入っているのでしょうか? 正しくはimagesで最後にsが付いているのが正しいディレクトリかと思います。
      上記が単純にコメント欄でのタイプミスでしたら、get_ameba_rss()内で画像へのパスが合っているか確認してみてください。

      // $item->thumbnail = テーマのURL . "/画像ディレクトリ/noimage.jpg";
      $item->thumbnail = get_bloginfo("template_url") . "/images/noimage.jpg";
      

      こちらでも表示出来ない場合、また状況を教えて頂けたらと思います!

  • us

    Jun 01, 2015

    dackel様

    パスの確認をしましたところ、やはり置く場所が違っていたようで、
    正しい場所に置くと表示されました!
    丁寧にご返信いただき、本当にありがとうございました

    おかげさまで想定していたものに仕上げることができました!
    ありがとうございました!

    返信

    • dackel

      Jun 01, 2015

      us さん
      画像表示の件、単純な問題でよかったです! それと、今回の件は記事に追記させていただきました。
      こちらこそありがとうございます。

      また何かありましたらよろしくお願いします!

  • ジェシー

    Jun 08, 2015

    初めまして。
    アメブロの画像表示に、困っており大変勉強になりました。
    ありがとうございます。

    当方、勉強不足で、ブログの更新日時も表示したいのですがやり方がわかりません。
    欲を言えば、ブログの数行も表示したいです。(続きを読むでリンク出来ると最高です。)
    ご教授いただけると幸いです。
    よろしくお願いいたします。

    返信

    • とおりすがりの仮面ラ…

      Jun 09, 2015

      ブログの更新日時を表示する。

      index.phpの24行目付近に

      pubDate)); ?>
      を追加すればOKですよー。

      ブログの数行を表示
      functions.phpのsimplexml_load_stringを 以下に修正
      simplexml_load_string($rss, ‘SimpleXMLElement’, LIBXML_NOCDATA);

      その後、index.phpで substr($item->description ,0,80)
      とすればOK(ここでは80文字を表示)

    • ジェシー

      Jun 10, 2015

      とおりすがりの仮面ラ…様
      ありがとうございます!
      教えていただいたとおりに作業し、表示することができました。
      心より感謝いたします。

  • 初心者

    Jul 06, 2015

    wordpressでアメブロのRSSを画像付きで表示したくてここにたどり着きました。拝見させて頂きましたが残念ながらよく分かりませんでした。サンプルファイルを落としましたがそれをどうすればいいのでしょうか?ご教授お願いします。

    返信

    • dackel

      Jul 07, 2015

      初心者さん
      はじめまして。コメントありがとうございます。

      WordPressで動作させるために、まずサンプルのファイルを指定の位置へ配置する必要があります。
      使用しているテーマディレクトリに下記のようにファイルを配置してみてください。

      .
      ├── images
      │   └── noimage.jpg
      └── response.php
      

      記事の中にある下記の関数をfunctions.phpに追記します。
      お使いのテーマに、functions.phpが無いようであれば新規作成してください。

      • curl_get_contents
      • get_mime_type
      • get_ameba_rss (追記:2014年9月29日のもの)

      functions.phpと、ファイルの用意ができたら、response.phpの一部を「追記:2014年9月29日」に沿って一部変更して下さい。

      そうしたら、RSSを表示したい箇所で下記を記載して下さい。

      <?php
      // RSS情報を取得する
      $rss = get_ameba_rss("http://feedblog.ameba.jp/rss/ameblo/webdesign-dackel/rss20.xml");
      foreach( $rss as $item ) : ?>
      <a href="<?php print $item->link; ?>" target="_blank">
        <p class="rss-image"><img src="<?php print $item->thumbnail; ?>" alt="<?php print $item->title; ?>"></p>
        <p class="rss-title"><?php print $item->title; ?></p>
      </a>
      <?php endforeach; ?>
      

      うまく行けば、これでブログの内容が表示されるようになると思います。
      もしここでエラーが出たりするようであれば、エラーの内容や不明点を添えて、再度ご相談頂ければと思います。

  • 初心者

    Jul 07, 2015

    早速の返信ありがとうございます。上記の方法で試してみたところ無事サンプルサイトの画像が表示されました。がしかし、お目当てのブログの画像は表示されず「no image」が表示されました・・・いくつか有名所のブログで試したところ以下の状況となりました。

    北斗昌さんのブログ⇒記事の最後の画像が表示されました
    東原亜希さんのブログ⇒記事の最後の画像が表示されました
    木下優樹菜さんのブログ⇒「no image」画像が表示されました
    市川海老蔵さんのブログ⇒「no image」画像が表示されました

    何か間違えているのでしょうか?ご教示お願い致します。

    返信

    • dackel

      Jul 09, 2015

      初心者さん
      返信遅くなってしまいすみません…。
      とりあえずサンプルブログで表示できてよかったです!

      表示されないブログがあるのは、RSS内で全文配信しているかしていないかの違いで、RSS内に<img>がない場合は「no image」の表示になると思います。
      全文配信していないものは、『著作権保護のため、記事の一部のみ表示されております。』という表示がされています。

      それと念のため追記となりますが、著作権の関係がありますので、本番環境ではご自分の管理されているブログ以外の記事情報を取得しないように注意してください。
      (開発時も避けるのが無難かと思います…!)

  • 初心者

    Jul 09, 2015

    表示されない原因が良く分かりました。いろいろ教えて頂いてほんとにありがとうございました。

    返信

  • やま

    Sep 08, 2015

    はじめまして。
    アメブロのRSSを画像付きで取得する方法を調べているところこちらの記事にたどり着きました。

    こちらのソースを元にいろいろと触っているのですが、どうしても本文記事の抜粋(200文字)ができません。
    よろしければご教授お願いいたします。

    返信

    • dackel

      Sep 09, 2015

      やま さん
      コメントありがとうございます。

      本文記事の抜粋が出来ないとのことですが、本文記事の内容自体は取得できているでしょうか?
      本記事でいうところのget_ameba_rss関数内の$item->descriptionの値です。

      もし確認方法がわからないようでしたら、get_ameba_rssを以下のよう書き換えてみて記事の内容が出力されるか確認してみてください。

      function get_ameba_rss( $url, $limit=5 )
      {
        $rss = simplexml_load_string($rss);
      
        foreach( $rss->channel->item as $item ){
          var_dump((string) $item->description);
        }
      
        return array();
      }
      

  • やま

    Sep 09, 2015

    早速の返信ありがとうございます。

    はい、記事の取得自体はできております。
    取得自体はできているのですが、ブログ記事の体裁(絵文字やら改行やら)がそのままが表示されている状態です。
    よろしくお願いいたします。

    返信

    • dackel

      Sep 09, 2015

      記事本文が取得できているようでよかったです。

      絵文字や改行がそのまま表示されてしまうのは、HTML文字列のままとなっているからだと思います。

      記事の抜粋を行うために、HTMLタグを除去して、指定した文字数分だけ切り取れば良さそうです。
      一部省略してしまっていますが、get_ameba_rss関数を以下のように変更してみました。

      function get_ameba_rss( $url, $limit=5, $excerpt_length=200 )
      {
        // ...省略
      
        foreach( $rss->channel->item as $item ){
      
          // ...省略
      
          // レスポンス用のPHPへのパスへ設定する
          $data = array("f" => (string)$item->thumbnail);
          $item->thumbnail = sprintf("response.php?%s", http_build_query($data));
      
          // 本文記事の抜粋 (HTMLタグ、改行コード、前後余白を除去)
          $excerpt = strip_tags($item->description);
          $excerpt = str_replace(array("\r\n", "\r", "\n"), "", trim($excerpt));
          $item->excerpt = mb_substr($excerpt, 0, $excerpt_length, "UTF-8");
      
          $results[] = $item;
        }
      
        return $results;
      }
      

      主な変更は下記です。

      1. 引数に抜粋文字数$excerpt_lengthを追加
      2. $itemexcerptプロパティを追加

      あとは、抜粋を表示したい箇所で次のようにすればOKかなと思います。

      <p class="excerpt"><?php print $item->excerpt; ?></p>
      

      一応指定した文字数で本文の抜粋を出来るようにしてみましたが、意図するものと違っていたらすみません!

  • やま

    Sep 15, 2015

    返信が遅くなりまして申し訳ございません。

    上記教えていただいたコードで無事、
    思っていたとおりに本文抜粋を表示させることができました!
    ありがとうございました、

    返信

    • dackel

      Sep 15, 2015

      思ったとおりの動作ができたようでよかったです! 分かりづらかったかなと思っていたので安心しました。
      また何かありましたらご相談ください〜。

  • SAKURA

    Sep 30, 2015

    ロリポップのサーバーだと、画像が表示されません。
    別のサーバーでは表示されるのを確認しました。

    サーバーにより表示されないとかありますか?

    返信

    • dackel

      Oct 01, 2015

      SAKURA さん
      はじめまして、コメントありがとうございます。

      サーバによっては動かないことがあると思います。
      何かエラーメッセージなど出ていましたら、分かる範囲で構いませんので教えていただくことは可能でしょうか?

      原因特定の手掛かりになるかもしれません。

  • SAKURA

    Oct 01, 2015

    返信ありがとうございます。

    エラーメッセージは以下になります。
    Failed to load resource: the server responded with a status of 403

    ロリポップが新サーバーに移転してから画像が表示されなくなりました。

    返信

    • dackel

      Oct 01, 2015

      エラーメッセージありがとうございます。
      404ではなく、403エラーなのですね。

      RSSの情報自体が取得できているかどうか確認できるでしょうか?
      例えば、記事の内容や画像のファイル名などです。

      記事中の内容でいうと、下記$rssの中身のことです。var_dump()などで出力を確認できると思います。

      // RSS情報を取得する
      $rss = get_ameba_rss("http://feedblog.ameba.jp/rss/ameblo/webdesign-dackel/rss20.xml");
      
      // 内容を確認
      var_dump($rss);
      

  • 通りすがり

    Oct 14, 2015

    間違っていたらすみません、本文中の「記事中の最初の画像を取得、表示用のPHPへ値を渡す」の箇所が、「記事中の最後の画像を取得、表示用のPHPへ値を渡す」ではないのかなーと思いました。
    それにしても分かりやすい記事を有り難うございます。
    よろこんぶしております!

    返信

    • dackel

      dackel

      Oct 16, 2015

      通りすがり さん

      コメントありがとうございます。参考になったみたいでよかったです。。

      画像の部分ご指摘ありがとうございます、記事修正しました。
      確かに最初の画像をとってなかったですね…。笑

  • unyora

    Nov 26, 2015

    お世話になります。助かりました。
    wordpressの場合
    get_bloginfo(“template_url”)
    だと親テーマ
    get_stylesheet_directory_uri()
    だと子テーマをみにいきますので、注意が必要ですね。

    返信

    • dackel

      dackel

      Nov 26, 2015

      unyora さん
      コメントありがとうございます。

      仰るとおり子テーマを使う場合だと、必要に応じて変更する必要がありそうですね。
      子テーマの事は全く想定外だったので参考になりました!

  • unyora

    Nov 27, 2015

    お返事ありがとうございます。
    ところで
    “/<img([\s\S]+?)>/is”,
    正規表現のisはこの場合何のためにあるのでしょうか?
    phpは全く不慣れのため、素人の質問誠にすいません。

    返信

    • dackel

      dackel

      Nov 27, 2015

      isは修飾子と呼ばれる正規表現のオプションです。

      それぞれの意味は、

      • i : 大文字・小文字を区別しないマッチング
      • s : .(改行以外の1文字)を改行も含めてマッチング

      といった具合で、preg_matchや、preg_match_allに指定するパターンにオプションを加えることが出来ます。
      他にも様々な修飾子がありますので、以下のページを見てみると参考になるかもしれません。

      PHP: 正規表現パターンに使用可能な修飾子 – Manual

      と、書きましたが正規表現に一部、無駄があることに気がついたので記事中のコード修正しました…。

      '/<img([\s\S]+?)>/is'から、'/<img(.+?)>/is'にしています。

      記事を見直すきっかけになりました、ありがとうございます!

  • まめくま

    Dec 05, 2015

    はじめまして。記事を参考にさせていただいております。大変わかりやすく本当に助かっております。ありがとうございます。サンプルをダウンロードさせていただき、設置しましたところ、うまくできました。

    アメブロの広告を外す件なのですが、最近『PR』が広告文の一番後ろについていることがあります。
    一番後ろについていた場合、どのようなコードを書けばいいのでしょうか?ご教授いただければ嬉しいです。
    お恥ずかしながら、PHPは全くの初心者です。ずうずうしい質問すみません!

    返信

    • dackel

      dackel

      Dec 06, 2015

      まめくま さん
      はじめまして。コメントありがとうございます。
      参考になったようでよかったです…!

      広告のPRが一番後ろにあるとのことですが、以下の様なコードに変更してみるのはいかがでしょうか?

      if( strpos($item->title, "PR:") !== false || ($limit >= 0 && count($results) >= $limit) ){
        continue;
      }
      

      preg_matchの代わりに、strposを使うように変更しています。
      内容としては、「PR:から始まる」では無く「PR:を含む」、という条件になっています。

      広告文が最後に入っているパターンが手元で実現出来なかったので、上記の変更でいけるか未検証です。
      もし差し支えないようであれば、どのような文字列(タイトル)が渡ってくるか教えていだけると、もう少し最適化してお答えできるかもです!

    • dackelさま

      Dec 07, 2015

      ご返答いただき、本当にありがとうございます!ラッキーなことに(?)今朝、『PR』が後ろについてくる広告が入ってきました。『借金で悩んでいませんか?-政府広報: PR』というものです。『:』『PR』の間は半角あいているように思えます。

      教えていただいたコードで設置してみました。『PR』を含む、にしたので”PR:”の部分の『:』を抜いてみました。無事に上記の広告もはじくことができて、成功致しました!

      if( strpos($item->title, “PR”) !== false || ($limit >= 0 && count($results) >= $limit) ){
      continue;
      }

      成功してすごくすごく嬉しいです。助かりました。お忙しい中、ご教授いただき本当にありがとうございました。

    • dackel

      dackel

      Dec 07, 2015

      動かせたようでよかったですー!

      PRを含む」という条件の場合、若干ルールとして緩いような気がするので、教えていただいた広告分を元に条件を調整してみました。
      以下のコードでは、「PR:で始まる、又は: PRで終わるタイトル」という条件になっています。

      if( preg_match("/^(PR:.+|.+:\sPR)$/", $item->title) || ($limit >= 0 && count($results) >= $limit) ){
        continue;
      }
      

      もし、タイトルにPRという文字を使っちゃいそうな場合、こちらの条件に変更してみていただけると良さそうです!
      また何かあればご相談いただければと思います。

    • まめくま

      Dec 07, 2015

      dackelさま

      先ほど新たに教えていただいた「PR:で始まる、又は: PRで終わるタイトル」の分もテストしてみましたところ、大丈夫でした!
      ご親切に教えていただき感激です!本当にありがとうございました。

  • まめくま

    Jan 11, 2016

    先日もご教授いただきましたまめくまと申します。先日は本当にありがとうございました。
    あれからも拝見させていただいております。

    今回また本文抜粋時の絵文字削除の件で困ってしまい、再度コメントさせていただきました。

    Sep 09, 2015のやま様のコメントの記事より

    function get_ameba_rss( $url, $limit=5, $excerpt_length=200 )
    {
    // …省略

    // 本文記事の抜粋 (HTMLタグ、改行コード、前後余白を除去)
    $excerpt = strip_tags($item->description);
    $excerpt = str_replace(array(“\r\n”, “\r”, “\n”), “”, trim($excerpt));
    $item->excerpt = mb_substr($excerpt, 0, $excerpt_length, “UTF-8”);

    を追加して、HTMLの表示したいところに 

    excerpt; ?>

     を記載しました。

    しかし、それでも表示してしまう絵文字があります。

    アメブロの絵文字は例えば、


    たぶん①はスマホからの投稿の時のような気がします。

    があるようで、①のpng画像の絵文字が本文の画像より先にきた場合、最初の画像として表示されてしまいます。
    ②と③は大丈夫でした。

    見当違いかもしれませんが、画像取得の時の

    // 記事の中で最初に使われている画像を検索、設定する
    if( preg_match_all(“/<img.+?src=\”‘[\”‘].*?>/i”, $item->description, $matches) ){
    $item->thumbnail = array_shift($matches[1]);
    }

    の[jpeg|jpg|png]、ここのpngを抜いてみたりしてもダメでした。

    他サイトで絵文字の文字列、”stat.ameba.jp/blog/ucs/img”, “emoji.ameba.jp”,”stat100.ameba.jp/blog/ucs/img”を排除すればよいというふうな記事があり、コードも書いてあったのですが、アメブロの画像取得のプログラムがそもそもdackel様のものと違うので、分からなくなってしまいました。
    もし何かお分かりでしたらご教授いただければすごく助かります。

    あと、このdackel様のプログラムでは本文抜粋の後に『…Read More』などの文をつけるときはどうすればよいでしょうか?
    いつもは下記のようにしております。
    $description = mb_strimwidth (strip_tags($item->description), 0 , 100, “…Read More”, “utf-8”);

    長々と申し訳ございません。よろしくお願い致します。

    返信

  • まめくま

    Jan 11, 2016

    何度もすみません。
    先ほど投稿したものを見直すと、一部消えてしまっているところがありました…

    アメブロの絵文字は例えば、

    たぶん①はスマホからの投稿の時のような気がします。

    上記の空白の部分は<imgタグから始まる画像のURL>を記載しております。
    仕様か何かで投稿の時に削除されるのでしょうか…

    返信

    • dackel

      dackel

      Jan 16, 2016

      まめくま さん

      返信が遅くなってしまいすみません。。
      コメントの仕様で一部消えてしまっていたようです。お手数をおかけしました…

      絵文字の件、画像の検索部分を以下のように書き換えてみるのはどうでしょうか。

          // 記事の中で最初に使われている画像を検索、設定する
          $blacklist = array(
            "stat.ameba.jp/blog/ucs/img",
            "emoji.ameba.jp",
            "stat100.ameba.jp/blog/ucs/img"
          );
      
          if (preg_match_all('/<img(.+?)>/is', $item->description, $matches)) {
            foreach ($matches[0] as $img) {
              $is_white = true;
              foreach ($blacklist as $path) {
                if (strpos($img, $path) !== false) {
                  $is_white = false;
                }
              }
              if ($is_white && preg_match('/src=[\'"](.+?(?:jpe?g|png))[\'"]/i', $img, $m)) {
                $item->thumbnail = $m[1];
              }
            }
          }
      

      実際に試せてはいませんが、コメントいただいた除外用のURLsrcに含まれる場合は結果に含めないようにしています。

      本文の抜粋は、Sep 09, 2015の僕(dackel)のコメントが参考になるかなと思います。

    • まめくま

      Jan 17, 2016

      dackelさま

      コメントにお返事いただいてありがとうございます。嬉しいです。お忙しい中、本当にごめんなさい…
      絵文字の件ですが、教えていただいたコードで実行してみますと、無事に成功致しました!排除できなかった絵文字も排除できました。あと、本文抜粋の件も大丈夫です。思い通りにできました。

      分からなくて心が折れていたので、本当に助かりました。また参考に勉強させていただきます。ご丁寧にありがとうございました。

    • dackel

      dackel

      Jan 18, 2016

      まめくま さん

      無事に解決出来たようでよかったです…!
      すぐに返信出来ないこともありますが、また何かありましたらお気軽にご相談いただければと思います。

    • まめくま

      Jan 19, 2016

      dackelさま

      こんにちは、しつこく何度もすみません…先日ご教授いただいた件でまた質問させていただきます。先日のコードでは記事の一番最後の画像を取得しているようです。絵文字はちゃんと排除されております。私の確認ミスで、また質問することになってしまい恐縮です。。。
      一番最初の画像を取得するにはどうしたらよろしいでしょうか?
      お時間あるときで結構ですので、またご教授いただければ助かります。

    • dackel

      dackel

      Feb 01, 2016

      まめくま さん

      返信遅くなってしまいすみません。。
      僕もすっかり「最初の画像」を忘れていました…

      $item->thumbnail = $m[1];
      

      上記コードにbreak;を追加してみるのはいかがでしょうか。

      $item->thumbnail = $m[1];
      break;
      

      foreachで全ての画像を走査してしまっていたので、条件の合致する画像が見つかった時点で走査を抜ける想定です。

  • まめくま

    Feb 04, 2016

    dackelさま

    返信いただきありがとうございます。お忙しい中、本当にすみません…
    上記を追加してみますと、最初の画像が取得でき、うまくいきました!(絵文字もちゃんと排除されています)
    本当にありがとうございました。お礼のお返事が遅くなってしまいました。何度もご教授いただき感謝致します。

    返信

  • us05

    Jul 08, 2016

    お世話になります。
    アメブロのRSS取得、こちらの通りにさせていただきましたら、うまくいきました。
    ありがとうございます。

    日付と本文(文字数制限あり)もしたいな、と思っておりますが、
    こちらでリクエストなどしてもよろしいでしょうか?
    …お忙しいところすみませんが、よろしくお願いいたします。

    返信

メールアドレスが公開されることはありません。お気軽にコメントどうぞ。