人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

複数サイトのRSS表示について

http://www.zakzak.co.jp/rss/sports/etc_sports.xml
http://number.bunshun.jp/list/rsscolumn
http://gendai.net/articles/feed.rss
http://sankei.jp.msn.com/rss/news/points.xml
の4つのサイトから
'title'要素に
「関塚」又は「なでしこ」又は「柔道」
の3つの文字のあるデータを
日付順に並べて、出力する構文を
http://1811way.com/work008/20120730-02.txt
を元に修正していただけますか。

よろしくお願いします。

●質問者: kohhi
●カテゴリ:ウェブ制作
○ 状態 :終了
└ 回答数 : 3/3件

▽最新の回答へ

1 ● oil999
●100ポイント

エラーチェックはしていません。
複数サイトのRSSは、冒頭の配列$rss_urlsに代入してください。いくつでもOKです。

<?php
//ブログなどのRSS FEEDのURL設定
$rss_urls = array(
'http://b.hatena.ne.jp/hotentry?mode=rss&cname=elec',//rdfのURL例 はてなブックマーク
'http://ideblog.info/feed',// rss2.0のURL例
'http://number.bunshun.jp/list/rsscolumn'// atomのURL例
);

//出力データ用
$items[] = array();

// 検索キーワードを設定
$keyword = '/関塚|なでしこ|柔道/ui';
// 最大読み込み件数を設定 
$num_of_data = 5;
// 読み込みカウンタも初期化
$count_of_data = 0; 

foreach ($rss_urls as $url) {
//設定した読み込み件数分だけ取得できたらループを抜ける
if ($count_of_data >= $num_of_data) { break; }

$rssdata = simplexml_load_file($url);
if ($rssdata->getName() == 'feed') {
// atom の場合の処理
$children = $rssdata->children('http://www.w3.org/2005/Atom');
 // 記事ループ
 foreach ($children->entry as $myEntry) { 
 $items[$count_of_data]['myTitle'] = $myEntry->title; //タイトル取得
 if (preg_match($keyword, $items[$count_of_data]['myTitle'])) {
 $items[$count_of_data]['myDate'] = $myEntry->published; //日付取得
 //リンクURL取得
 $items[$count_of_data]['myAttr'] = $myEntry->{'link'}->attributes();
 $items[$count_of_data]['myLink'] = $myAttr['href'];
$count_of_data++;
}
 }
} else if ($rssdata->getName() == 'rss') {
 // rss2.0 の場合の処理
 // 記事ループ
 foreach ($rssdata->channel->item as $myEntry) {
 $items[$count_of_data]['myTitle'] = $myEntry->title; //タイトル取得
if (preg_match($keyword, $items[$count_of_data]['myTitle'])) {
 $items[$count_of_data]['myDate'] = $myEntry->pubDate; //日付取得
 $items[$count_of_data]['myLink'] = $myEntry->link; //リンクURL取得
$count_of_data++;
}
 }
} else if ($rssdata->getName() == 'rdf') {
 // rss1.0 の場合の処理
 // 記事ループ
 foreach ($rssdata->item as $myEntry) {
 $items[$count_of_data]['myTitle'] = $myEntry->title; //タイトル取得
 if (preg_match($keyword, $items[$count_of_data]['myTitle'])) {
 $items[$count_of_data]['myDate'] = $myEntry->pubDate; //日付取得
 $items[$count_of_data]['myLink'] = $myEntry->link; //リンクURL取得
$count_of_data++;
}
 }
 }
}

//出力内容を空っぽに初期化 
$outdata = ''; 
foreach ($items as $item) {
//出力内容にタイトル(リンク付)を入れる 
$outdata .= '<h3 class="posttitle"><a href="' . $item['myLink'] . '">' . $item['myTitle'] . '</a></h3>' . "\n"; 
//出力内容に日付けを入れる 
$outdata .= '<p class="postdate">' . $item['myDate'] . '</p>' . "\n"; 
}

//echo $rssdata->getName() . "\n";
echo $keyword . 'の検索結果は' . $count_of_data . "件です\n";
echo $outdata;//全部出力する
echo "End\n";
?>

kohhiさんのコメント
早速お返事いただきありがとうございました。

2 ● うぃんど
●300ポイント ベストアンサー

URLを配列に入れておいてループさせるように改良

先頭に形式を整えた日時を加えることでソートできるようにして、
最終出力段階でソート用の先頭の日時を消すという形にしています。

後から並び替えやすいように、$outdata は配列に変更しています。
検索結果件数のカウントは削除しました。

<?php
//ブログなどのRSS FEEDのURL設定
$url_array = array(
 'http://www.zakzak.co.jp/rss/sports/etc_sports.xml',
 'http://number.bunshun.jp/list/rsscolumn',
 'http://gendai.net/articles/feed.rss',
 'http://sankei.jp.msn.com/rss/news/points.xml'
);

// 検索キーワードを設定
$keyword = '/関塚|なでしこ|柔道/';
// 最大出力件数を設定
$num_of_data = 3;

//出力内容を空っぽに初期化(並び替え易いようにするため配列に変えました)
$outdata = array();

// ループ
foreach ($url_array as $url) {
 // 読み込みカウンタ初期化
 $count_of_data = 0; 
 // 読み込み
 $rssdata = simplexml_load_file($url);
 // データの形式によって分岐
 if ($rssdata->getName() == 'feed') {
 // atom の場合の処理
 $children = $rssdata->children('http://www.w3.org/2005/Atom');
 // 記事ループ
 foreach ($children->entry as $myEntry) { 
 $myTitle = $myEntry->title; //タイトル取得
 if (preg_match($keyword, $myTitle)) {
 $myDate = $myEntry->published; //日付取得 
 //リンクURL取得
 $myAttr = $myEntry->{'link'}->attributes();
 $myLink = $myAttr['href'];
 //出力内容にタイトル(リンク付)と日付を入れる
 array_push($outdata,
 date('Y/m/d H:i:s', strtotime($myDate))
 . '<h3 class="posttitle"><a href="' . $myLink . '">' . $myTitle . '</a></h3>' . "\n"
 . '<p class="postdate">' . $myDate . '</p>' . "\n"
 ); 
 //設定した読み込み件数分だけ取得できたらループを抜ける
 if (++$count_of_data == $num_of_data) { break; }
 }
 }
 } elseif ($rssdata->getName() == 'rss') {
 // rss2.0 の場合の処理
 // 記事ループ
 foreach ($rssdata->channel->item as $myEntry) {
 $myTitle = $myEntry->title; //タイトル取得
 if (preg_match($keyword, $myTitle)) {
 $myDate = $myEntry->pubDate; //日付取得
 $myLink = $myEntry->link; //リンクURL取得
 //出力内容にタイトル(リンク付)と日付を入れる
 array_push($outdata,
 date('Y/m/d H:i:s', strtotime($myDate))
 . '<h3 class="posttitle"><a href="' . $myLink . '">' . $myTitle . '</a></h3>' . "\n"
 . '<p class="postdate">' . $myDate . '</p>' . "\n"
 ); 
 //設定した読み込み件数分だけ取得できたらループを抜ける
 if (++$count_of_data == $num_of_data) { break; }
 }
 }
 } elseif ($rssdata->getName() == 'rdf') {
 // rss1.0 の場合の処理
 // 記事ループ
 foreach ($rssdata->item as $myEntry) {
 $myTitle = $myEntry->title; //タイトル取得
 if (preg_match($keyword, $myTitle)) {
 $myDate = $myEntry->pubDate; //日付取得
 $myLink = $myEntry->link; //リンクURL取得
 //出力内容にタイトル(リンク付)と日付を入れる
 array_push($outdata,
 date('Y/m/d H:i:s', strtotime($myDate))
 . '<h3 class="posttitle"><a href="' . $myLink . '">' . $myTitle . '</a></h3>' . "\n"
 . '<p class="postdate">' . $myDate . '</p>' . "\n"
 ); 
 //設定した読み込み件数分だけ取得できたらループを抜ける
 if (++$count_of_data == $num_of_data) { break; }
 }
 }
 }
}

// 降順並び替え
rsort($outdata);
//最大出力件数分だけ出力する
foreach(array_slice($outdata, 0, $num_of_data) as $output) {
 // 並び替えのための日時部分を消しつつ出力
 echo substr($output, 19);
}
echo "End\n";

うぃんどさんのコメント
4つのサイト全ての情報から新しいもの3件を出力するのが回答2です。 4つのサイトからそれぞれ3件ずつ出力するのが回答1です。 回答2を回答1のように、4つのサイトそれぞれ3件ずつに直したい場合は、 下記の部分を書き換えるだけで対応可能なので、下記のどちらも書いておいて、 いつでも変えることが出来るようにしてみても良いかも知れません。 >|php| // 降順並び替え rsort($outdata); //最大出力件数分だけ出力する foreach(array_slice($outdata, 0, $num_of_data) as $output) { // 並び替えのための日時部分を消しつつ出力 echo substr($output, 19); } ||< ↓ >|php| //最大出力件数分だけ出力する foreach($outdata as $output) { // 並び替えのための日時部分を消しつつ出力 echo substr($output, 19); } ||<

kohhiさんのコメント
早速お返事いただきありがとうございました。 echo substr($output, 19);} は19->2にして使います。

うぃんどさんのコメント
date関数のYをyに変えると、 date('y/m/d H:i:s', strtotime($myDate)) 最初から年は下2桁表記になりますのでsubstrが不要になります。 echo $output; date関数の詳細は下記参照。 http://php.net/manual/ja/function.date.php

3 ● Cherenkov
●100ポイント

質問者にとってより価値のある回答を提供したいと思っているので、敢えてSimplePieというライブラリを使った例を示します。
こういったライブラリを使えばatom,rss1.0,rss2.0などの違いを吸収してくれて、メソッド一発で必要な物を取得できるのでおすすめです。
フィードリーダーを1から作るのが目的ではないですよね?


使い方
SimplePie Documentation: Setup and Getting Started を参考にすすめる。

  1. SimplePie: Super-fast, easy-to-use, RSS and Atom feed parsing in PHP. download&解凍。
  2. libraryディレクトリとautoloader.phpをコピー。
  3. cacheディレクトリを作成。
  4. cacheディレクトリのパーミッションを777にする。

以下の様な構成になる。

<?php 
require_once './autoloader.php';

// 検索キーワードを設定
$keyword = '/関塚|なでしこ|柔道/u'; //uフラグでパターンがutf-8であることを知らせる
// 最大読み込み件数を設定 
$num_of_data = 5; //今回はキーワードにマッチしたエントリの内の最大表示件数として利用

$feedList = array(
'http://www.zakzak.co.jp/rss/sports/etc_sports.xml',
'http://number.bunshun.jp/list/rsscolumn',
'http://gendai.net/articles/feed.rss',
'http://sankei.jp.msn.com/rss/news/points.xml'
);

function pr($var) {
echo '<pre>'; print_r($var); echo '</pre>';
}

$feed = new SimplePie();
$feed->set_cache_location("./cache"); // キャッシュディレクトリ指定
$feed->set_cache_duration(600);
$feed->set_feed_url($feedList);
//$feed->set_item_limit(5); フィード全体のリミット
$success = $feed->init();
$feed->handle_content_type();


header('Content-Type:text/html; charset=UTF-8');

$result_items = array();

if ($success) {
//キーワードにマッチするエントリを集める。
foreach($feed->get_items() as $item) {
if (preg_match($keyword, $item->get_title())) {
$result_items[] = $item;
}
}
echo '<p>' . $keyword . ' の検索結果は ' . count($result_items) . ' 件です<br>(最大読み込み件数の設定によっていくつか見えないはず)</p>';

//エントリー表示部
foreach($result_items as $i => $item) {
if ($i < $num_of_data) {
//エントリのフィードタイトルは $item->get_feed()->get_title()
echo '<h3 class="posttitle"><a href="' . $item->get_permalink() . '">' . $item->get_title() . '</a>' . $item->get_feed()->get_title() . '</h3>';
//echo '<h3 class="posttitle"><a href="' . $item->get_permalink() . '">' . $item->get_title() . '</a></h3>';
echo '<p class="postdate">' . $item->get_date('Y/m/d H:i:s') . '</p>';
}
}
} else {
echo 'error';
}


参考


Cherenkovさんのコメント
4つのサイトを条件に入れてなかった…

Cherenkovさんのコメント
問題なく動作確認。

kohhiさんのコメント
早速お返事いただきありがとうございました。 SimplePieのライブラリー参考になります。 事情があり、短期間でカッコつけないとならないことになってます。 SimplePieの使い方は改めて勉強します。 SimplePieの質問出てきたら、よろしくお願いします。

Cherenkovさんのコメント
$rssdata->getName()で条件分岐するのは危険だと思うけどなぁ。 特定のフィードで動作確認が取れれば問題は少ないと思うけれども。

Cherenkovさんのコメント
http://q.hatena.ne.jp/1343721480 の質問にある「description要素」の有無についても [http://simplepie.org/wiki/reference/simplepie/get_description:title=get_description()] このメソッド使えばいいわけだし。

kohhiさんのコメント
コメントありがとうございます。 get_description() メソッド、勉強してみます。
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ