It is currently March 30th, 2020, 1:57 pm

⭐ weather.com - Parsing the JSON

Our most popular Tips and Tricks from the Rainmeter Team and others
User avatar
jsmorley
Developer
Posts: 20425
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: ⭐ weather.com - Parsing the JSON

Post by jsmorley »

Yincognito wrote:
February 9th, 2020, 12:42 am
You're probably right. We wouldn't be the first ones to use it though - I came up upon a large discussion about some (probably) similar software to "ours" and they were pasting keys left and right (though only 2 of them). That was from last year, yet it still works. The key is also present on the main page source itself (I discovered it while getting an error section on Sevastopol - I just wanted to know if the city was described as a disputed territory, LOL -, and found out that it's there even without any error anyway). My impression is that it's the very key used to display the data on the main page, available to all users (hence why I said it's not "hacked").
It's really not how we roll here in RainmeterLand. The combination of using that key, with a UserAgent string of "Rainmeter WebParser plugin" is enough to give us a bad name with their Web Master... We don't ever tell anyone what they should or shouldn't do to be good netizins, that's up to you and your karma. As a "project", we like to keep our noses clean, our pants pulled up, and our hats turned around the right way. If they meant for their API to be public, it wouldn't need a key. Scraping what the website returns to any user is more fair game, you can't complain that your neighbors saw your butt if you sunbath in your front yard.
User avatar
Yincognito
Posts: 1072
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: ⭐ weather.com - Parsing the JSON

Post by Yincognito »

jsmorley wrote:
February 9th, 2020, 12:44 am
Scraping what the website returns to any user is more fair game, you can't complain that your neighbors saw your butt if you sunbath in your front yard.
Apparently, not in the eyes of Google though, which is why they don't allow Chrome extensions to download YouTube videos. That's the main reason why I never registered or posted my image scraping extension on their WebStore, although it's good looking and vastly superior to others, querying up to various levels for linked images. I reserved it for my personal use (which is why I made it in the first place).

But as I said, I get what you mean, and I agree. Didn't know the WebParser "plugin" has its own UserAgent though. Nice!
User avatar
jsmorley
Developer
Posts: 20425
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: ⭐ weather.com - Parsing the JSON

Post by jsmorley »

I get the location information from here:

Code: Select all

"Location":{"language:en-US:locationType:locid:locid:USVA0944:1:US":{"loading":false,"loaded":true,"data":{"location":{"latitude":38.733,"longitude":-77.058,"city":null,"locale":{"locale1":null,"locale2":"Fort Hunt","locale3":null,"locale4":null},"neighborhood":null,"adminDistrict":"Virginia","adminDistrictCode":"VA","postalCode":"22308","postalKey":"22308:US","country":"United States of America","countryCode":"US","ianaTimeZone":"America\u002FNew_York","displayName":"Fort Hunt",
With:

Code: Select all

(?siU)"Location":{.*"latitude":(.*),.*"longitude":(.*),.*"adminDistrict":(.*),.*"adminDistrictCode":(.*),.*"country":(.*),.*"countryCode":(.*),.*"displayName":(.*),
So I'm getting the "first" adminDistrict, then country, then displayName.

If there is a more accurate or reliable way, I'm all ears... However, as I said, If it involves worrying about what kind of location code the user uses, I'm not interested. If at all possible, I want the same behavior if they use USVA0944, b48efc57780b9849d26b01c8abf4cc4e268471cb02e8054dfd9801206d2f9add, or 22308.

The only thing I have a high degree of confidence in is that there will always be a displayName.
User avatar
jsmorley
Developer
Posts: 20425
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: ⭐ weather.com - Parsing the JSON

Post by jsmorley »

Added the following two bits of information:

[@CurrentPrecipitationLast24Hours] : Use [@UnitsAccumulation]
[@CurrentSnowDepth] : Use [@UnitsAccumulation]

Might be of more interest if global warming ever lets it snow here...
User avatar
Yincognito
Posts: 1072
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: ⭐ weather.com - Parsing the JSON

Post by Yincognito »

jsmorley wrote:
February 9th, 2020, 1:22 am
I get the location information from here:

Code: Select all

"Location":{"language:en-US:locationType:locid:locid:USVA0944:1:US":{"loading":false,"loaded":true,"data":{"location":{"latitude":38.733,"longitude":-77.058,"city":null,"locale":{"locale1":null,"locale2":"Fort Hunt","locale3":null,"locale4":null},"neighborhood":null,"adminDistrict":"Virginia","adminDistrictCode":"VA","postalCode":"22308","postalKey":"22308:US","country":"United States of America","countryCode":"US","ianaTimeZone":"America\u002FNew_York","displayName":"Fort Hunt",
With:

Code: Select all

(?siU)"Location":{.*"latitude":(.*),.*"longitude":(.*),.*"adminDistrict":(.*),.*"adminDistrictCode":(.*),.*"country":(.*),.*"countryCode":(.*),.*"displayName":(.*),
So I'm getting the "first" adminDistrict, then country, then displayName.

If there is a more accurate or reliable way, I'm all ears... However, as I said, If it involves worrying about what kind of location code the user uses, I'm not interested. If at all possible, I want the same behavior if they use USVA0944, b48efc57780b9849d26b01c8abf4cc4e268471cb02e8054dfd9801206d2f9add, or 22308.
It has nothing to do with the location code or anything like that, don't worry (since the first regex below is capturing the same displayName).

I misunderstood when you said that you use displayName, then adminDistrict - I thought "then" implied that you captured adminDistrict after you captured displayName (which would have made the 2nd occurence of adminDistrict the one that got retrieved, hence the one that wasn't null in some of my tests).

Take this example of a source (it only happened to me once or twice, but it did happen nevertheless):

Code: Select all

"Location":{"language:en-GB:locationType:locid:locid:ROXX4613:1:RO":{"loading":false,"loaded":true,"data":{"location":{"latitude":47.95,"longitude":26.4,"city":null,"locale":{"locale1":null,"locale2":"Dorohoi","locale3":null,"locale4":null},"neighborhood":null,"adminDistrict":null,"adminDistrictCode":null,"postalCode":"715200","postalKey":"715200:RO","country":"Romania","countryCode":"RO","ianaTimeZone":"Europe\u002FBucharest","displayName":"Dorohoi","dstEnd":"2019-10-27T04:00:00+0200","dstStart":"2020-03-29T03:00:00+0300","dmaCd":null,"placeId":"308812117dc37d5579836cb12451d875f7d56d0f6110b0039d6f7dd92ca06004","disputedArea":false,"canonicalCityId":"de6a0e21dc1d414329278dfa9961435380b25b76a2cfeb7b7b6156364e9afcbb","countyId":null,"locId":"47.950\u002F26.400:29:RO","locationCategory":null,"pollenId":null,"pwsId":null,"regionalSatellite":"eur","tideId":null,"type":"locid","zoneId":"RO005"}},"ttl":86400,"date":1580559384000},"canonicalCityId:de6a0e21dc1d414329278dfa9961435380b25b76a2cfeb7b7b6156364e9afcbb:language:en-GB":{"loading":false,"loaded":true,"data":{"location":{"latitude":47.96,"longitude":26.4,"city":"Dorohoi","locale":{"locale1":null,"locale2":"Dorohoi","locale3":null,"locale4":null},"neighborhood":null,"adminDistrict":"Botoșani County","adminDistrictCode":null,"postalCode":"715200","postalKey":"715200:RO","country":"Romania","countryCode":"RO","ianaTimeZone":"Europe\u002FBucharest","displayName":"Dorohoi","dstEnd":"2019-10-27T04:00:00+0200","dstStart":"2020-03-29T03:00:00+0300","dmaCd":null,"placeId":"15bc0d7380e2eb48a62bf7775bf74c3d5e7239934fd863d0827a029a5433f320","disputedArea":false,"canonicalCityId":"de6a0e21dc1d414329278dfa9961435380b25b76a2cfeb7b7b6156364e9afcbb","countyId":null,"locId":null,"locationCategory":null,"pollenId":null,"pwsId":null,"regionalSatellite":"eur","tideId":null,"type":"city","zoneId":"RO005"}},"ttl":86400,"date":1580559385000}}
With the regex you posted and currently use, you'll get null as the value of adminDistrict, simply because you capture its first occurence (from the "language:..." subsection of "Location"). If, however, you "invert" the order of elements in your regex, placing displayName as the first capture instead of the last, you'll get the rest of the elements from the 2nd subsection of "Location" (i.e. the "canonicalCityId" one), and not the first. Now I could be wrong in that the 2nd subsection of "Location" is always the most complete, but so far in my tests, this has been the case.

So, your regex would be instead:

Code: Select all

(?siU)"Location":{.*"displayName":(.*),.*"latitude":(.*),.*"longitude":(.*),.*"adminDistrict":(.*),.*"adminDistrictCode":(.*),.*"country":(.*),.*"countryCode":(.*),
which would get the non-null value of adminDistrict (and of City, if you were to use it - but you don't because of your previously stated reasons). The only modification is cutting .*"displayName":(.*), from the end and placing it upfront.

Personally, given the fact that I included most of the parathesis in my regexes, I use something along these lines:

Code: Select all

(?siU)"Location":.*,".*":{.*{.*{.*"latitude":(.*),.*"longitude":(.*),.*"adminDistrict":(.*),.*"adminDistrictCode":(.*),.*"country":(.*),.*"countryCode":(.*),.*"displayName":(.*),
basically capturing the elements from the subsection of "Location" which comes after a comma (,). This has the same effect as the previous regex, in that it will get the elements from the 2nd subsection (the difference compared to the first regex is that it will also get the 2nd occurence of displayName). It can be also easily modified with a ? after the first * to get the elements from the last subsection of "Location", if in the future it somehow turns out that there are more than 2 subsections contained in "Location".

It's up to you which one of these you would prefer - if you prefer any, that is. Me, I don't like to have missing values in my skin, especially when the actual values do exist in the source.
jsmorley wrote:
February 9th, 2020, 2:43 am
Added the following two bits of information:

[@CurrentPrecipitationLast24Hours] : Use [@UnitsAccumulation]
[@CurrentSnowDepth] : Use [@UnitsAccumulation]

Might be of more interest if global warming ever lets it snow here...
I recently read in a TWC paper that the units for accumulation can be either mm (for rain) or cm (for snow) - so 2 alernative units -, for those employing a metric system. The "imperialists" have nothing to worry about, as they measure even their noses in inches. :D
User avatar
jsmorley
Developer
Posts: 20425
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: ⭐ weather.com - Parsing the JSON

Post by jsmorley »

Ok, I changed the order as you suggested. For my location, it works the same, but I will test with some others.
User avatar
jsmorley
Developer
Posts: 20425
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: ⭐ weather.com - Parsing the JSON

Post by jsmorley »

Yincognito wrote:
February 9th, 2020, 2:56 am
I recently read in a TWC paper that the units for accumulation can be either mm (for rain) or cm (for snow) - so 2 alernative units -, for those employing a metric system. The "imperialists" have nothing to worry about, as they measure even their noses in inches. :D
Ah right... It should be:

[@CurrentPrecipitationLast24Hours] : Use [@UnitsPrecipitation]
[@CurrentSnowDepth] : Use [@UnitsAccumulation]

I'll fix the docs...

Give me an inch, and I'll take a mile...


1.png

2.png
You do not have the required permissions to view the files attached to this post.
User avatar
Yincognito
Posts: 1072
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: ⭐ weather.com - Parsing the JSON

Post by Yincognito »

jsmorley wrote:
February 9th, 2020, 3:05 am
Ah right... It should be:

[@CurrentPrecipitationLast24Hours] : Use [@UnitsPrecipitation]
[@CurrentSnowDepth] : Use [@UnitsAccumulation]

I'll fix the docs...

Give me an inch, and I'll take a mile...
Yeah. And some docs that might be helpful:
- the icons and their description here
- the API usage (where I got the unit info from) here

EDIT: No, it's 2 units for Accumulation, not 1, in the case of the metric system. It's either mm if the precipType is "rain" (and probably the default "precip"), and cm if the type is "snow". At least that's how I understand it - correct me if I'm wrong. I know, even more trouble, LOL...

The TWC data and structure seem to be much more volatile and adaptive than the "old" wxdata one.
User avatar
jsmorley
Developer
Posts: 20425
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: ⭐ weather.com - Parsing the JSON

Post by jsmorley »

Yincognito wrote:
February 9th, 2020, 3:14 am
Yeah. And some docs that might be helpful:
- the icons and their description here
- the API usage (where I got the unit info from) here

EDIT: No, it's 2 units for Accumulation, not 1, in the case of the metric system. It's either mm if the precipType is "rain" (and probably the default "precip"), and cm if the type is "snow". At least that's how I understand it - correct me if I'm wrong. I know, even more trouble, LOL...

The TWC data and structure seem to be much more volatile and adaptive than the "old" wxdata one.
I don't think that is right. The "units" are static, based on your language code. I firmly believe that amount of rain is measured in @UnitsPrecipitation, and amount of snow is measured in @UnitsAccumulation.

Guess I'll find out for sure if it ever snows here.
User avatar
jsmorley
Developer
Posts: 20425
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: ⭐ weather.com - Parsing the JSON

Post by jsmorley »

You may be right now that I look at it.

If you get this information from each day/night "forecast":

"precipPct":10,"precipAmt":0,"precipType":"rain"

Then perhaps if precipType is "rain / precip" it is measured in @UnitsPrecipitation, and if precipType is "snow" is it measured in @UnitsAccumulation.
That's not going to be rocket-science to deal with with an IFMatch is this is the case.