PHPでRSSを作る(その2)

(1/1)
PHPでRSSを作る」では、あらかじめ用意したテキストからRSSを生成するプログラムを作ったが、今回は、RSSを備えていないサイトで、新着情報一覧ページをスクレイピングしてRSSを生成するプログラムを作ってみることにする。1つのプログラムで複数サイトのRSSを生成できることを目指す。

(2026年1月10日)大幅改訂
(2025年12月28日)PHP8.5対応:curl_closeを使わない

目次

サンプル・プログラムの実行例

PHPでRSSを作る(その2)
makeRSS.php?id=3 のように、idでサイトを指定する。このサイトIDについては、後述する。

サンプル・プログラムのダウンロード

圧縮ファイルの内容
RSSmaker.phpサンプル・プログラム本体
pahooInputData.phpデータ入力に関わる関数群。
使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。
pahooRSS.phpRSS処理に関わるクラス pahooRSS。
RSS処理に関わるクラスの使い方は「PHPで作るRSSビューア」「[/e-soul/webtech/php02/php02-38-01.shtm:title=PHPでRSSを作る]」「[/e-soul/webtech/php02/php02-52-01.shtm:title=PHPでRSSを作る(その2)]」を参照。include_path が通ったディレクトリに配置すること。
pahooScraping.phpRSS処理に関わるクラス pahooScraping。
スクレイピング処理に関わるクラスの使い方は「PHPで作るRSSビューア」を参照。include_path が通ったディレクトリに配置すること。
RSSmaker.php 更新履歴
バージョン 更新日 内容
2.0.0 2026/01/10 大幅改訂
1.4.4 2025/06/06 yomiuri() -- コンテンツ構造変更対応
1.4.3 2025/03/16 rnnnews() -- 生の & を & に置換
1.4.2 2025/02/19 ynaCoKr() -- bug-fix
1.4.1 2024/12/28 ynaCoKr() -- 記事URLのパラメータを削除
pahooInputData.php 更新履歴
バージョン 更新日 内容
2.0.1 2025/08/11 getParam() bug-fix
2.0.0 2025/08/11 pahooLoadEnv() 追加
1.9.0 2025/07/26 getParam() 引数に$trim追加
1.8.1 2025/03/15 validRegexPattern() debug
1.8.0 2024/11/12 validRegexPattern() 追加
pahooRSS.php 更新履歴
バージョン 更新日 内容
1.3.1 2024/08/01 atom() -- 修正
1.3.0 2024/04/20 RSS 0.91対応
1.2.0 2024/04/20 名前空間 NS_dc を変数に変更;複数RSSに対応のため
1.1.0 2023/09/24 メーカー系のメソッド、プロパティを追加
1.0.0 2023/09/18 初版
pahooScraping.php 更新履歴
バージョン 更新日 内容
1.2.1 2024/10/31 __construct() 文字化け対策
1.2.0 2024/09/29 getValueFistrXPath() 属性値でない指定に対応
1.1.0 2023/10/15 getValueFistrXPath() 追加
1.0.1 2023/09/29 __construct() bug-fix
1.0.0 2023/09/18 初版

サンプル・プログラムの流れ

PHPでRSSを作る(その2)
サイト毎にスクレイピング関数を用意し、$id に応じて呼び出す。
RSS 1.0を作成するユーザー関数 makeRSS10、RSS 1.1を作成するユーザー関数 makeRSS1w は、「PHPでRSSを作る」をそのまま流用した。

準備:pahooInputData 関数群

PHPのバージョンや入力データのバリデーションなど、汎用的に使う関数群を収めたファイル "pahooInputData.php" が同梱されているが、include_path が通ったディレクトリに配置してほしい。他のプログラムでも "pahooInputData.php" を利用するが、常に最新のファイルを1つ配置すればよい。

また、各種クラウドサービスに登録したときに取得するアカウント情報、アプリケーションパスワードなどを登録した .pahooEnv ファイルから読み込む関数 pahooLoadEnv を備えている。こちらについては、「各種クラウド連携サービス(WebAPI)の登録方法」をご覧いただきたい。

準備:pahooRSS クラス

pahooRSS.php

  15: class pahooRSS {
  16:     private $rssURL;            //RSS URL
  17:     private $items;             //チャネル情報、フィード情報
  18:     private $language;          //使用言語(初期値は日本語)
  19:     private $error;             //エラー・メッセージ
  20:     private $parseTable;        //定義済みパーサ一覧
  21:     private $templateRSS10;     //RSS1.0テンプレート
  22:     private $templateRSS11;     //RSS1.0テンプレート
  23:     private $templateRSS20;     //RSS1.0テンプレート
  24:     private $templateAtom;      //Atomテンプレート
  25:     private $nameSpaces;        //名前空間
  26:     private $userParseTable;    //ユーザー定義パーサ一覧
  27:     private $errorTable;        //エラー番号 => エラー・メッセージ 一覧
  28: /**
  29:  * プロパティ $items の構造
  30:  * 
  31:  * 添字[0] チャネルの情報
  32:  *   [0]['title']       タイトル
  33:  *   [0]['link']        URL
  34:  *   [0]['rss']         RSSのURL
  35:  *   [0]['creator']     製作者
  36:  *   [0]['copyright']   著作権者
  37:  *   [0]['description'] 説明
  38:  *
  39:  * 添字[1以上] フィードの情報
  40:  *   [#]['title']       タイトル
  41:  *   [#]['link']        URL
  42:  *   [#]['description'] 説明
  43:  *   [#]['date']        更新日時(ISO 8601形式)
  44: */
  45: 

RSS の読み込みや作成を行うためのクラスが pahooRSS である。同梱のクラス・ファイル "pahooRSS.php" は include_path が通ったディレクトリに配置してほしい。他のプログラムでも pahooRSSクラス を利用するが、常に最新のクラス・ファイルを1つ配置すればよい。
RSS を PHP の連想配列として扱えるようにする。連想配列の構造は、上記コメントを参考にしていただきたい。
RSS 1.0, RSS 1.1, RSS 2.0, Atom の読み込み/作成に対応している。

PHPのクラスについては「PHPでクラスを使ってテキストの読みやすさを調べる」を参照されたい。

準備:pahooScraping クラス

pahooScraping.php

  13: class pahooScraping {
  14:     private $dom;           //DOMDocument
  15:     private $xpath;         //DOMXPath
  16:     private $language;      //使用言語(初期値は日本語)
  17:     private $error;         //エラー・メッセージ
  18:     private $errorTable;    //エラー番号 => エラー・メッセージ 一覧
  19: 
  20: /**
  21:  * コンストラクタ
  22:  * @param   string $contents 解析対象テキスト(UTF-8)
  23:  * @return  object /NULL:PHP8未満のため実行できない.
  24: */
  25: function __construct($contents) {
  26:     //PHPのバージョンをチェックする.
  27:     if (! $this->isphp8over()) {
  28:         $this->error = 111;
  29:         throw new Exception($this->getErrorMessage());
  30:         return NULL;
  31:     }
  32:     //プロパティの初期値を設定する.
  33:     try {
  34:         // Unicodeの範囲を指定
  35:         $map = [ 0x80, 0xFFFF, 0, 0xFFFF ];
  36:         // DOMの文字化け対策:UTF-8文字を数値エンティティに変換
  37:         $contents = mb_encode_numericentity($contents, $map, 'UTF-8');
  38:         // DOMDocument クラス
  39:         $this->dom = new DOMDocument();
  40:         libxml_use_internal_errors(TRUE);
  41:         @$this->dom->loadHTML($contents);
  42:         libxml_clear_errors();
  43:         $this->xpath = new DOMXPath($this->dom);
  44:     } catch (Exception $e) {
  45:         $this->error = 121;
  46:         throw new Exception($e->getMessage());
  47:         return FALSE;
  48:     }
  49: 
  50:     //エラー番号 => エラー・メッセージ 一覧
  51:     $this->errorTable = array(
  52:         111 => array('PHP8以上が必要です', 'PHP8 or higher is required'),
  53:         121 => array('DOMエラーです', 'DOM error'),
  54:         999 => array('不明のエラー', 'unknown error'),
  55:     );
  56: }

Webサイトのスクレイピング処理を行うためのクラスが pahooScraping である。同梱のクラス・ファイル "pahooScraping.php" は include_path が通ったディレクトリに配置してほしい。他のプログラムでも pahooScrapingクラス を利用するが、常に最新のクラス・ファイルを1つ配置すればよい。

PHPのクラスについては「PHPでクラスを使ってテキストの読みやすさを調べる」を参照されたい。

解説:RSS作成サイト

RSSを作成するサイト(スクレイピング対象サイト)は、あらかじめグローバル変数 $ListSites に代入しておく。この配列変数の構造は下表の通り。
$ListSites の構造
サイトID
(1次元目)
添字
(2次元目)

(2次元目)
1 titleサイト名
urlスクレイピングURL
funcスクレイピング関数名
2 titleサイト名
urlスクレイピングURL
funcスクレイピング関数名

RSSmaker.php

  71: // RSS作成サイト
  72: $ListSites = array(
  73: 1 => array(
  74: 'title'     => 'アニメ!アニメ!',
  75: 'url'       => 'https://animeanime.jp/rss/index.rdf',
  76: 'func'      => 'animeanime'
  77: ),
  78: array(
  79: 'title'     => '日本気象協会',
  80: 'url'       => 'https://tenki.jp/forecaster/',
  81: 'func'      => 'tenkiJp'
  82: ),
  83: array(
  84: 'title'     => '聯合ニュース',
  85: 'url'       => 'https://jp.yna.co.kr/RSS/news.xml',
  86: 'func'      => 'ynaCoKr'
  87: ),
  88: array(
  89: 'title'     => 'RNN時事英語辞典',
  90: 'url'       => 'https://rnnnews.jp/rss/rss.xml',
  91: 'func'      => 'rnnnews'
  92: ),
  93: array(
  94: 'title'     => '朝日新聞デジタル',
  95: 'url'       => 'https://www.asahi.com/rss/asahi/newsheadlines.rdf',
  96: 'func'      => 'asahi'
  97: ),
  98: array(
  99: 'title'     => '讀賣新聞(経済)',
 100: 'url'       => 'https://www.yomiuri.co.jp/economy/',
 101: 'func'      => 'yomiuri'
 102: ),
 103: array(
 104: 'title'     => '讀賣新聞(政治)',
 105: 'url'       => 'https://www.yomiuri.co.jp/politics/',
 106: 'func'      => 'yomiuri'
 107: ),
 108: array(
 109: 'title'     => '讀賣新聞(社会)',
 110: 'url'       => 'https://www.yomiuri.co.jp/national/',
 111: 'func'      => 'yomiuri'
 112: )
 113: );

解説:「アニメ!アニメ!」をスクレイピングする

RSSmaker.php

 209: /**
 210:  * アニメ!アニメ!をスクレイピングする
 211:  * @param   array $id    RSS作成サイト番号
 212:  * @param   array $param スクレイピング用パラメータ
 213:  * @return  string RSS文字列/FALSE:スクレイピング失敗
 214: */
 215: function animeanime($id, $param) {
 216:     // ページ読み込み
 217:     $str = @file_get_contents($param['url']);
 218:     // エラー処理
 219:     if (($str == NULL|| ($str == FALSE)) {
 220:         // インスタンス生成
 221:         $prs  = new pahooRSS();
 222:         $errmsg = 'アニメ!アニメ!:情報が取得できない.';
 223:         errorRSS($errmsg, $items);
 224:         $outstr = $prs->maker($items, 'RSS1.0');
 225:         // インスタンス解放
 226:         $prs =  NULL;
 227:         return $outstr;
 228:     }
 229: 
 230:     static $pat11 = '/^<\?xml[^>]+>/iums';
 231:     $outstr = trim(preg_replace($pat11, '', $str));
 232: 
 233:     return $outstr;
 234: }

ユーザー関数 animeanime は、アニメ!アニメ!RDF の冒頭1行(XML宣言)を取り除き、RSS 1.0 に加工する。

解説:「日本気象協会」をスクレイピングする

RSSmaker.php

 236: /**
 237:  * 日本気象協会をスクレイピングする
 238:  * @param   array $id    RSS作成サイト番号
 239:  * @param   array $param スクレイピング用パラメータ
 240:  * @return  string RSS文字列
 241: */
 242: function tenkiJp($id, $param) {
 243:     // ページ読み込み
 244:     $curl = curl_init() ;
 245:     curl_setopt($curl, CURLOPT_URL, $param['url']);
 246:     curl_setopt($curl, CURLOPT_HEADER, 1) ; 
 247:     curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET');
 248:     curl_setopt($curl, CURLOPT_SSL_VERIFYPEER , FALSE);     // 証明書は無視
 249:     curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);       // 結果を文字列で
 250:     curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0');
 251:     curl_setopt($curl, CURLOPT_TIMEOUT, 5);
 252:     $res1 = curl_exec($curl);
 253:     $res2 = curl_getinfo($curl);
 254:     // PHP8.5:非推奨関数
 255:     if (PHP_VERSION_ID < 80500) {
 256:         curl_close($curl);
 257:     }
 258:     $html = substr($res1, $res2['header_size']);
 259: 
 260:     // インスタンス生成
 261:     $scrp = new pahooScraping($html);
 262:     $prs  = new pahooRSS();
 263: 
 264:     // エラー処理
 265:     if ($scrp->iserror()) {
 266:         $errmsg = '日本気象協会:情報が取得できない.';
 267:         errorRSS($errmsg, $items);
 268:         $outstr = $prs->maker($items, 'RSS1.0');
 269:         return $outstr;
 270:     }
 271: 
 272:     // サイト諸元
 273:     $items[0]['title'] = $param['title'];
 274:     $items[0]['link']  = getDomainURL($param['url']);
 275:     $items[0]['rss']   = $_SERVER['SCRIPT_NAME'. '?id=' . $id;
 276:     $items[0]['creator'] = CREATOR;
 277:     $items[0]['copyright'] = '日本気象協会';
 278:     $items[0]['description'] = $scrp->getDescription();
 279: 
 280:     // コンテンツ情報
 281:     $nodes = $scrp->queryXPath('//a[starts-with(@href, "/forecaster/")]');
 282:     $cnt = 1;
 283:     for ($i = 0$i < $nodes->length$i++) {
 284:         $url = $nodes->item($i)->getAttribute('href');
 285:         if (preg_match('/\/[0-9]+\.html$/', $url> 0) {
 286:             $items[$cnt]['link'] = $items[0]['link'. preg_replace('/^\// i', '', $url);
 287:             $cnt++;
 288:         }
 289:     }
 290:     $nodes = $scrp->queryXPath('//div[contains(concat(" ", normalize-space(@class), " "), " text-box ")]/p[@class="title"]');
 291:     $cnt = 1;
 292:     for ($i = 0$i < $nodes->length$i++) {
 293:         $title = $nodes->item($i)->nodeValue;
 294:         $items[$cnt]['title'] = $title;
 295:         $items[$cnt]['description'] = '';
 296:         $cnt++;
 297:     }
 298:     $nodes = $scrp->queryXPath('//span[@class="date-time"]');
 299:     $cnt = 1;
 300:     for ($i = 0$i < $nodes->length$i++) {
 301:         $dt = $nodes->item($i)->nodeValue;
 302:         $items[$cnt]['date'] = str2iso8601_02($dt);
 303:         $cnt++;
 304:     }
 305: 
 306:     // 不要な情報を削除
 307:     foreach ($items as $key=>$item) {
 308:         if (! isset($item['title']) || ! isset($item['link'])) {
 309:             unset($items[$key]);
 310:         }
 311:     }
 312: 
 313:     // RSS1.0作成
 314:     $outstr = $prs->maker($items, 'RSS1.0');
 315: 
 316:     // インスタンス解放
 317:     $scrp = NULL;
 318:     $prs =  NULL;
 319: 
 320:     return $outstr;
 321: }

ユーザー関数 tenkiJp は、日本気象協会最新の記事をスクレイピングし、RSS 1.0 を生成する。

HTMLに対して XPath式の評価を行うことでスクレイピングを行っている。
日本気象協会の場合、タイトル、リンク、日付が各々別のブロックにあるので、各々別の XPath式で評価することで、配列 $items に格納する。記事概要はないので、空文字を代入する。URLから生地本体ページにジャンプし概要を取り込むこともできるが、応答が遅くなるので、ここでは見送った。

解説:「聯合ニュース」をスクレイピングする

RSSmaker.php

 323: /**
 324:  * 聯合ニュースをスクレイピングする
 325:  * @param   array $id    RSS作成サイト番号
 326:  * @param   array $param スクレイピング用パラメータ
 327:  * @return  string RSS文字列/FALSE:スクレイピング失敗
 328: */
 329: function ynaCoKr($id, $param) {
 330:     $items = array();
 331: 
 332:     // ページ読み込み
 333:     $curl = curl_init() ;
 334:     curl_setopt($curl, CURLOPT_URL, $param['url']);
 335:     curl_setopt($curl, CURLOPT_HEADER, 1) ; 
 336:     curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET');
 337:     curl_setopt($curl, CURLOPT_SSL_VERIFYPEER , FALSE);     // 証明書は無視
 338:     curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);       // 結果を文字列で
 339:     curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0');
 340:     curl_setopt($curl, CURLOPT_TIMEOUT, 5);
 341:     $res1 = curl_exec($curl);
 342:     $res2 = curl_getinfo($curl);
 343:     // PHP8.5:非推奨関数
 344:     if (PHP_VERSION_ID < 80500) {
 345:         curl_close($curl);
 346:     }
 347:     $str = substr($res1, $res2['header_size']);
 348: 
 349:     // エラー処理
 350:     if (($str == NULL|| ($str == FALSE)) {
 351:         // インスタンス生成
 352:         $prs = new pahooRSS();
 353:         $errmsg = '聯合ニュース:情報が取得できない.';
 354:         errorRSS($errmsg, $items);
 355:         $outstr = $prs->maker($items, 'RSS1.0');
 356:         // インスタンス解放
 357:         $prs =  NULL;
 358:         return $outstr;
 359:     }
 360: 
 361:     static $pat11 = '/^<\?xml[^>]+>/iums';
 362:     $outstr = trim(preg_replace($pat11, '', $str));
 363: 
 364:     return $outstr;
 365: }

ユーザー関数 ynaCoKr は、聯合ニュースRDF の冒頭1行(XML宣言)を取り除き、RSS 1.0 に加工する。
HTTP通信で UserAgent のないものを排除するようなので、cURL 関数を使ってブラウザからのアクセスのように見せかけている。

解説:「RNN時事英語辞典」をスクレイピングする

RSSmaker.php

 367: /**
 368:  * RNN時事英語辞典:RSS 2.0→1.0
 369:  * @param   array $id    RSS作成サイト番号
 370:  * @param   array $param スクレイピング用パラメータ
 371:  * @return  string RSS文字列
 372: */
 373: function rnnnews($id, $param) {
 374:     $items = array();
 375: 
 376:     // インスタンス生成
 377:     $prs = new pahooRSS();
 378: 
 379:     // RSS 2.0パース
 380:     $items = $prs->parse($param['url']);
 381:     if ($items === FALSE) {
 382:         $errmsg = 'RNN時事英語辞典:情報が取得できない.';
 383:         errorRSS($errmsg, $items);
 384:         $outstr = $prs->maker($items, 'RSS1.0');
 385:         return $outstr;
 386:     }
 387: 
 388:     // サイト諸元
 389:     $items[0]['rss'] = $_SERVER['SCRIPT_NAME'. '?id=' . $id;
 390:     $items[0]['creator'] = CREATOR;
 391:     $items[0]['copyright'] = 'RNN時事英語辞典';
 392: 
 393:     // RSS1.0作成
 394:     $outstr = $prs->maker($items, 'RSS1.0');
 395: 
 396:     // インスタンス解放
 397:     $prs =  NULL;
 398: 
 399:     return $outstr;
 400: }

ユーザー関数 rnnnews は、RNN時事英語辞典RSS 2.0RSS 1.0 に変換する。

解説:「朝日新聞デジタル」をスクレイピングする

RSSmaker.php

 402: /**
 403:  * 朝日新聞デジタル:?→RSS 1.0
 404:  * @param   array $id    RSS作成サイト番号
 405:  * @param   array $param スクレイピング用パラメータ
 406:  * @return  string RSS文字列
 407: */
 408: function asahi($id, $param) {
 409:     define('NS_dc', 'http://purl.org/dc/elements/1.1/');    //名前空間
 410:     $items = array();   // アイテムを格納する配列
 411: 
 412:     // コンテンツ読み込み
 413:     $ss  = @file_get_contents($param['url']);
 414:     $xml = simplexml_load_string($ss);
 415: 
 416:     // インスタンス生成
 417:     $scrp = new pahooScraping($xml);
 418:     $prs  = new pahooRSS();
 419: 
 420:     // エラー処理
 421:     if ($xml == FALSE) {
 422:         $errmsg = '朝日新聞デジタル:情報が取得できない.';
 423:         errorRSS($errmsg, $items);
 424:         $outstr = $prs->maker($items, 'RSS1.0');
 425:         return $outstr;
 426:     }
 427: 
 428:     // サイト諸元
 429:     $items[0]['title'] = $xml->channle->title;
 430:     $items[0]['link'] = getDomainURL($param['url']);
 431:     $items[0]['rss'] = $_SERVER['SCRIPT_NAME'. '?id=' . $id;
 432:     $items[0]['creator'] = CREATOR;
 433:     $items[0]['copyright'] = '朝日新聞デジタル';
 434:     $items[0]['description'] = $xml->channle->description;
 435: 
 436:     // コンテンツ情報
 437:     $cnt = 1;
 438:     for ($i = 0$i < count($xml->item); $i++) {
 439:         $items[$i + 1]['title'] = $xml->item[$i]->title;
 440:         $items[$i + 1]['link']  = $xml->item[$i]->link;
 441:         $items[$i + 1]['description'] = '';
 442:         $node = $xml->item[$i]->children(NS_dc);
 443:         $dt = strtotime((string)$node->date);
 444:         $items[$i + 1]['date'] = date('c', $dt);
 445:         $cnt++;
 446:     }
 447: 
 448:     // RSS1.0作成
 449:     $outstr = $prs->maker($items, 'RSS1.0');
 450: 
 451:     // インスタンス解放
 452:     $scrp = NULL;
 453:     $prs =  NULL;
 454: 
 455:     return $outstr;
 456: }

ユーザー関数 asahi は、朝日新聞デジタルRDFを加工し、RSS 1.0 を生成する。

解説:「讀賣新聞」をスクレイピングする

RSSmaker.php

 458: /**
 459:  * 讀賣新聞をスクレイピングする(共通)
 460:  * @param   array $id    RSS作成サイト番号
 461:  * @param   array $param スクレイピング用パラメータ
 462:  * @return  string RSS文字列
 463: */
 464: function yomiuri($id, $param) {
 465:     $items = array();   // アイテムを格納する配列
 466: 
 467:     // インスタンス生成
 468:     $prs  = new pahooRSS();
 469: 
 470:     // コンテンツ読み込み
 471:     $html = @file_get_contents($param['url']);
 472: 
 473:     // エラー処理
 474:     if ($html === FALSE) {
 475:         $errmsg = '讀賣新聞:情報が取得できない.';
 476:         errorRSS($errmsg, $items);
 477:         $outstr = $prs->maker($items, 'RSS1.0');
 478:         return $outstr;
 479:     }
 480: 
 481:     // インスタンス生成
 482:     $scrp = new pahooScraping($html);
 483: 
 484:     // サイト諸元
 485:     $items[0]['title'] = $param['title'];
 486:     $items[0]['link']  = getDomainURL($param['url']);
 487:     $items[0]['rss']   = $_SERVER['SCRIPT_NAME'. '?id=' . $id;
 488:     $items[0]['creator'] = CREATOR;
 489:     $items[0]['copyright'] = '讀賣新聞';
 490:     $items[0]['description'] = $scrp->getDescription();
 491: 
 492:     // コンテンツ情報
 493:     $nodes = $scrp->queryXPath('// div[@class="item"]/h3[@class="title"]/a');
 494:     $cnt = 1;
 495:     for ($i = 0$i < $nodes->length$i++) {
 496:         $node = $nodes->item($i);
 497:         $uri  =  $items[0]['link'. preg_replace('/^\// i', '', $node->getAttribute('href'));
 498:         if (strpos($uri, $param['url']) !== FALSE) {
 499:             $items[$cnt]['title'] = trim($node->nodeValue);
 500:             $items[$cnt]['link']  = $uri;
 501:             $items[$cnt]['description'] = trim($node->nodeValue);
 502:             $cnt++;
 503:         }
 504:     }
 505:     $nodes = $scrp->queryXPath('// div[@class="info"]/time');
 506:     $cnt = 1;
 507:     for ($i = 0$i < $nodes->length$i++) {
 508:         $node = $nodes->item($i);
 509:         if (isset($items[$cnt]['title'])) {
 510:             $dt = strtotime((string)$node->getAttribute('datetime'));
 511:             $items[$cnt]['date'] = date('c', $dt);
 512:             $cnt++;
 513:         }
 514:     }
 515: 
 516:     // RSS1.0作成
 517:     $outstr = $prs->maker($items, 'RSS1.0');
 518: 
 519:     // インスタンス解放
 520:     $scrp = NULL;
 521:     $prs =  NULL;
 522: 
 523:     return $outstr;
 524: }

ユーザー関数 yomiuri は、讀賣新聞の各カテゴリのトップページをスクレイピングし、RSS 1.0 を生成する。カテゴリは、配列 $ListSites に格納してある URL によって識別する。

HTMLに対して XPath式の評価を行うことでスクレイピングを行っている。
讀賣新聞の場合、タイトル、リンク、記事概要が同じブロックに固まっており、日付が別のブロックにあるので、各々別の XPath式で評価することで、配列 $items に格納する。

参考サイト

(この項おわり)
header