
AWSフォーラムをMechanizeとNokogoriでスクレイピングしてRSS一覧を取得してみた
はじめに
こんにちは植木和樹@上越妙高オフィスです。本日はRubyのNokogiriライブラリを使ったスクレイピングのご紹介です。
AWS各サービスのアップデートはフォーラムにてアナウンスされています。
こちらのページでRSSが取得できるのですが、サービス単位でRSSが分かれているため、リンクを1つ1つコピーしてRSSリーダーに登録する必要があります。はい、面倒くさいですね。
面倒なことはコンピューターにやってもらいましょう。ということでRSSのURLを取得する処理をRubyを使って作ってみました。
スクリプトと解説
スクリプトはgistで公開しています。改変はご自由に。 解説はシェルのコメントに書いたので参考にしてください。
#!/usr/bin/env ruby | |
require 'mechanize' | |
require 'nokogiri' | |
host = "https://forums.aws.amazon.com" | |
url = "#{host}/rss.jspa" | |
# open-uriだと302のリダイレクトが正しく処理できないためMechanizeを使います | |
mechanize = Mechanize.new | |
page = mechanize.get url | |
# AWSフォーラムはトップ・ミドル・フォーラムの3階層になっているようです | |
top_category="" | |
mid_category="" | |
# Machanizeで取得したHTMLをNokogiriに渡してパースします | |
doc = Nokogiri::HTML(page.body) | |
# jive-tableコンテナー内のテーブルの各行がサービスに対応しているようです | |
doc.xpath("//div[@class='jive-table']/table/tbody/tr").each do |node| | |
# 階層レベルとサービス名・フォーラム名は jive-first クラスの列内のテーブルにあります | |
# カテゴリの階層はテーブルの1列目でスペースが3つならトップ、6つならミドルです | |
indent_cell = node.xpath("td[@class='jive-first']/table/tbody/tr/td[1]") | |
title_cell = node.xpath("td[@class='jive-first']/table/tbody/tr/td[2]") | |
title = title_cell.text | |
if title =~ /^\s*Category\s*:\s*(.+)/ | |
if indent_cell.text.length == 3 | |
top_category = $1.strip | |
else | |
mid_category = $1.strip | |
end | |
end | |
# Forum以外のRSSは更新されないようなので無視します | |
next unless title =~ /^\s*Forum/ | |
# サービスのアナウンスは"Amazon Web Services"カテゴリで行われるようなので | |
# それ以外のトップカテゴリは無視します | |
next unless top_category == "Amazon Web Services" | |
# rssのリンクは jive-last クラスの列内のテーブルにあります | |
# AnnoucementsのRSSはテーブル1列目です | |
rsspath = node.xpath("td[@class='jive-last']/div/table/tbody/tr/td[1]/a").attribute("href") | |
# Forumという文字列と余分な空白を取り除きます | |
title.sub!("Forum:","") | |
title.strip! | |
next unless title.length > 0 | |
#puts "#{host}/#{rsspath} #{top_category}/#{mid_category}/#{title}" | |
puts "#{host}/#{rsspath} #{title}" | |
end |
また実行にはRubyのMechanizeとNokogiriライブラリが必要になります。gemでインストールしましょう。(今回rubyは2.2.0を使いました)
$ gem install mechanize nokogiri --no-ri --no-rdoc $ ruby --version ruby 2.2.0p0 (2014-12-25 revision 49005) [x86_64-darwin13] $ gem list mechanize nokogiri *** LOCAL GEMS *** mechanize (2.7.4) *** LOCAL GEMS *** nokogiri (1.6.7.2)
実行結果
https://forums.aws.amazon.com/rss/rssannounce.jspa?forumID=199 Amazon API Gateway https://forums.aws.amazon.com/rss/rssannounce.jspa?forumID=171 Amazon AppStream https://forums.aws.amazon.com/rss/rssannounce.jspa?forumID=137 Amazon CloudSearch https://forums.aws.amazon.com/rss/rssannounce.jspa?forumID=147 Amazon Elastic Transcoder https://forums.aws.amazon.com/rss/rssannounce.jspa?forumID=90 Amazon Simple Email Service : :
スクレイピングのコツ
NokogiriではXPathという方法で、HTMLの構造を指定して必要なコンテンツを取得できます。ただHTMLのソースを読んでこの階層構造を解析するのは大変です。
今回はChromeのDeveloper Toolを使って、XPathを調べました。調べ方はこちらのブログが詳しかったです。
# Forum Amazon API Gateway サービス名のXPathを取得 //*[@id="jive-rsspage"]/table/tbody/tr/td[1]/div/table/tbody/tr[3]/td[1]/table/tbody/tr/td[2] # Forum Amazon AppStream サービス名のXPathを取得 # 途中のtr配列が[3] -> [4] なので、このtrをループさせればサービスをとれそう //*[@id="jive-rsspage"]/table/tbody/tr/td[1]/div/table/tbody/tr[4]/td[1]/table/tbody/tr/td[2] # Forum Amazon API Gateway Annousments RSSリンクのXPathを取得 # API Gatewayは同じtr[3]で列がtd[2]、さらに下層にテーブル構造があることがわかる //*[@id="jive-rsspage"]/table/tbody/tr/td[1]/div/table/tbody/tr[3]/td[2]/div/table/tbody/tr/td[1]/a
Chromeで取得したXPath表記だと指定するパスが長かったので、今回は構造を調べた後class指定に見直してちょっとスッキリさせています。
まとめ
Nokogiri + XPathを使って簡単にHTMLから情報を引き出すことができました。
このURLを個人のRSSリーダー(LDRが好みです)に登録して読んでもいいのですが、AWS業務に関わるメンバーみんなで共有した方がいいため、取得したアナウンスをChatworkにポストするようにしました(くらめその方はご自由に入室ください)。このスクリプトは以前ご紹介したシェルスクリプトを流用していますので、こちらも参考にどうぞ。
- 【Ruby】ActiveSupportを使わず標準添付ライブラリReXML/JSONだけでXML→JSON変換する(ruby 2.2.0) | Developers.IO
- 【習作】AWS Service Health Dashboardの更新をChatWorkに書き込むシェルスクリプトを作ってみた | Developers.IO
AWSは日々新サービスや新機能がリリースされますので追うのが大変ですが、RSSをうまく使って効率良く情報収集しましょう。