[RUBY] Holen Sie sich Wettervorhersage von Open Weather Map with Rails

zunaechst

Dies ist Qiitas erster Beitrag! Da ich ein Anfänger bin, denke ich, dass es viele Punkte gibt, die ich nicht erreichen kann, aber ich wäre dankbar, wenn Sie herzlich kommentieren könnten!

Überblick

Entwicklungsumgebung

ruby: 2.7.1 rails: 6.0.3.2

Verfahren

  1. Holen Sie sich API KEY
  2. Holen Sie sich die STADT-ID der Stadt, die Sie erhalten möchten
  3. Erstellen und speichern Sie die Stadttabelle
  4. Implementierung der HTTP-Anfrage
  5. Erstellen und speichern Sie die WeatherForecast-Tabelle

1. Holen Sie sich API KEY

Gehen Sie zur OpenWeatherMap-Homepage und erstellen Sie ein Konto über Anmelden mit Konto erstellen. Wenn Sie es über die gesendete E-Mail aktivieren, erhalten Sie einen API-SCHLÜSSEL.

Speichern Sie dies als Umgebungsvariable oder "Anmeldeinformationen". Dieses Mal werden wir "Anmeldeinformationen" verwenden. In Bezug auf "Anmeldeinformationen" ist der [Artikel] dieser Person (https://qiita.com/NaokiIshimura/items/2a179f2ab910992c4d39) sehr hilfreich.

EDITOR=vi bin/rails credentials:edit

credentials.yml.enc


open_weahter:
    appid: <API_KEY>
    uri: https://samples.openweathermap.org/data/2.5/forecast

Da ich dieses Mal alle 3 Stunden das Wetter erhalte, erhalte ich außerdem die URI, um die Anfrage unter Bezugnahme auf das API-Dokument zu senden.

Es scheint, dass es viele Arten von Wetter gibt, die sogar mit der kostenlosen Stufe erhalten werden können! Es ist interessant, verschiedene API-Dokumente zu durchsuchen.

2. Holen Sie sich die STADT-ID

Laden Sie city.list.json aus der API-Dokumentation herunter (https://openweathermap.org/forecast5). [Screenshot 2020-08-02 15.54.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684915/9535a511-db9d-f4b3-f042- 028b93b1c498.png)

Erhalten Sie aus dieser Datei die STADT-ID der Stadt, die Sie erhalten möchten. Dies ist ein Teilauszug des Inhalts. Lon bedeutet übrigens Längengrad und Lat bedeutet Breitengrad.

city.list.json


  {
    "id": 1850147,
    "name": "Tokyo",
    "state": "",
    "country": "JP",
    "coord": {
      "lon": 139.691711,
      "lat": 35.689499
    }
  },

Ich habe geweint, um diesen Ausweis zu bekommen ... Bitte beachten Sie, dass einige Städte mit demselben Namen unterschiedliche Breiten- und Längengrade haben!

Wenn Sie Excel oder Mac verwenden, sollten Sie sie in Zahlen auflisten und in CSV konvertieren! Die von mir erstellte CSV sieht übrigens so aus. Ich kratzte ein paar Säulen.

db/csv/cities.csv


Sapporo,2128295
Aomori,2130658
Morioka,2111834
Sendai,2111149
Akita,2113126
Yamagata,2110556
Fukushima,2112923
Mito,2111901
Utsunomiya,1849053
Maebashi,1857843
Saitama,6940394
Chiba,2113015
Tokio,1850147
Yokohama,1848354
Niigata,1855431
Toyama,1849876
Kanazawa,1860243
Fukui,1863983
Yamanashi,1848649
Nagano,1856215
Gifu,1863640
Shizuoka,1851715
Nagoya,1856057
Tsu,1849796
Otsu,1853574
Kyoto,1857910
Osaka,1853909
Kobe,1859171
Nara,1855612
Wakayama,1926004
Tottori,1849890
Matsue,1857550
Okayama,1854383
Hiroshima,1862415
Yamaguchi,1848689
Tokushima,1850158
Takamatsu,1851100
Matsuyama,1926099
Kochi,1859146
Fukuoka,1863967
Saga,1853303
Nagasaki,1856177
Kumamoto,1858421
Oita,1854487
Miyazaki,1856717
Kagoshima,1860827
Naha,1856035

3. Erstellen und speichern Sie die Stadttabelle

Schreiben Sie den Code in seeds.rb oder task und speichern Sie ihn in der Datenbank. Dieses Mal habe ich es unter "lib / task" implementiert. CITY ID speichert den Spaltennamen als "location_id".

import_csv.rake


  desc 'Import cities'
  task cities: [:environment] do
    list = []
    CSV.foreach('db/csv/cities.csv') do |row|
      list << {
        name: row[0],
        location_id: row[1],
      }
    end

    puts 'start creating cities'
    begin
      City.create!(list)
      puts 'completed!'
    rescue ActiveModel::UnknownAttributeError
      puts 'raised error: unknown attributes'
    end
  end

Laden Sie die zuvor mit der Methode CSV.foreach erstellte city.csv Zeile für Zeile. Sie können den Städtenamen in der ersten Spalte mit "row [0]" und die CITY-ID in der zweiten Spalte mit "row [1]" abrufen. Erstellen Sie also ein Array von Hashes und speichern Sie es in der Datenbank mit "City.create!" Ich bin.

4. Implementierung der HTTP-Anfrage

Antwortanalyse

Analysieren Sie vor dem Implementieren der HTTP-Anforderung zunächst die JSON-Datei der Antwort.

API-Dokument enthält eine ausführliche Erläuterung der einzelnen Elemente. Lesen Sie daher das Dokument, um den Schlüssel der gewünschten Daten zu erhalten. Eine Anfrage für eine Stadt wird im folgenden JSON-Format zurückgesendet. (Wenn Sie den Befehl curl oder VScode verwenden, sollten Sie ihn mit REST Client versuchen.)

example_resopnse.json


{
  "cod": "200",
  "message": 0,
  "cnt": 40,
  "list": [
    {
      "dt": 1578409200,
      "main": {
        "temp": 284.92,
        "feels_like": 281.38,
        "temp_min": 283.58,
        "temp_max": 284.92,
        "pressure": 1020,
        "sea_level": 1020,
        "grnd_level": 1016,
        "humidity": 90,
        "temp_kf": 1.34
      },
      "weather": [
        {
          "id": 804,
          "main": "Clouds",
          "description": "overcast clouds",
          "icon": "04d"
        }
      ],
      "clouds": {
        "all": 100
      },
      "wind": {
        "speed": 5.19,
        "deg": 211
      },
      "sys": {
        "pod": "d"
      },
      "dt_txt": "2020-01-07 15:00:00"
    },
    

Dieses Mal erstelle ich eine Tabelle mit den folgenden Elementen.

"Regen" wird der Liste nur hinzugefügt, wenn es Niederschlag gibt.

Die Wetter-ID finden Sie unter hier. OpenWeatherMap klassifiziert das Wetter nach ID. Es ist auch möglich, das Wetter aus der Beschreibung zu erhalten. Da es jedoch viele Typen gibt, wird in dieser Implementierung die Wetter-ID in der Datenbank gespeichert und das Wetter von der Methode zugewiesen.

Implementierung der HTTP-Anfrage

Fügen Sie zunächst httpclient zu Ihrer Gemfile hinzu und installieren Sie das Paket.

gem 'httpclient', '~> 2.8', '>= 2.8.3'

Erstellen Sie dann "lib / api / open_weather_map / request.rb". Ich dachte, es wäre nicht notwendig, es so tief zu machen, aber ich entschied mich, die Dateien so anzuordnen, um andere Klassen für diese API und andere API-Klassen zu implementieren.

Standardmäßig wird nur die Aufgabe unter lib geladen, daher sind die folgenden Einstellungen in config / application.rb erforderlich. Da es sich um "eifrige_Ladungspfade" handelt, ist auch die Produktionsumgebung in Ordnung.

config/application.rb


config.paths.add 'lib', eager_load: true

Ich würde mich sehr freuen, wenn Sie auf Punkte wie "Hey, das ist großartig" hinweisen könnten. Die Platzierung von Dateien war das größte Problem bei dieser Implementierung ...

WeatherForecast-Tabelle zum Speichern von Anfragen ↓

WeatherForecast
temp_max float
temp_min float
temp_feel float
weather_id int
rainfall float
date datetime
aquired_at datetime

Das Folgende ist die implementierte Request-Klasse.

request.rb


module Api
  module OpenWeatherMap
    class Request
      attr_accessor :query

      def initialize(location_id)
        @query = {
          id: location_id,
          units: 'metric',
          appid: Rails.application.credentials.open_weather[:appid],
        }
      end

      def request
        client = HTTPClient.new
        request = client.get(Rails.application.credentials.open_weather[:uri], query) #Der Rückgabewert sind Daten für 5 Tage alle 3 Stunden
        JSON.parse(request.body)
      end

      def self.attributes_for(attrs)
        rainfall = attrs['rain']['3h'] if attrs['rain']
        date = attrs['dt_txt'].in_time_zone('UTC').in_time_zone

        {
          temp_max: attrs['main']['temp_max'],
          temp_min: attrs['main']['temp_min'],
          temp_feel: attrs['main']['feels_like'],
          weather_id: attrs['weather'][0]['id'],
          rainfall: rainfall,
          date: date,
          aquired_at: Time.current,
        }
      end
    end
  end
end

Die Abfragezeichenfolge wird mit initialize gesetzt. Die für diese Anforderung erforderliche Abfragezeichenfolge fügt "location_id" und API KEY hinzu, um die CITY-ID anzugeben, und "unit:" metric ", um die Temperaturanzeige in Grad Celsius zu ändern.

Die Methode attribute_for wird in eine Klassenmethode umgewandelt, um die zurückgegebene Anforderung in ein Formular zu konvertieren, das in der Datenbank gespeichert werden kann.

Was Sie beachten müssen, ist die Niederschlagsmenge und das Prognosedatum.

Informationen zum Umgang mit Zeitzonen finden Sie in diesem Artikel.

5. Erstellen und speichern Sie die WeatherForecast-Tabelle

Erstellen einer Rechenaufgabe

Ich möchte die Datenbank regelmäßig speichern / aktualisieren, daher schreibe ich sie in "Rake Task". Trotzdem habe ich die meisten Methoden in der Klasse "Request" früher geschrieben, also muss ich sie nur verwenden.

open_weather_api.rake


namespace :open_weather_api do
  desc 'Requests and save in database'
  task weather_forecasts: :environment do
    City.all.each do |city|
      open_weather = Api::OpenWeatherMap::Request.new(city.location_id)

      #Anforderungslimit: 60 mal/min
      response = open_weather.request

      #Speichern Sie alle 3 Stunden 2 Tage Daten
      16.times do |i|
        params = Api::OpenWeatherMap::Request.attributes_for(response['list'][i])
        if weather_forecast = WeatherForecast.where(city: city, date: params[:date]).presence
          weather_forecast[0].update!(params)
        else
          city.weather_forecasts.create!(params)
        end
      end
    end
    puts 'completed!'
  end
end

Dieses Mal haben wir festgelegt, dass die Daten 2 Tage lang alle 3 Stunden in der Datenbank gespeichert und aktualisiert werden sollen. Der Punkt ist das Anforderungslimit und ob es sich um die Erstellung oder Aktualisierung von Daten handelt.

Schließlich

Wenn Sie ein Wettersymbol vorbereiten, das der gespeicherten "Wetter-ID" entspricht, sieht es wie eine Wettervorhersage aus! Ich denke, es ist eine gute Idee, API regelmäßig mit Cron oder "Heroku Schedular" für Heroku zu schlagen!

Es wurde so angezeigt! スクリーンショット 2020-08-02 18.26.45.png

Vielen Dank für das Lesen des langen Textes!

Referenz

https://openweathermap.org/api https://qiita.com/yoshito410kam/items/26c3c6e519d4990ed739

Recommended Posts

Holen Sie sich Wettervorhersage von Open Weather Map with Rails
[Rails] Holen Sie sich UserAgent auf den Controller
[Rails] So zeigen Sie die Wettervorhersage der registrierten Adresse auf Japanisch mit OpenWeatherMap an
Holen Sie sich Wettervorhersagen von Watson Weather Company Data mit einfachem Java
Holen Sie sich "2-4, 7, 9" aus [4, 7, 9, 2, 3]
Abrufen des Verlaufs vom Zabbix-Server in Java
So erhalten Sie eine Klasse von Element in Java
Rails Logger Machen Sie sich in 1 Minute eine ungefähre Vorstellung
Holen Sie sich Unixtime (Sekunden) von ZonedDateTime in Scala / Java
Group_by in Rails
[Java] KFunction von Method / Constructor in Java abrufen [Kotlin]
Holen Sie sich Standortinformationen mit Rails und sortieren Sie in aufsteigender Reihenfolge
Modellassoziation in Rails
Hinzufügen von Spalten in Rails
Deaktivieren Sie Turbolinks in Schienen
^, $ im regulären Ausdruck von Rails
Verwenden Sie Bilder mit Schienen
Migration in Schienen verstehen
Holen Sie sich Cookies im Frühling
Teilen Sie route.rb in Rails6
Cloud9 (Rails) von Github
Markdown in Rails implementiert
Holen Sie sich ganz einfach Ganzzahlen aus den Systemeigenschaften in Java
Ruft Attribute und Werte aus einer XML-Datei in Java ab
Holen Sie sich mit Java eine nicht leere Sammlung aus einem optionalen Stream