I have been using this snippet for the authentication on Google Reader and get the unread list, but it had been failing for a while. It turned out SID (Session ID) authentication is not allowed anymore, it had been announced and it effected recently.
Now, you will need to get the Auth token, which is exactly same as you get the SID. But you will have to include service=reader in your request data or you will only get SID and LSID. I think this new Auth token might be issued by per service base.
Here is my final script:
#!/usr/bin/env python from xml.dom import minidom from xml.dom import EMPTY_NAMESPACE try: import json except ImportError: import simplejson as json import urllib import urllib2 username = 'user@gmail.com' password = '***SECRET***' # Authenticate to obtain Auth auth_url = 'https://www.google.com/accounts/ClientLogin' auth_req_data = urllib.urlencode({ 'Email': username, 'Passwd': password, 'service': 'reader' }) auth_req = urllib2.Request(auth_url, data=auth_req_data) auth_resp = urllib2.urlopen(auth_req) auth_resp_content = auth_resp.read() auth_resp_dict = dict(x.split('=') for x in auth_resp_content.split('\n') if x) AUTH = auth_resp_dict["Auth"] # Create a cookie in the header using the Auth header = {'Authorization': 'GoogleLogin auth=%s' % AUTH} #################################### ### PART 1: Getting unread count ### #################################### reader_base_url = 'http://www.google.com/reader/api/0/unread-count?%s' reader_req_data = urllib.urlencode({ 'all': 'true', 'output': 'json'}) reader_url = reader_base_url % (reader_req_data) reader_req = urllib2.Request(reader_url, None, header) reader_resp = urllib2.urlopen(reader_req) #reader_resp_content = reader_resp.read() #j = json.loads(reader_resp_content) j = json.load(reader_resp) count = ([c['count'] for c in j['unreadcounts'] if c['id'].endswith('/state/com.google/reading-list')] or [0])[0] if count: print 'Unread: %d' % count else: print 'No unread items.' ################################### ### PART 2: Getting unread list ### ################################### if count: ATOM_NS = 'http://www.w3.org/2005/Atom' reader_base_url = r'http://www.google.com/reader/atom/user%2F-%2Fstate%2Fcom.google%2freading-list?n=50' reader_url = reader_base_url reader_req = urllib2.Request(reader_url, None, header) reader_resp = urllib2.urlopen(reader_req) doc = minidom.parse(reader_resp) doc.normalize() for entry in doc.getElementsByTagNameNS(ATOM_NS, u'entry'): title = entry.getElementsByTagNameNS(ATOM_NS, u'title')[0].firstChild.data if [True for cat in entry.getElementsByTagNameNS(ATOM_NS, u'category') if cat.getAttributeNS(EMPTY_NAMESPACE, u'term').endswith('/state/com.google/read')]: continue print title
It does two tasks: 1) it get the unread count, and 2) it lists the unread items.
For the first task, we request a JSON format, using JSON is easier than XML format, or say JSON library is easier to use than the xml.minidom. The returned data contains many type of unread counts, you will need to find the one’s ID ends with /state/com.google/reading-list.
The second task, there is no output=json option, so XML is. The returned Atom entries will also contain read items, you need to filter them out by checking if there is a category‘s term ends with /state/com.google/read, which indicates the item is read or mark as read. Since, the entries contain read items, therefore if you have more than 50 unread items (there is a n=50 in request URL), the script may not print out 50 items.
Great post! Pointed me in the right direction to fix my script now the auth requirements differ from the previously working cookie based auth. Cheers!
ReplyDelete