質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
RSS

RSS(Really Simple Syndication)はブログのエントリやニュースの見出し、標準のフォーマットの音声やビデオなどを発行するために使われるウェブフィードのフォーマットの集合体です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

1回答

3648閲覧

【PHP】【RSS取得】複数のRSSから「指定回数」だけ均等に情報を取得する方法【ばらばらでは取得成功済】

shimane

総合スコア98

RSS

RSS(Really Simple Syndication)はブログのエントリやニュースの見出し、標準のフォーマットの音声やビデオなどを発行するために使われるウェブフィードのフォーマットの集合体です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2017/07/28 03:29

現在PHPを勉強中の初心者です。

今回、複数の外部RSSから情報を取得してmysqlへ登録を行うという事をしていて
いくら調べても上手くいかなかった為、質問をさせてください。

「実現したい事」

複数の外部RSSから指定した回数分だけ
サイト名・記事タイトル・記事URL・日時を取得して
mysqlを使ってデータベースに登録を行いたい。

色々調べたり、実際に使ってみた所
「rss-php」では取得エラーが発生することもあり「SimplePie 1.5」を使用する事に決定

参考URL
http://absg.hatenablog.com/entry/2015/10/10/173215

こちらの参考URLのコードを元に一連の流れのコードを書いて見ました。

php

1<?php 2 3try { 4 $db = new \PDO(DSN, DB_USERNAME, DB_PASSWORD); 5 $db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); 6 echo "データベースへの接続が出来ました"; 7 8}catch (\PDOException $e) { 9 echo $e->getMessage(); 10 exit; 11} 12 13date_default_timezone_set("Asia/Tokyo"); 14require_once('./autoloader.php'); 15 16$url1[] = [ 17'http://i2chmeijin.blog.fc2.com/', 18'http://www.akb48matomemory.com/index.rdf', 19'http://blog.livedoor.jp/aquarium_matome/index.rdf',]; 20 21$feed = new SimplePie(); 22$feed->set_feed_url($url1[0]); 23$feed->enable_cache(false); //キャッシュ機能はオフで使う 24$success = $feed->init(); 25$feed->handle_content_type(); 26 27if ($success){ 28 29 $i = 0; 30 foreach ($feed->get_items() as $item) { 31 32 //12回分だけforeachを回します。 33 if ($i >= 12 ) { 34 break; 35 }else { 36 $i++; 37 } 38 39 echo $item->get_feed()->get_title()."\n"; //サイトタイトル 40 echo $item->get_title()."\n"; //記事タイトル 41 echo $item->get_link()."\n"; //記事URL 42 echo $item->get_date('Y-m-d h:i:s')."\n"; //記事投稿時刻 43 echo "<br>"; 44 45 $name = $item->get_feed()->get_title(); 46 $title = $item->get_title(); 47 $url = $item->get_link(); 48 $date = $item->get_date('Y-m-d h:i:s'); 49 50 $sql = "insert IGNORE into matome (name, title, url, created) values (:name,:title,:url,:created)"; 51 $stmt = $db->prepare($sql); 52 $stmt->execute([ 53 ':name' => $name, 54 ':title' => $title, 55 ':url' => $url, 56 ':created' => $date 57 ]); 58 59 } 60}else{ 61 echo $feed->error(); 62} 63?>

実行結果:

アクアリウム速報【ミナミヌマエビ】食べられないことを願っててくれ http://blog.livedoor.jp/aquarium_matome/archives/1066872643.html 2017-07-28 12:00:25 2ch名人 第67期王将戦二次予選の組み合わせ決定 http://i2chmeijin.blog.fc2.com/blog-entry-6487.html 2017-07-28 12:00:00 NEWSまとめもりー|2chまとめブログ 【緊急】日本人の洗脳、ついに解けるwwwwww(※画像あり) http://www.akb48matomemory.com/archives/1066861959.html 2017-07-28 11:22:07 NEWSまとめもりー|2chまとめブログ 【衝撃】オードリー春日俊彰、東大合格へwwwwwwwww http://www.akb48matomemory.com/archives/1066866442.html 2017-07-28 10:22:02 2ch名人 【王座戦】居飛車対四間飛車の相穴熊戦に http://i2chmeijin.blog.fc2.com/blog-entry-6486.html 2017-07-28 10:00:00 NEWSまとめもりー|2chまとめブログ 【愕然】好きだった女と食事に行った結果wwwwwwwww http://www.akb48matomemory.com/archives/1066866462.html 2017-07-28 09:22:12 2ch名人 将棋連盟、千駄ヶ谷エレジーのCD販売断る http://i2chmeijin.blog.fc2.com/blog-entry-6485.html 2017-07-28 08:30:00 NEWSまとめもりー|2chまとめブログ 【北海道行方不明】美人中国女性「日本人はすごく親切」→ とんでもないことになる・・・ http://www.akb48matomemory.com/archives/1066866455.html 2017-07-28 08:22:03 NEWSまとめもりー|2chまとめブログ 【速報】巨大地震の前兆!!?大変なことが起きてる・・・ http://www.akb48matomemory.com/archives/1066866451.html 2017-07-28 07:22:14 NEWSまとめもりー|2chまとめブログ 新海誠監督『君の名は』パクリがバレて大炎上中wwwww(検証動画あり) http://www.akb48matomemory.com/archives/1066867470.html 2017-07-28 06:22:08 NEWSまとめもりー|2chまとめブログ 今井絵理子、週刊新潮の略奪不倫に意味深コメントwwwwwwww http://www.akb48matomemory.com/archives/1066867446.html 2017-07-28 05:22:42 NEWSまとめもりー|2chまとめブログ 琵琶湖線・瀬田駅の架線事故が怖すぎる…(動画あり) http://www.akb48matomemory.com/archives/1066861961.html 2017-07-28 04:22:29

このように「取得するサイトの順番」がぐちゃぐちゃにRSSフィードを取得しています。

「理想」
5回分だけ取得するという設定にした場合

サイトAから5件(5件未満しか情報が無かったら次のサイトBへ移動)
サイトBから5件(5件未満しか情報が無かったら次のサイトCへ移動)
サイトCから5件

という風に複数のRSSから指定した回数の分だけ取得する方法を調べたり、
色々試しているのですが上手くいきません。

mysqlへの登録も
重複するデータは登録しないという風な設定も出来て、
残りはこの「指定回数分だけ取得する」が分からないという状況です。

解決する為の方法をご存知の方がいらっしゃいましたら、
お力をお貸しいただけると嬉しいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

s-washion

2017/08/04 01:51

上記のソースに「$feed->set_feed_url($url1[0]);」とありますが、これだと常にi2chmeijin.blog.fc2.comからしか取得しないような気がしますが、間違いないですか?
shimane

2017/08/04 04:40

質問ありがとうございます。 はい、最初は「$feed->set_feed_url($url1);」で試してみたのですが、これだとエラーが表示され、何も取得できませんでした。それで「$feed->set_feed_url($url1[0]);」とすると、ランダムではありますが複数のURLから取得するようになりました。 なんとか、ランダムではなく綺麗に均等に取得する方法を今も探しているのですが上手くいっていないです。
s-washion

2017/08/04 05:07

わかりました。上記ソースだと、2次元配列になっているんですね。なので、$url1[0]としないとエラーになりますね。修正ソースを考えてみますので回答欄に記載いたします。
guest

回答1

0

ベストアンサー

こんにちは

SimplePieを見ると、複数のフィードを指定した場合、記事がマージされて出力されるようです。
(おそらく時系列順で取得していると思います)
なので、質問者さんの意図することを行う為には、フィード毎のSimplePieオブジェクトを生成し、
それぞれget_itemsを行う方法がいいかなと思います。

(SimplePieを詳しく見たわけではないので、他に良い方法があるかもしれません)

ソースを書いてみましたのでご参考にしてみてください。

php

1<?php 2 3try { 4 $db = new \PDO(DSN, DB_USERNAME, DB_PASSWORD); 5 $db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); 6 echo "データベースへの接続が出来ました"; 7 8}catch (\PDOException $e) { 9 echo $e->getMessage(); 10 exit; 11} 12 13date_default_timezone_set("Asia/Tokyo"); 14require_once('./autoloader.php'); 15 16// 1次元配列に 17$url1 = [ 18 'http://i2chmeijin.blog.fc2.com/', 19 'http://www.akb48matomemory.com/index.rdf', 20 'http://blog.livedoor.jp/aquarium_matome/index.rdf', 21]; 22 23// feed毎のSimplePieオブジェクトを作成 24$feeds = []; 25foreach ($url1 as $url) { 26 $feed = new SimplePie(); 27 $feed->set_feed_url($url); 28 $feed->enable_cache(false); //キャッシュ機能はオフで使う 29 $success = $feed->init(); 30 if ( $success === false ){ 31 // いずれかのfeedでエラーになったら即終了(ここはお好みで修正してください) 32 $error_msg = $feed->error(); 33 break; 34 } 35 $feed->handle_content_type(); 36 $feeds[] = $feed; 37} 38 39if ($success){ 40 $get_count = 12; // 取得する回数 41 $sql = "insert IGNORE into matome (name, title, url, created) values (:name,:title,:url,:created)"; // foreach内で代入するのは無駄なのでここで定義 42 43 // 各feed毎にget_itemsを繰り返す 44 foreach ($feeds as $feed) { 45 // get_itemsの引数を指定して何個取得するか指定 46 foreach ($feed->get_items(0, $get_count) as $item) { 47 48 echo $item->get_feed()->get_title()."\n"; //サイトタイトル 49 echo $item->get_title()."\n"; //記事タイトル 50 echo $item->get_link()."\n"; //記事URL 51 echo $item->get_date('Y-m-d h:i:s')."\n"; //記事投稿時刻 52 echo "<br>"; 53 54 $name = $item->get_feed()->get_title(); 55 $title = $item->get_title(); 56 $url = $item->get_link(); 57 $date = $item->get_date('Y-m-d h:i:s'); 58 59 $stmt = $db->prepare($sql); 60 $stmt->execute([ 61 ':name' => $name, 62 ':title' => $title, 63 ':url' => $url, 64 ':created' => $date 65 ]); 66 } 67 } 68} else { 69 echo error_msg; 70} 71

投稿2017/08/04 05:35

s-washion

総合スコア204

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shimane

2017/08/04 10:44

素晴らしいです!本当に素晴らしい。 まさにこれです、この動作を理想として何度も何度も試行錯誤を繰り返してきました。 自分の力ではとても辿りつけない領域でしたので 本当に助かりました! 今は教えて頂いたコードを何度も読んで 何故このような動作になるんだろう?というのも勉強していきたいと思います。 特にMYSQLのINSERT文がforeachの外に出ているのに 正常にデータベースへの保存が出来ているのが不思議です。 (foreachを回す事で各種データを取得すると思うのですが、 何故その前にmysqlを書いて保存できているのか不思議です。 プログラムコードは上から下へと処理が行われていくという風に書籍で習った記憶があり、疑問です。) もっともっと勉強しようと思います。 本当に有難うございます。 大感謝です!
s-washion

2017/08/07 01:23 編集

解決されたようでよかったです。 > 特にMYSQLのINSERT文がforeachの外に出ているのに正常にデータベースへの保存が出来ているのが不思議です。 ↑ですが、$sqlはただ文字列を代入しているだけで、SQLを実行しているのは、$stmt->execute()というメソッドです。 では、$stmtってなんだということになりますが、これは、$db->prepareメソッドで作成してますね。 ざっくり言うと、$db->prepareメソッドの引数のSQL文を操作するオブジェクトです。(実際に実行したり、「:」がついている個所を置き換えたり等々) そして、$stmt->executeメソッドに引数に連想配列を与えていますが、 これは、$sqlのINSERT文の「:」がついている箇所をそれぞれ変数の値に書き換えて実行します。 (例、「:name」を「$name」の値に置き換えてますので、foreach文で回すと違う値がINSERTされます。) こういう仕組みをプリペアドステートメントっていいます。 データベースを利用する際によく使う方法ですので、公式ドキュメントなど一読されることをオススメします 公式Doc http://php.net/manual/ja/pdo.prepared-statements.php
shimane

2017/08/08 18:40

さらに教えてくださいまして有難うございます、とっても勉強になります! 教えてくださった事を忘れないように学習メモに記録して もっともっと勉強をしていきます、本当に有難うございます!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問