【WordPress】 WordPressをフィードアンテナ化するまとめ(その3)

前回の続きです。
getfeed関数についてです。

今回はこの右側部分です。

20141204_feedantenna_05b

スポンサーリンク

 getfeed関数

crawl.phpから呼び出されるgetfeed関数を見て行きましょう。
これは使用しているテーマの中のfunctions.phpに記載します。

function getfeed($url, $num = 1, $post_cat){	//フィード取得・データベース取り込み処理用関数

	date_default_timezone_set('Asia/Tokyo');	//東京時間
	include_once(ABSPATH . WPINC . '/class-simplepie.php');		//SimplePieインクルード

	$feed = new SimplePie;	//オブジェクトの生成
	$feed->set_feed_url($url);	//フィードurlを指定
	$feed->enable_cache(false);	//キャッシュを無効に指定
	$feed->init();	//解析を実行

	$items = $feed->get_items(0, $num);	//指定数のフィードを取得
	$lists = Array();
	foreach($items as $item) {

		/* pickup data */	//フィードから必要なデータを取得
		$list = Array(
			'date' => $item->get_date('Y-m-d H:i:s'),	//投稿日付と時間を取得
			'title' => $item->get_title(),	//記事のタイトルを取得
			'link' => $item->get_link(),	//記事のURLを取得
			'sitetitle' => $item->get_feed()->get_title(),	//サイトタイトルを取得
			'sitelink' => $item->get_feed()->get_permalink(),	//サイトのURLを取得
			'contdescription' => $item->get_description(),	//記事の抜粋を取得
		);

		/* post data */		//データベース格納用に配列で整形
		$post = array();
		$post['ID'] = ''; 
		$post['menu_order'] = '';
		$post['comment_status'] = 'closed';
		$post['ping_status'] = 'closed';
		$post['pinged'] = '';
		$post['post_author'] = '';
		$post['post_category'] = array($post_cat) ;	//カテゴリーの指定
		$post['post_content'] = "{$list['link']}-::-{$list['title']}-::-{$list['sitelink']}-::-{$list['sitetitle']}-::-{$list['date']}";	//記事本文
		$post['post_date'] = $list['date'];	//WordPressの投稿日時・時間は取得した記事のものを使う 
		$post['post_date_gmt'] = ''; 
		$post['post_excerpt'] = $list['contdescription'];
		$post['post_name'] = ''; 
		$post['post_parent'] = ''; 
		$post['post_password'] = ''; 
		$post['post_status'] = 'publish'; 
		$post['post_title'] = $list['title'];
		$post['post_type'] = 'post';
		$post['tags_input'] = $list['sitetitle']; 	//記事のサイト名をWordPressのタグに指定 
		$post['to_ping'] = ''; 

		/* database connection */	//データベース接続
		$link = mysql_connect('データベースアドレス', 'ユーザー名', 'パスワード');
		if (!$link) {
			die('login failed---'.mysql_error());	//エラーの場合は処理停止
		}
		echo "login OK / ";

		$db_selected = mysql_select_db('データベース名', $link);

		if (!$db_selected) {
			die('DB connect failed---'.mysql_error());	//エラーの場合は処理停止
		}
		echo "DB connect OK / ";

		$resultb = mysql_query("SELECT post_title,ID FROM postsテーブル名 WHERE post_content LIKE \"{$list['link']}%\"");		//記事URLをセレクト

		if (!$resultb) {
			die('DB select failed---'.mysql_error());	//エラーの場合は処理停止
		}
		echo "DB select OK / ";		//セレクト成功(同じ記事URLがあってもなくても)

		$duplicate_num = mysql_num_rows($resultb) ;	//セレクトできた記事URLの数
		echo $duplicate_num ;

		/* insert post */	//データベース取り込み
		if ($duplicate_num == 0 ) {	//同じ記事URLがない場合
			$insert_id = wp_insert_post( $post );		//DBへ格納し、自動採番される投稿IDを取得
			if ($insert_id) {
				echo "post OK / ";
				echo $insert_id;
				echo $list['title'];
				echo $list['link'];
				update_post_meta($insert_id, 'custom_title', $list['title']);	//例)カスタムフィールドに記事タイトルを追加する場合
			} else {
				echo "post failed";
			}
		} else {
			echo "post skip";	//同じ記事がある場合はスキップ
		}
		echo "<br />\n";

	}
}

必要はないのですが、カスタムフィールドに記事タイトルを追加する処理を加えています。
カスタムフィールドへ追加する場合は対象記事の投稿IDが必要になります。
このため、記事をデータベースに取り込んだときに自動採番される投稿IDを取得し、それを用いて再度データベースに取り込むという処理をします。
何かと使いそうなので、例として追加しておきました。
必要がなければupdate_post_metaの部分は削除してください。

フィード取り込みテスト

crawl.phpをWordPressをインストールしているディレクトリ(wpとか)に入れ、getfeed関数を使っているテーマのfunctions.phpに追記すると手動でも記事の取り込みが可能になります。

http://サイトURL/crawl.phpをブラウザに打ち込みエンターを叩くと、処理が実行されます。

20141204_feedantenna_11

記事一覧を見てみるとこのように取り込まれています。

20141204_feedantenna_14b

記事はどうなっているかというと、

20141204_feedantenna_15

このように必要な情報がまとめられた1行の本文となります。

カスタムフィールドも無事記事タイトルが追加されています。
記事タイトルを入れるという意味のない処理ですが、こういうことも出来るということで。

一度記事を取り込むとサイト名でタグが自動的に追加されています。

20141204_feedantenna_12

データベースはこんな感じ。

20141204_feedantenna_13

カスタムフィールドのテーブル「postmeta」にはこのように追加されています。

20141204_feedantenna_16

一番下であれば、23970という投稿IDの記事のcostom_titleというmeta_keyはこの内容ですという意味です。

手動の取り込みテストで問題なければ、crawl.phpをCRONで叩くように設定すればここまでは終了です。

注意点

1)セキュリティについて

指定したフィードではあるものの、外部データを自動で取り込んで処理をしていますのでどんなデータを扱っているのか分かりません。
セキュリティ対策は必要に応じて追加してください。

特にブログではPHPでも使う特殊文字である「”」「’」「<」「&」「=」などを記事タイトルや本文抜粋で使うことが非常に多く、悪意がなくても不具合を起こす可能性があります。
このためWordPressに入れるまでの前処理、取り出した後の後処理の部分にはクロスサイトスクリプティング対策をやっておいたほうがいいと思います。

2)データベース接続のエラーメッセージ

これは解決できなかったことなのですが、データベースに接続できなかったときのエラーメッセージがなぜか表示されません。

20141204_feedantenna_17

コードを間違えているのか、自分の環境が悪いのか、はたまたそういう仕様なのか、全く原因がわからない状態です。

他の2箇所のセレクトの部分はキチンとエラーコードが出るのですが、このデータベースの接続だけがエラーコードの取得が出来ないのです。

20141204_feedantenna_18

エラーメッセージが出ないだけで機能は問題ないので大したことではないのですが、気持ちが悪いなぁと。

もし分かる方がいらっしゃいましたら是非教えて下さい。

3)手動テスト時の注意

取得した記事を削除して繰り返しテストをすることになりますが、記事はゴミ箱から完全に消去しないと同じ記事を取り込むことができません。

20141204_feedantenna_19b

これはデータベース上に記事のステータスがtrashになっているだけなのです。
記事は完全に消去する必要があります。

まとめ

ここまでで記事の自動取り込みが可能になりました。

20141204_feedantenna_20

今回は記事抜粋はデータベースに取り込んではいますが使いません。
データベースに取り込むデータ、記事本文に表示させるデータは好みに応じて変化させてください。

またサイトを機能で差別化をしようとしたときにカスタムフィールドが役に立ちます。
カスタムフィールドはクリックカウンタや記事への評価など、公開後のユーザーの行動で動的に変化するものを扱うのにも適しています。
いろいろアイデアを試してみてください。

次回は固定ページにこの記事一覧を出力させます。

思った以上にまとめるのは大変です。
気長に待っていただけると助かります。

スポンサーリンク
  • このエントリーをはてなブックマークに追加

コメント

  1. n より:

    こんにちは。
    とても参考になる記事をありがとうございます。

    質問なのですが、getfeed関数のソースの61行目
    $resultb = mysql_query(“SELECT post_title,ID FROM postsテーブル名

    この部分の「postsテーブル名」は$wpdb->postsと同じですか?
    また、ここを $wpdb->posts という書き方にしても問題ないでしょうか。

    • 雨男 より:

      コメントありがとうございます!
      はい、その通りでいいと思います。

      ・・・あらら!?
      ソース確認したら私直接テーブル名書いていましたね。。

      せっかくなので$wpdb->postsに直してみましたが問題なく動いています。
      記事がなんだか微妙な書き方になっていたのは勉強中だったということで許してください。

      実はこの記事を書いた直後に入院してしまい
      サイトの更新やアンテナのカスタムが中途半端な形で止まっています。
      申し訳無いです。

      しかしアンテナサイトはいまだに動いています(?)

      http://nantena.net/

      暇ができたら全部作り直したいなとは思っているのですが。

      それでは、また。

      • n より:

        こんにちは。
        返信ありがとうございます。

        ソースを参考に使わせていただき、記事の取得を行ってみたのですが
        URLが https:// から始まるRSSフィードだけ取得が出来ません。

        管理人さんは https//~ のフィードも問題なく取得できますか?
        個人的に調べてたのですが、SimplePieのcurlの記述に curl_setopt($fp, CURLOPT_SSL_VERIFYPEER, false);を加えると直せるみたいな情報も見つかるのですが、Wordpressに付いてくるSimplePieを直接編集するのもどうなのかなーというところで悩んでおります…。

        • n より:

          度々すいません。色々弄っていたらできました…。
           $feed = new SimplePie;
          の下に追記↓
           $feed->set_curl_options( 
          array(
          CURLOPT_SSL_VERIFYHOST => false,
          CURLOPT_SSL_VERIFYPEER => false
          )
           );
          ただ、デフォルトのclass-simplepie.phpを使うと上手く行かなかったので
          直接SimplePieをダウンロードしてそちらを読み込むように変えました。
          https://github.com/simplepie/simplepie/releases/tag/1.5

          もしかするとWordpressに付属している方でも可能かもしれませんが
          私の技術力では難しかったです…少しでも参考になりましたら幸いです。

          • 雨男 より:

            そう言えば私、登録しているサイトにはhttps://ないですね。
            ということで新たにhttps://のサイトを追加してみると、

            ・・・問題なく拾っていますね。
            うーん、、

            サーバー証明書の検証をキャンセルすると動くのであれば、
            対象サイトの証明書が怪しいと判断されてエラーがでたのかもしれません。

            しかしこのシステムでは対象サイトの素性を知った上で登録していますので、
            検証をキャンセルしても大きな問題ではないようにも思います。

            私のサイトでも今後同じ問題が出るのかもしれませんね。
            貴重な情報ありがとうございます!
            しっかり覚えておきますね。

コメントをどうぞ

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA