Skip to content

Instantly share code, notes, and snippets.

@VerizonMediaOwner
Last active September 19, 2020 12:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save VerizonMediaOwner/e6be950f74c5a8071329f1d9a50e3158 to your computer and use it in GitHub Desktop.
Save VerizonMediaOwner/e6be950f74c5a8071329f1d9a50e3158 to your computer and use it in GitHub Desktop.
Yahoo Weather API Python Sample.
"""
Weather API Python sample code
Copyright 2019 Oath Inc. Licensed under the terms of the zLib license see https://opensource.org/licenses/Zlib for terms.
$ python --version
Python 2.7.10
"""
import time, uuid, urllib, urllib2
import hmac, hashlib
from base64 import b64encode
"""
Basic info
"""
url = 'https://weather-ydn-yql.media.yahoo.com/forecastrss'
method = 'GET'
app_id = 'your-app-id'
consumer_key = 'your-consumer-key'
consumer_secret = 'your-consumer-secret'
concat = '&'
query = {'location': 'sunnyvale,ca', 'format': 'json'}
oauth = {
'oauth_consumer_key': consumer_key,
'oauth_nonce': uuid.uuid4().hex,
'oauth_signature_method': 'HMAC-SHA1',
'oauth_timestamp': str(int(time.time())),
'oauth_version': '1.0'
}
"""
Prepare signature string (merge all params and SORT them)
"""
merged_params = query.copy()
merged_params.update(oauth)
sorted_params = [k + '=' + urllib.quote(merged_params[k], safe='') for k in sorted(merged_params.keys())]
signature_base_str = method + concat + urllib.quote(url, safe='') + concat + urllib.quote(concat.join(sorted_params), safe='')
"""
Generate signature
"""
composite_key = urllib.quote(consumer_secret, safe='') + concat
oauth_signature = b64encode(hmac.new(composite_key, signature_base_str, hashlib.sha1).digest())
"""
Prepare Authorization header
"""
oauth['oauth_signature'] = oauth_signature
auth_header = 'OAuth ' + ', '.join(['{}="{}"'.format(k,v) for k,v in oauth.iteritems()])
"""
Send request
"""
url = url + '?' + urllib.urlencode(query)
request = urllib2.Request(url)
request.add_header('Authorization', auth_header)
request.add_header('X-Yahoo-App-Id', app_id)
response = urllib2.urlopen(request).read()
print(response)
@louisfox
Copy link

louisfox commented Mar 13, 2019

"""
Weather API Python sample code
Copyright 2019 Oath Inc. Licensed under the terms of the zLib license see https://opensource.org/licenses/Zlib for terms.
$ python --version
Python 3.7.x
"""

import time, uuid, urllib, json
import hmac, hashlib
from base64 import b64encode

Basic info

app_id = 'your-app-id'
consumer_key = 'your-consumer-key'
consumer_secret = 'your-consumer-secret'
query = {'location': 'macau,mo', 'format': 'json', 'u': 'c'}

url = 'https://weather-ydn-yql.media.yahoo.com/forecastrss'
method = 'GET'

concat = '&'

oauth = {
'oauth_consumer_key': consumer_key,
'oauth_nonce': uuid.uuid4().hex,
'oauth_signature_method': 'HMAC-SHA1',
'oauth_timestamp': str(int(time.time())),
'oauth_version': '1.0'
}

Prepare signature string (merge all params and SORT them)

merged_params = query.copy()
merged_params.update(oauth)
sorted_params = [k + '=' + urllib.parse.quote(merged_params[k], safe='') for k in sorted(merged_params.keys())]
signature_base_str = method + concat + urllib.parse.quote(url, safe='') + concat + urllib.parse.quote(concat.join(sorted_params), safe='')

Generate signature

composite_key = urllib.parse.quote(consumer_secret, safe='') + concat
oauth_signature = b64encode(hmac.new(composite_key.encode('utf-8'), signature_base_str.encode('utf-8'), hashlib.sha1).digest())

Prepare Authorization header

oauth['oauth_signature'] = oauth_signature.decode('utf-8')
auth_header = 'OAuth ' + ', '.join(['{}="{}"'.format(k,v) for k,v in oauth.items()])

Send request

url = url + '?' + urllib.parse.urlencode(query)

request = urllib.request.Request(url)
request.headers['Authorization'] = auth_header
request.headers['X-Yahoo-App-Id']= app_id

response = urllib.request.urlopen(request).read()
print(response)

@acadkins327
Copy link

I am using Python 3.5.3 and receive the following error when running the update:

request = urllib.request.Request(url)
AttributeError: module 'urllib' has no attribute 'request'

The Python 2 version runs fine on my 2.7.13

Advise?

Best regards,

@acadkins327
Copy link

Found that using Python 3.5.3 on a Raspberry Pi required changing the 3.7 code from 'import urllib' to 'import urllib.request'. The sample then runs just fine.

@ubdussamad
Copy link

ubdussamad commented Jul 30, 2019

This is a non generic version of this code in python3:

import time, uuid , json
import urllib.request
import hmac, hashlib
from base64 import b64encode

class yahoo_api ( object ):
    def __init__ ( self ):
        self.consumer_secret = 'Your secret key'
        self.url = 'https://weather-ydn-yql.media.yahoo.com/forecastrss'
        self.method = 'GET'
        self.app_id = 'Your App Id'
        self.consumer_key = 'Your consumer key'
        self.concat = '&'        
    def process(self):
        #Prepare signature string (merge all params and SORT them
        merged_params = self.query.copy()
        merged_params.update(self.oauth)
        sorted_params = [k + '=' + urllib.parse.quote(merged_params[k], safe='') for k in sorted(merged_params.keys())]
        signature_base_str =  self.method + self.concat + urllib.parse.quote(self.url, safe='') + self.concat + urllib.parse.quote(self.concat.join(sorted_params), safe='')
        #Generate signature
        composite_key = urllib.parse.quote(self.consumer_secret, safe='') + self.concat
        oauth_signature = b64encode(hmac.new( bytes(composite_key , 'latin-1') , bytes(signature_base_str,'latin-1'), hashlib.sha1).digest())
        oauth_signature = oauth_signature.decode('utf-8')
        #Prepare Authorization header
        self.oauth['oauth_signature'] = oauth_signature
        auth_header = 'OAuth ' + ', '.join(['{}="{}"'.format(k,v) for k,v in self.oauth.items()])
        #Send request
        self.url = self.url + '?' + urllib.parse.urlencode(self.query)
        opener = urllib.request.build_opener()
        opener.addheaders = [('Authorization', auth_header),
                             ('X-Yahoo-App-Id', self.app_id),
                             ('Pragma', 'no-cache'),
                             ('User-Agent', 'Mozilla/5.0')]
        urllib.request.install_opener(opener)
        response = urllib.request.urlopen(self.url)
        data = response.read().decode('utf-8')
        del response
        del opener
        target = json.loads(data)
        return(target)

    def query_(self , location , unit = 'c'):
        # Location is the name of location (e.g. Moscow) , unit is the temp unit (C or F)
        # Returns a dictionary of weather data
        self.query = {'location': location, 'format': 'json' , 'u' : unit}
        self.url = 'https://weather-ydn-yql.media.yahoo.com/forecastrss'
        self.oauth = {
        'oauth_consumer_key': self.consumer_key,
        'oauth_nonce': uuid.uuid4().hex,
        'oauth_signature_method': 'HMAC-SHA1',
        'oauth_timestamp': str(int(time.time())),
        'oauth_version': '1.0'
        }
        return(self.process())

if __name__ == "__main__":
    obj = yahoo_api()
    data = obj.query_("Moscow")
    print(data)

@GrantBirki
Copy link

hey @ubdussamad, I copied your code exactly the way it is and then just added in my credentials and I'm getting an error. Traceback (most recent call last): File "c:/Python/IoT-Weather-Bot/weathertest.py", line 63, in <module> data = obj.query_("Moscow") File "c:/Python/IoT-Weather-Bot/weathertest.py", line 59, in query_ return(self.process()) File "c:/Python/IoT-Weather-Bot/weathertest.py", line 40, in process response = urllib.request.urlopen(self.url) File "C:\Users\Birki\AppData\Local\Programs\Python\Python37-32\lib\urllib\request.py", line 222, in urlopen return opener.open(url, data, timeout) File "C:\Users\Birki\AppData\Local\Programs\Python\Python37-32\lib\urllib\request.py", line 525, in open response = self._open(req, data) File "C:\Users\Birki\AppData\Local\Programs\Python\Python37-32\lib\urllib\request.py", line 543, in _open '_open', req) File "C:\Users\Birki\AppData\Local\Programs\Python\Python37-32\lib\urllib\request.py", line 503, in _call_chain result = func(*args) File "C:\Users\Birki\AppData\Local\Programs\Python\Python37-32\lib\urllib\request.py", line 1360, in https_open context=self._context, check_hostname=self._check_hostname) File "C:\Users\Birki\AppData\Local\Programs\Python\Python37-32\lib\urllib\request.py", line 1317, in do_open encode_chunked=req.has_header('Transfer-encoding')) File "C:\Users\Birki\AppData\Local\Programs\Python\Python37-32\lib\http\client.py", line 1244, in request self._send_request(method, url, body, headers, encode_chunked) File "C:\Users\Birki\AppData\Local\Programs\Python\Python37-32\lib\http\client.py", line 1285, in _send_request self.putheader(hdr, value) File "C:\Users\Birki\AppData\Local\Programs\Python\Python37-32\lib\http\client.py", line 1221, in putheader if _is_illegal_header_value(values[i]): TypeError: expected string or bytes-like object

Any idea why this might be?

@ubdussamad
Copy link

ubdussamad commented Aug 8, 2019

Hi @GrantBirki , I tested my code again and it works on my machine. (Python 3.5.2 & Python 3.7 [GCC 5.4.0 20160609] on linux). My best guess analyzing the error would be that your header is somehow messed up, maybe some text with illegal characters or the whole header is a different object or something.
What python version are you using? Plus if you could double check your credentials for any unintended white space or something maybe?
(usage of keyring might be the cause, have your tried pasting the credential values itself?)

@GrantBirki
Copy link

@ubdussamad I took another look at my code and it looks like if I just use the yahoo pypi library I can authenticate with the credentials using keyring so that shouldn't be causing any issues. I also just printed the strings to standard output and did not see any whitespace or illegal characters. This is leading me to believe that the user agent is causing issues. I haven't done too many web requests in python. My system is running python 3.7 on windows but the desired goal is to run this script on a linux OS so I'm not 100% sure what user agent to be using but I will do some research. I will comment below if I find a solution to get the script running. Thanks!!

@GrantBirki
Copy link

@ubdussamad I had accidentally misclicked a "h" in my keyring import so it wasn't grabbing the secret key. Works flawlessly now. Thanks! 😄

@ubdussamad
Copy link

@GrantBirki Well, it's good that it worked out. That's why I don't use key rings for projects since they add extra margin of error. :) But sometimes it's just nessasary. I forgot the snippet can be considered under MIT licence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment