WordPress Blogのfeedをjavascriptで扱いたい。
feedをjsonで返すプラグインなんてのもあったんですが、今後のことも考えて使う側でどうにかしたいと思います。
jQueryの$.parseXML()
を使うとかなり楽ですが、できればもうjQueryにはかかわらないようにしたい。
fetch APIを使ってXMLを処理してみます。
パース処理
1 2 3 4 5 6 7 8 |
const parser = new DOMParser(); fetch("https://blog.narumium.net/feed") .then(res => res.text()) .then(txt => parser.parseFromString(txt, "text/xml")) .then(doc => doc.querySelectorAll("item")) .then(items => { ... //後処理 }); |
res => res.text()
← fetch
で得られるResponse
でxml()
みたいなものがあればよかったんですが、そんなものはないのでtext()
で文字列にします。
txt => parser.parseFromString(txt, "text/xml")
← DOMParserでxmlにパース。
doc => doc.querySelectorAll("item")
← XMLからitemをすべて抜き出す。
(ところでこういう処理だとasync / await
よりもthen
チェーンの方が見やすい気がする。)
パース後の抽出処理
後処理はXMLの中身次第ですがワードプレスのフィードを例に書いてみます。
まずはNodeListをArrayにしてmap()処理します。
(list.forEach
でもいいんですがArray処理に慣れた今いちいち書くのがめんどい)
1 2 3 4 5 |
.then(items => Array.from(items).map(item => { ... }) ); |
このitem
のitem.innerHTMLから必要な情報を取ってまわるわけですが結構面倒。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
//外にテキスト取得用関数を作っておく(別になくてもいい) const text = node => node.textContent || node.innerText; ... const title = text(item.querySelector("title")); const date = new Date( text(item.querySelector("pubDate")) ).toLocaleString(); const link = text(item.querySelector("link")); const _c = parser .parseFromString(item.querySelector("encoded").innerHTML, "text/html") .querySelector("body"); let thumb = null; let _t = _c.querySelector("url"); if (_t) { thumb = _t.innerText; _c.removeChild(_t); } const content = text(_c).slice(0, 100); return { title, date, link, content, thumb }; |
特に本文<content:encoded>
はhtmlだとquerySelector("content\\:encoded")
で取れるのにxmlだとquerySelector("encoded")
でないといけないのはハマった。
中身もよくわからないことになっていたので追加でパースしないといけないし。
また本文中にサムネイルURLが含まれるため<url>
があれば別途保存してノードから取り除くみたいな泥臭い処理になってしまいました。
Array.map
内の処理なので上処理の返値の配列が返ってきます。
色々不格好ではありますがとりあえず必要な情報をjsonで取得できました。
追記:サムネイルについて
なんかほかでサムネイル取得できないなと思ったら、通常のフィードにサムネイルURLがないため自分のブログでは追加してました。
1 2 3 4 5 6 7 8 9 10 |
function post_thumbnail_in_feeds($content) { global $post; $image_url = wp_get_attachment_image_src(get_post_thumbnail_id($post->ID), 'thumbnail'); if(has_post_thumbnail($post->ID)) { $content = '<image><url>' . $image_url[0] . '</url></image>' . $content; } return $content; } add_filter('the_excerpt_rss', 'post_thumbnail_in_feeds'); add_filter('the_content_feed', 'post_thumbnail_in_feeds'); |
ノーマルなフィードの場合はthumb
の部分は除いてください。