XML-RPCという仕組みが使われていて、大体weblogUpdates.extendedPingか、weblogUpdates.pingというメソッド名が使われる。IXR_Library.phpというライブラリがあるのでこれを使って作る。飛んでくる情報の最小単位はブログ名とブログURLなので、ブログURLからRSSのURLを取得して、RSSから最新記事のURLとタイトルを取得する。WordPressがweblogUpdates.extendedPingで、アメブロとライブドアが、weblogUpdates.pingだった。wordpressは、array(ブログ名、ブログURL、RSS_URL)できた。RSS URLを取得するのにphpQuery使おうと思ったけど、どうもライブドアだとエラーになるから使うのやめた。あとアメブロのRSSは、新規投稿が1分後くらいにしか反映されないから、CRONで5分後に再チェックするようにした。
<?php App::uses('AppController', 'Controller'); App::import('Vendor', 'xmlrpc'); //App::import('Vendor', 'phpquery/phpQuery/phpQuery'); class PingController extends AppController { public $uses = array('Site'); public function beforeFilter() { parent::beforeFilter(); $this->Components->disable('Security'); $this->Auth->allow(array('index')); Configure::write('debug', 0); $this->autoRender = false; } public function index() { $callbacks = array(); $callbacks['weblogUpdates.ping'] = array(&$this, '_updates'); $callbacks['weblogUpdates.extendedPing'] = array(&$this, '_updates_extended'); $callbacks['weblogUpdates.pbping'] = array(&$this, '_pbping'); $this->server = new IXR_Server($callbacks); } public function _updates($data) { $this->log('weblogUpdates.ping', 'debug'); if(empty($data[1])){ $this->log('Fail to updates.', 'debug'); $this->log($data, 'debug'); return false; } if($this->_get_new_post($data[1])){ return true; } return false; } public function _updates_extended($data) { $this->log('weblogUpdates.extendedPing', 'debug'); if(empty($data[1]) || empty($data[2])){ $this->log('Fail to updates_extended.', 'debug'); $this->log($data, 'debug'); return false; } if($this->_get_new_post($data[1], $data[2])){ return true; } return false; } public function _pbping($data) { $this->log('weblogUpdates.pbping', 'debug'); $this->log($data); } private function _get_new_post($blog_url, $rss_url = null) { if(!$site = $this->Site->findByUrlForPing($blog_url)) return false; if(!$rss_url){ if(!$rss_url = $this->_get_rss_url($blog_url)) return false; } if(!$rss = $this->_get_rss($rss_url)) return false; if(!$this->Site->saveNewPost($rss['url'], $rss['title'], $site['Site']['id'])){ $this->log('Fail to save new post', 'debug'); return false; } return true; } private function _get_rss_url($blog_url) { $pattern = '/type="application\/rss\+xml".+?href="(.+?)"/s'; $html = file_get_contents($blog_url); if(!preg_match($pattern, $html, $match)){ $this->log('Not Match. '.$blog_url, 'debug'); return null; } return $match[1]; } //private function _get_rss_url($blog_url) //{ // try{ // $doc = phpQuery::newDocumentFile($blog_url); // return pq($doc)->find('link[type=application/rss+xml]:first')->attr('href'); // }catch(Exception $e){ // $this->log('Fail to get rss url: '.$e->getCode().'|'.$e->getMessage(), 'debug'); // return null; // } //} private function _get_rss($rss_url) { try{ $rss = Xml::build($rss_url); if(!empty($rss->channel->item[0])){ $item = $rss->channel->item[0]; }elseif(!empty($rss->item[0])){ $item = $rss->item[0]; } return array( 'url' => (string)$item->link, 'title' => (string)$item->title ); }catch(Exception $e){ $this->log('Fail to get rss: '.$e->getCode().'|'.$e->getMessage(), 'debug'); return null; } } }
参考: 更新Pingの送信 Pingを送信する! Google ブログ検索の更新通知 API について CakePHP + 更新Ping送信で更新情報サービスを利用する方法 IXRライブラリの使い方 utils/Model/Behavior/PingbackableBehavior.php How-to-create-an-XML-RPC-server-with-CakePHP.rst CakePHP-Wordpress-Datasource/Vendor/IXR_Library.php [42-3] link rel="alternate" で他言語サイトやモバイル版へ導こう