【スマートホーム】SwitchBotのカーテン開閉機の日の出、日の入り時刻を自動で入手する方法

投稿者: | 2月 26, 2023

Switchボットカーテンの自動化をした時に日の出・日の入り時刻1年間のみ手動で取得していたため、年がまたいだ時にカーテンが開閉しない事態に陥りました。
今回は、年をまたがなくも時刻を取得できるように、Rubyのスクレイピング技術を用いて取得します。

1.スクレイピングとは

スクレイピングとは、「webページなどのデータを取得して加工すること」を意味します。

スクレイピングと同様に「クローリング」という用語も使用されますが、クローリングはデータの取得のみを行うことを意味しています。
しかし、どちらの意味を使っても通じるので、使い分ける必要はないと考えてます。

2. 今回の目標

今回は、このスクレイピングを用いて、motohashi.netさんの日の出・日の入り時刻の表ページからデータを収集し、CSV形式で1年間保管することを実現します。
※②~③はこちらで説明してるので、気になる方がいましたら参照いただけたらと思います

3.事前準備

今回はRuby言語を用いてスクレイピングを実施するため、事前にNokogiriをインストールします。

3-1.Nokogiriとは

Nokogiriとは、Ruby言語のスクレイピングを実施するためのライブラリとなっています。
下表8つの機能が使用できますが、今回は「XML、HTML4、および HTML5 用の DOM パーサー」を使用します。

・XML、HTML4、および HTML5 用の DOM パーサー
・XML および HTML4 用の SAX パーサー
・XML および HTML4 のプッシュ パーサー
・XPath 1.0 による文書検索
・jquery に似た拡張機能を備えた、CSS3 セレクターによるドキュメント検索
・XSD スキーマの検証
・XSLT 変換
・XML および HTML ドキュメント用の「ビルダー」DSL
※Nokogiri(https://nokogiri.org/)参照

3-2.Nokogiriのインストール

インストールは下記を実施するだけで簡単に実行できます。

$gen install nokogiri

4.ソースコード作成

今回は、motohashi.netさんのページの下表から日付・日の出・日の入りの3つを年間で取得し、CSVで保存しておくソースコードを作成します。

データ取得の際にHTML文の中から要素を取得する必要があるため、HTML文を確認する必要があります。
また、今回は表形式から要素を抽出するため、そんなに難しくはないと思います。

実際にHTML文テーブルを確認すると、「tableタブ」の中の「trタブ」の「td」を取得することになります。
※ブラウザの「F12」キーで確認することができます

2023/1/1の要素

そのため、今回は下記のソースコードを作成しました。

#curtain_dataset.rb
require 'nokogiri'
require 'open-uri'

require 'date'


#すべての要素を配列で格納する
row = Array.new(365){Array.new(10,0)}
#p row
first = 0
i = 0
j = 0

# 対象のURL(日にちで取得可能のため、取得時の日付を指定)
today = Date.today
url = "https://www.motohasi.net/SunriseSunset/WorldSun2.php?Date=" + today.to_s + "&Lat=35.689444&Lng=139.691666&TimeZone=Asia/Tokyo&CityName=%E6%9D%B1%E4%BA%AC"



html = Nokogiri::HTML(open(url))

#table配下のtdタブを取得
html.xpath('//*/table/tr/td').each do |td|

        #最初は空のため、除外
        if td.text == ''

        elsif j == 10
           i += 1
           j = 0
           row[i][j] = td.text
           j += 1
        else
          row[i][j] = td.text
          j += 1

        end
end

これで日の出・日の入りの日時を取得することができましたが、テキストに保存ができていません。

そのため、上記のソースコードにCSV保存するためのコードを追加します。

#curtain_dataset.rb
require 'nokogiri'
require 'open-uri'
require 'csv'
require 'date'


row = Array.new(365){Array.new(10,0)}
#p row
first = 0
i = 0
j = 0

# 対象のURL
today = Date.today
url = "https://www.motohasi.net/SunriseSunset/WorldSun2.php?Date=" + today.to_s + "&Lat=35.689444&Lng=139.691666&TimeZone=Asia/Tokyo&CityName=%E6%9D%B1%E4%BA%AC"

p url

html = Nokogiri::HTML(open(url))

html.xpath('//*/table/tr/td').each do |td|
        if td.text == ''

        elsif j == 10
           i += 1
           j = 0
           row[i][j] = td.text
           j += 1
        else
          row[i][j] = td.text
          j += 1

        end
end


CSV.open("/home/pi/data/sunrise_sunset.csv","w") do |write|
        row.each do |date, sunset, sunrise, lunch, city_open, city_close, water_open, water_close, tenmon_open, tenmon_close|
                write <<[date, sunset, sunrise]
        end
end

4-1 Cronの設定

最後に、Cronの設定を行います。
Cronとは、設定した日時にスクリプトを動かしてくれるLinuxの機能です。

今回は設定している内容は載せませんが、12/31の23時に設定すると年がまたいだ時にカーテンの開閉が行われなくなる心配はなくなると思います。

5.さいごに

今回はRuby言語のNokogiriを用いて日の出・日の入り時刻データを収集する方法を記載しました。

WebページではHTMLベースで記載されているため、データの取得・加工が簡単に行えるため、皆さんも挑戦してみてはいかがでしょうか。

ちなみに私は、ソースコードを書くのに2.5時間はかかりました。。。

6.参考図書

スクレイピングを実施する際はPythonが主流のため、Rubyでの出版物が皆無に等しいです。
また、RUbyでググってもあまり有益な情報は出てこないことが多々あります。

そのため、今回は私が5年ほど前に読んだ図書を参考とさせていただきますので、興味がありましたら購入をお勧めします。


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です