Как получить данные о погоде с платформы Google Maps?

У меня есть список мест, и я хочу знать, можно ли получать данные о погоде из API Карт Google.

Ответ 1

Когда я должен был сделать это в Go, я сделал что-то вроде этого:

package main

import (
    "bufio"
    "context"
    "database/sql"
    "encoding/json"
    "flag"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "os"
    "strings"
    "sync"
    "time"

    "googlemaps.github.io/maps"

    _ "github.com/lib/pq"
)

var db *sql.DB

var (
    apiKey        string
    dsn           string
    locationsFile string
)

type HourlyForecast struct {
    Type       string
    Properties Properties
}

type Properties struct {
    Periods []Period
}

type Period struct {
    Temperature int
}

func main() {
    flag.StringVar(&apiKey, "api-key", "", "Google Maps API key")
    flag.StringVar(&dsn, "dsn", "", "The database connection string")
    flag.StringVar(&locationsFile, "locations", "locations.txt", "The locations file")
    flag.Parse()

    if apiKey == "" {
        apiKey = os.Getenv("GOOGLE_MAPS_API_KEY")
    }

    if apiKey == "" {
        log.Fatal("The --api-key flag or GOOGLE_MAPS_API_KEY env var must be set and non-empty")
    }

    apiKey = strings.TrimSpace(apiKey)

    if dsn == "" {
        dsn = os.Getenv("DSN")
    }

    var err error
    db, err = sql.Open("postgres", dsn)
    if err != nil {
        log.Fatal(err)
    }

    for {
        err := db.Ping()
        if err != nil {
            log.Println(err.Error())
            time.Sleep(3 * time.Second)
            continue
        }
        break
    }

    data, err := os.Open(locationsFile)
    if err != nil {
        log.Fatal(err)
    }

    var locations []string

    scanner := bufio.NewScanner(data)
    for scanner.Scan() {
        locations = append(locations, scanner.Text())

    }

    var wg sync.WaitGroup

    for _, location := range locations {
        wg.Add(1)
        location := location

        go func() {
            defer wg.Done()

            mc, err := maps.NewClient(maps.WithAPIKey(apiKey))
            if err != nil {
                log.Fatal(err)
            }

            r := maps.FindPlaceFromTextRequest{
                Input:     location,
                InputType: maps.FindPlaceFromTextInputTypeTextQuery,
            }

            response, err := mc.FindPlaceFromText(context.Background(), &r)
            if err != nil {
                log.Fatal(err)
            }

            pdr := maps.PlaceDetailsRequest{
                PlaceID: response.Candidates[0].PlaceID,
            }
            log.Printf("retrieving geo coordinates for %s", location)
            pdResponse, err := mc.PlaceDetails(context.Background(), &pdr)
            if err != nil {
                log.Fatal(err)
            }

            lat := pdResponse.Geometry.Location.Lat
            lng := pdResponse.Geometry.Location.Lng
            u := fmt.Sprintf("https://api.weather.gov/points/%.4f,%.4f/forecast/hourly", lat, lng)
            log.Printf("retrieving weather data for %s (%.4f,%.4f)", location, lat, lng)

            request, err := http.NewRequest("GET", u, nil)
            if err != nil {
                log.Fatal(err)
            }
            request.Header.Add("User-Agent", "Hightower Weather 1.0")
            request.Header.Add("Accept", "application/geo+json")

            weatherResponse, err := http.DefaultClient.Do(request)
            if err != nil {
                log.Fatal(err)
            }

            data, err := ioutil.ReadAll(weatherResponse.Body)
            if err != nil {
                log.Fatal(err)
            }

            weatherResponse.Body.Close()

            var forecast HourlyForecast
            if err := json.Unmarshal(data, &forecast); err != nil {
                log.Fatal(err)
            }

            log.Printf("setting temperature for %s to %d", location, forecast.Properties.Periods[0].Temperature)
            _, err = db.Exec(query, location, forecast.Properties.Periods[0].Temperature)
            if err != nil {
                log.Fatal(err)
            }
        }()
    }

    wg.Wait()
}

var query = 'INSERT INTO weather (location, temperature)
VALUES ($1, $2)
ON CONFLICT (location)
DO UPDATE SET temperature = EXCLUDED.temperature;'