Búsqueda de sitios web

Un servicio meteorológico de PowerShell


Me he divertido esta semana compartiendo algunas herramientas para obtener información y pronósticos meteorológicos usando PowerShell. Para completar la historia, hoy tengo una técnica más. Con PowerShell, puede consultar un servicio web para obtener información meteorológica. En términos simples, un servicio web es como una aplicación que puedes "ejecutar" a través de una conexión web y, a veces, incluso en un navegador. El servicio web tiene "métodos" que puede invocar para hacer algo. En el pasado, si deseaba interactuar con un servicio web en PowerShell, lo más probable era que necesitara ponerse manos a la obra con .NET Framework. Luego, PowerShell 3.0 nos trajo un nuevo cmdlet, New-WebServiceProxy. Con este cmdlet puede crear un objeto que, en esencia, se convierte en un contenedor para el servicio web. Los métodos del servicio web se convierten en los métodos del objeto. Deja que te enseñe.

Primero, crearé mi objeto proxy.

$proxy = New-WebServiceProxy -uri http://www.webservicex.com/globalweather.asmx?WSDL

Este objeto también tiene métodos:

Entonces, ¿cómo uso el método GetWeather?

Parece sencillo. Intentemos. ¿Me pregunto cómo será un lugar cálido?

Interesante. Puedo leerlo, pero seguro que parece XML. Si es así, debería poder recuperar el clima como un documento XML.

[xml]$current = $proxy.GetWeather("Miami","United States")

Ahora puedo explorarlo.

Guau. Esto parece sencillo. Todo lo que necesito es la propiedad CurrentWeather y tengo un resultado fácil de leer. Probablemente podría ejecutar esto como una sola línea.

([xml]((New-WebServiceProxy -uri http://www.webservicex.com/globalweather.asmx?WSDL).GetWeather("Fairbanks","United States"))).CurrentWeather

No necesariamente es fácil de leer pero funciona.

¿Qué pasa con otra ciudad? Quizás Charlotte, Carolina del Norte, el sitio de la próxima Cumbre PowerShell.

([xml]((New-WebServiceProxy -uri http://www.webservicex.com/globalweather.asmx?WSDL).GetWeather("Charlotte","United States"))).CurrentWeather

Bueno, eso funcionó, pero esa no es la ciudad que tenía en mente. Volviendo a los métodos del servicio web, recuerdo haber visto algo para obtener ciudades por país. Intentemos eso.

$proxy.GetCitiesByCountry("Nepal")

Más XML. Eso es encontrar. Puedo usar Select-XML para analizar el nodo Ciudad.

$proxy.GetCitiesByCountry("Nepal") | select-xml "//City"

Ahora, expanda cada nodo.

$proxy.GetCitiesByCountry("Nepal") | select-xml "//City" | select -expand node

Probemos ahora con EE. UU. y busquemos ciudades que tengan Charlotte en el nombre.

$proxy.GetCitiesByCountry("United States") | select-xml "//City" | select -expand node | Where {$_.'#text' -match "Charlotte"}

Me parece que los datos del servicio meteorológico proceden principalmente de lugares con aeropuertos. Entonces, si vive en una ciudad sin aeropuerto, lo mejor que puede hacer probablemente sea encontrar una ubicación cerca de usted con aeropuerto. Pero ahora que veo lo que necesito para Charlotte, Carolina del Norte, puedo revisar mi mando.

([xml]((New-WebServiceProxy -uri http://www.webservicex.com/globalweather.asmx?WSDL).GetWeather("Charlotte / Douglas","United States"))).CurrentWeather

Mucho mejor. Pero no quiero tener que escribir mucho para todo esto, así que reuní algunas funciones para simplificar todo el proceso. Primero, es una función para obtener una ubicación.

Function Get-WeatherLocation {

<#
.SYNOPSIS
Get weather locations via web service proxy
.DESCRIPTION
This command will get all cities for a given country using a web service proxy designed to retrieve weather conditions.
.PARAMETER Country
The name of the country in English. 
.PARAMETER City
Some portion of the name of a city or area. The command will match on the pattern so regular expressions are permitted.
.EXAMPLE
PS C:\> Get-WeatherLocation Albania

City                                         Country
----                                         -------
Tirana                                       Albania

.EXAMPLE
PS C:\> Get-Weatherlocation -city "chicago"


City                                         Country                                    
----                                         -------                                    
Chicago / Meigs                              United States                              
Chicago / West Chicago, Dupage Airport       United States                              
Chicago, Chicago Midway Airport              United States                              
Chicago, Chicago-O'Hare International Air... United States                              
Chicago / Wheeling, Pal-Waukee Airport       United States                              
Chicago / Waukegan                           United States                              

Find all US locations that have "Chicago" in the name.

.NOTES
NAME        :  Get-WeatherLocation
VERSION     :  1.0   
LAST UPDATED:  2/19/2015
AUTHOR      :  Jeff Hicks

Learn more about PowerShell:
Essential PowerShell Learning Resources
**************************************************************** * DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED * * THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK. IF * * YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, * * DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING. * **************************************************************** .LINK New-WebServiceProxy .INPUTS None .OUTPUTS Custom object #> [cmdletbinding()] Param( [Parameter(Position=0,ValueFromPipeline)] [ValidateNotNullorEmpty()] [string]$Country="United States", [string]$City ) Begin { Write-Verbose -Message "Starting $($MyInvocation.Mycommand)" Try { #hashtable of parameters to splat to New-WebServiceProxy $paramHash = @{ uri = 'http://www.webservicex.com/globalweather.asmx?WSDL' ErrorAction = 'Stop' } Write-Verbose "Creating web proxy to $($paramHash.uri)" $webproxy = New-WebServiceProxy @paramHash } Catch { Throw $_ } } #begin Process { If ($webproxy) { [xml]$cities = $webproxy.GetCitiesbyCountry($Country) #only continue if there is data to process if ($cities.NewDataset) { #this will write a new object to the pipeline with 2 properties $data = $cities.NewDataSet.table | select City,Country } Else { Write-Warning "Failed to retrieve cities for $country" } if ($City) { $data | where {$_.city -match $City} } else { #write all data to the pipeline $data } } #if webproxy } #process End { Write-Verbose -Message "Ending $($MyInvocation.Mycommand)" } #end } #end function Set-Alias -Name gwl -Value Get-WeatherLocation

La función hace todo el trabajo de crear el proxy del servicio web y recuperar ciudades por país. Puede cambiar el valor predeterminado a su país. También agregué un parámetro que coincidirá con el nombre de una ciudad.

Luego escribí una función para facilitar la obtención de información meteorológica.

Function Get-WeatherByProxy {
<#
.SYNOPSIS
Get weather conditions via a web service proxy
.DESCRIPTION
This command uses the New-WebServiceProxy cmdlet to retrieve weather information from a web service.
.PARAMETER City
The name of the city or location. This works best if the city has an airport. You can also use part of the airport name.
.PARAMETER Country
The name of the country in English.

.EXAMPLE
PS C:\> Get-Weatherbyproxy Seattle

Location         : SEATTLE-TACOMA INTERNATIONAL  AIRPORT , WA, United States (KSEA) 
                   47-27N 122-19W 136M
Time             : Feb 18, 2015 - 08:53 AM EST / 2015.02.18 1353 UTC
Wind             : from the SE (130 degrees) at 8 MPH (7 KT):0
Visibility       : 10 mile(s):0
SkyConditions    : partly cloudy
Temperature      : 43.0 F (6.1 C)
DewPoint         : 39.0 F (3.9 C)
RelativeHumidity : 85%
Pressure         : 30.18 in. Hg (1022 hPa)
Status           : Success

Get the weather in Seattle.
.EXAMPLE
PS C:\> Get-WeatherbyProxy "O'Hare" | Select Time,Sky*,Temperature

Time                          SkyConditions                 Temperature                 
----                          -------------                 -----------                 
Feb 18, 2015 - 09:51 AM ES... partly cloudy                 5.0 F (-15.0 C)

Get the weather in Chicago using O'Hare airport as the source.
.EXAMPLE
PS C:\> Get-Weatherbyproxy Oslo Norway

Location         : Oslo / Gardermoen, Norway (ENGM) 60-12N 011-05E 204M
Time             : Feb 18, 2015 - 09:50 AM EST / 2015.02.18 1450 UTC
Wind             : from the S (190 degrees) at 12 MPH (10 KT):0
Visibility       : greater than 7 mile(s):0
SkyConditions    : mostly cloudy
Temperature      : 39 F (4 C)
DewPoint         : 33 F (1 C)
RelativeHumidity : 80%
Pressure         : 29.94 in. Hg (1014 hPa)
Status           : Success
.Example
PS C:\> Get-WeatherLocation "united states" -city "Charlotte" | get-weatherbyproxy | out-gridview -title Weather

This command uses a related function called Get-WeatherLocation to find all US locations that have Charlotte in the name and retrieves the weather for each location. Results are displayed using Out-Gridview.
.NOTES
NAME        :  Get-WeatherByProxy
VERSION     :  1.0   
LAST UPDATED:  2/18/2015
AUTHOR      :  Jeff Hicks

Learn more about PowerShell:
Essential PowerShell Learning Resources
**************************************************************** * DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED * * THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK. IF * * YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, * * DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING. * **************************************************************** .LINK New-WebServiceProxy .INPUTS Strings .OUTPUTS Custom object #> [cmdletbinding()] Param( [Parameter(Position=0,Mandatory, HelpMessage="Enter the name of a city. Preferably one with an airport", ValueFromPipeline,ValueFromPipelineByPropertyname)] [ValidateNotNullorEmpty()] [string[]]$City, [Parameter(Position=1,ValueFromPipelineByPropertyname)] [ValidateNotNullorEmpty()] [string]$Country = "United States" ) Begin { Write-Verbose -Message "Starting $($MyInvocation.Mycommand)" Try { #hashtable of parameters to splat to New-WebServiceProxy $paramHash = @{ uri = 'http://www.webservicex.com/globalweather.asmx?WSDL' ErrorAction = 'Stop' } Write-Verbose "Creating web proxy to $($paramHash.uri)" $webproxy = New-WebServiceProxy @paramHash } Catch { Throw $_ } } #begin Process { #only process if there is a proxy object if ($webproxy) { foreach ($location in $city) { Write-Verbose "Getting weather for $location, $country" Try { #result is XML so let's make it an object [xml]$doc = $webproxy.GetWeather($location,$country) Write-Debug ($doc.CurrentWeather | out-string) #get the child nodes which will be the properites #but omit Status since we don't need it. $properties = $doc.CurrentWeather.ChildNodes.name | Where {$_ -ne 'Status'} | Select -Unique #create a custom object and add each property value trimmed #of extra spaces $propHash = [ordered]@{} #there are duplicate node names so we'll join them #into a single property foreach ($property in $properties) { Write-Debug $property $value = ($doc.currentWeather | select-xml "//$property" | select -expand Node).'#text'.trim() -join " " $propHash.Add($property,$value) } Write-Debug ($propHash | out-string) #Write the result [pscustomobject]$propHash } #try xml Catch { Write-Warning "Failed to find weather information for $location, $country" Write-Warning $_.exception.message } #catch } #foreach location } #if $weather } # process End { Write-Verbose -Message "Ending $($MyInvocation.Mycommand)" } #end } #end function Set-Alias -Name gwp -Value Get-WeatherByProxy

Al observar el XML, hubo algunos problemas menores. Uno, el nodo Viento se repitió, así que decidí combinar los dos en una sola propiedad. También noté que algunos de los valores de los nodos tenían espacios adicionales. Así que recorté los valores mientras construía una tabla hash ordenada que luego convertí en un objeto personalizado. El resultado final es una herramienta fácil de usar.

Incluso puedes canalizar entre comandos.

get-weatherlocation -city chicago | get-weatherbyproxy | Out-GridView -title "Chicago"

Las propiedades del objeto son todas cadenas, lo que significa que ordenar o filtrar es problemático, pero aquí hay algunos buenos datos, así que supongo que es una compensación.

Ahora tienes varias formas de comprobar el tiempo, suponiendo que no puedas simplemente mirar por la ventana. Y, con suerte, habrá aprendido algunas cosas nuevas sobre PowerShell a lo largo del camino.

Artículos relacionados