QiitaのRSSフィード活用されていますか?
個人サイトや、推しメンの記事を確認するのに結構便利です。
↓↓ Feedの存在知らない方はこちら ↓↓
今回は個人用に提供されているRSSフィードをPHPで解析してみました。
公式からRSSが提供されているのに、わざわざ解析してJSON化する意味がわからない...。って思う方もいると思います。
用途は人それぞれですが、「毎朝Slack通知したい」「記録として残したい」「独自のAPIを用意して、複数のアプリで使いまわしたい」とか、まぁ役立ちそうですよね。
「HTTP通信」をして「XMLの解析」をして「JSON化」する。
わりと、初学者の学習にぴったりな題材な気がします。
使用ライブラリ
Guzzle Http Client
HTTP通信のためにGuzzleライブラリを利用します。
実装例
さっそくですが実装例を紹介。
(※ 記事用に細かい例外処理など省いています。甘い部分あるかと思いますが、ご了承ください。)
/**
* データのFetch.
*
* @param string $id
* Qiitaのアカウント名.
* @param bool $format_json
* Jsonで返すか. 配列で返すか.
*
* @return string|array|false
* 例外はFALSE.
*/
public function fetch(string $id, $format_json = TRUE): string|array|false {
$url = 'https://qiita.com/' . $id . '/feed';
try {
$http_request = $this->httpClient->get($url);
$feed = $http_request->getBody()->getContents();
if (!$feed) {
throw new \Exception();
}
$data = $this->loadRawFeedData($feed);
if (!$data) {
throw new \Exception();
}
$data = $this->parseXml($data, $url);
}
catch (\Exception $e) {
return FALSE;
}
return $format_json ? json_encode($data) : $data;
}
/**
* Fetchした生データを \SimpleXMLElement に変換.
*
* @param string $feed
* 生データ.
*
* @return \SimpleXMLElement|false
* オブジェクトを返す. 失敗したら FALSE を返す.
*/
private function loadRawFeedData(string $feed): \SimpleXMLElement|false {
$data = simplexml_load_string($feed);
if (assert($data instanceof \SimpleXMLElement)) {
return $data;
}
return FALSE;
}
/**
* XMLデータの解析.
*
* @param \SimpleXMLElement $xml
* XMLデータ.
* @param string $url
* RSS取得URL.
*
* @return array
* 解析データを配列で返す.
*/
private function parseXml(\SimpleXMLElement $xml, string $url): array {
$articles = [];
foreach ($xml->entry as $o) {
$title = (string) $o->title;
$link = (string) $o->url;
$published = (string) $o->published;
if (!isset($title) || !isset($link) || !isset($published)) {
continue;
}
$published = new \Datetime($published);
$articles[] = [
'title' => $title,
'link' => $link,
'published' => $published->format('c'),
];
}
return [
'title' => (string) $xml->title,
'link' => $url,
'data' => $articles,
];
}
実行
fetch('umekikazuya');
結果
{
"title": "umekikazuyaの記事 - Qiita",
"link": "https://qiita.com/umekikazuya/feed",
"data": [
{
"title": "PRに対して意識が変わりました 〜エンジニア2年目の夏〜",
"link": "https://qiita.com/umekikazuya/items/a3260117bbc64e6673c3",
"published": "2024-06-25T20:42:15+09:00"
},
{
"title": "【PHP】DateTime::createFromFormat における ISO 8601 形式の罠",
"link": "https://qiita.com/umekikazuya/items/fb1b407ddd0fc4d6021c",
"published": "2024-06-24T21:39:14+09:00"
},
{
"title": "アジャイルでキャリア形成しよ 〜スプリントを管理するDB設計法〜",
"link": "https://qiita.com/umekikazuya/items/032c1e5d144830548d79",
"published": "2024-06-24T09:29:09+09:00"
},
{
"title": "【Drupal】過去の hook_update_N をスキップしたい",
"link": "https://qiita.com/umekikazuya/items/421cf61a64b363cf9080",
"published": "2024-06-24T01:36:38+09:00"
}
]
}
いい感じ!
解説
ちょっとだけ解説。
fetch(string $id, $format_json = TRUE)
について
Fetchして、データを返す関数です。
- アカウント名を引数にしてどのユーザーのFeedでも取得できるようにしています
- 第2引数で、JSON形式でデータを返す or 配列でデータを返す を指定できます
- データの取得にコケた場合や、解析時に不正なデータが合った場合はFALSEを返します
コードの責務が曖昧なので HTTP通信の実装部分は関数化してもいいかもですね。
loadRawFeedData(string $feed)
について
HTTP通信で取得した、生データを \SimpleXMLElement に変換します。
parseXml(\SimpleXMLElement $xml, string $url)
について
XMLデータを解析して、データのフォーマットをします。
キャストがちょっと雑かもですが、大目に見てください...
まとめ
いかがでしょうか?
記事内では、関数として実装を行いましたが...。
私はAPIを提供する Controller を実装してみました!!
もちろん、アカウントごとにResponseをCacheする機構も組み込んでいます。
次回もお楽しみに。
シリーズ紹介