/get_books_on_shelf.py
Forked from gpiancastelli/goodreads-oauth-example.py
Last active Nov 20, 2020
A Python example of how to use OAuth on GoodReads. Includes scripts to pull list of books that are on a shelf and to add all owned books to a shelf.
from string import Template | |
import oauth2 as oauth | |
import urlparse | |
import urllib | |
import time | |
import xml.dom.minidom | |
import sys, getopt | |
# If you get 'Title Messed Up By Unicode Error' messages try | |
# export PYTHONIOENCODING=utf-8 | |
url = 'http://www.goodreads.com' | |
target_list = 'holding' | |
consumer = oauth.Consumer(key='Your-GoodReads-Key', | |
secret='Your-GoodReads-Secret') | |
token = oauth.Token('oauth token key', | |
'oauth token secret') | |
client = oauth.Client(consumer, token) | |
############################# | |
# | |
# who are we? | |
# | |
def getUserId(): | |
response, content = client.request('%s/api/auth_user' % url,'GET') | |
if response['status'] != '200': | |
raise Exception('Cannot fetch resource: %s' % response['status']) | |
# else: | |
# print 'User loaded.' | |
userxml = xml.dom.minidom.parseString(content) | |
user_id = userxml.getElementsByTagName('user')[0].attributes['id'].value | |
return str(user_id) | |
############################# | |
# | |
# fetch xml for a page of books on a shelf | |
# | |
def getShelfBooks(page, shelf_name): | |
owned_template = Template('${base}/review/list?format=xml&v=2&id=${user_id}&sort=author&order=a&key=${dev_key}&page=${page}&per_page=100&shelf=${shelf_name}') | |
body = urllib.urlencode({}) | |
headers = {'content-type': 'application/x-www-form-urlencoded'} | |
request_url = owned_template.substitute(base=url, user_id=user_id, page=page, dev_key='gYPjS9uMjMC5CnWuSohlw', shelf_name=shelf_name) | |
response, content = client.request(request_url, 'GET', body, headers) | |
if response['status'] != '200': | |
raise Exception('Failure status: %s for page ' % response['status'] + page) | |
# else: | |
# print 'Page loaded!' | |
return content | |
############################# | |
# | |
# grab id and title from a <book> node | |
# | |
def getBookInfo(book): | |
book_id = book.getElementsByTagName('id')[0].firstChild.nodeValue | |
book_title = book.getElementsByTagName('title')[0].firstChild.nodeValue | |
return book_id, book_title | |
############################# | |
# | |
# grab id and title from a <book> node | |
# | |
def addBookToList(book_id, shelf_name): | |
body = urllib.urlencode({'name': shelf_name, 'book_id': book_id}) | |
headers = {'content-type': 'application/x-www-form-urlencoded'} | |
response, content = client.request('%s/shelf/add_to_shelf.xml' % url,'POST', body, headers) | |
if response['status'] != '201': | |
raise Exception('Failure status: %s' % response['status']) | |
# else: | |
# print 'Book added!' | |
return True | |
############################# | |
# | |
# loop over each page of owned books | |
# loop over each book | |
# add book to list | |
# | |
user_id = getUserId() | |
print 'User id is: ' + user_id | |
current_page = 0 | |
total_books = 0 | |
while True: | |
current_page = current_page + 1 | |
content = getShelfBooks(current_page, target_list) | |
xmldoc = xml.dom.minidom.parseString(content) | |
page_books = 0 | |
for book in xmldoc.getElementsByTagName('book'): | |
book_id , book_title = getBookInfo(book) | |
try: | |
print 'Book %10s : %s' % (str(book_id), book_title) | |
except UnicodeEncodeError: | |
print 'Book %10s : %s' % (str(book_id), 'Title Messed Up By Unicode Error') | |
page_books += 1 | |
total_books += 1 | |
# addBookToList(book_id, 'holding') | |
# time.sleep(1) | |
# addBookToList(book_id, target_list) | |
# time.sleep(1) | |
print 'Found ' + str(page_books) + ' books on page ' + str(current_page) + ' (total = ' + str(total_books) + ')' | |
time.sleep(1) | |
if (page_books == 0): | |
break; | |
############################# | |
# | |
# so much fun | |
# | |
print 'Found ' + str(total_books) | |
print 'Done.' | |
## END ## |
# oauth example for goodreads | |
# | |
# based on code found in https://gist.github.com/gpiancastelli/537923 by Giulio Piancastelli | |
# | |
# edit script with your dev key and secret | |
# run it | |
# visit the url | |
# confirm that you have accepted | |
# write down token! | |
# | |
import oauth2 as oauth | |
import urllib | |
import urlparse | |
url = 'http://www.goodreads.com' | |
request_token_url = '%s/oauth/request_token' % url | |
authorize_url = '%s/oauth/authorize' % url | |
access_token_url = '%s/oauth/access_token' % url | |
consumer = oauth.Consumer(key='Your-GoodReads-Key', | |
secret='Your-GoodReads-Secret') | |
client = oauth.Client(consumer) | |
response, content = client.request(request_token_url, 'GET') | |
if response['status'] != '200': | |
raise Exception('Invalid response: %s, content: ' % response['status'] + content) | |
request_token = dict(urlparse.parse_qsl(content)) | |
authorize_link = '%s?oauth_token=%s' % (authorize_url, | |
request_token['oauth_token']) | |
print "Use a browser to visit this link and accept your application:" | |
print authorize_link | |
accepted = 'n' | |
while accepted.lower() == 'n': | |
# you need to access the authorize_link via a browser, | |
# and proceed to manually authorize the consumer | |
accepted = raw_input('Have you authorized me? (y/n) ') | |
token = oauth.Token(request_token['oauth_token'], | |
request_token['oauth_token_secret']) | |
client = oauth.Client(consumer, token) | |
response, content = client.request(access_token_url, 'POST') | |
if response['status'] != '200': | |
raise Exception('Invalid response: %s' % response['status']) | |
access_token = dict(urlparse.parse_qsl(content)) | |
# this is the token you should save for future uses | |
print 'Save this for later: ' | |
print 'oauth token key: ' + access_token['oauth_token'] | |
print 'oauth token secret: ' + access_token['oauth_token_secret'] | |
token = oauth.Token(access_token['oauth_token'], | |
access_token['oauth_token_secret']) | |
# | |
# As an example, let's add a book to one of the user's shelves | |
# | |
add_to_list = False | |
def addABook(): | |
client = oauth.Client(consumer, token) | |
# the book is: "Generation A" by Douglas Coupland | |
body = urllib.urlencode({'name': 'to-read', 'book_id': 6801825}) | |
headers = {'content-type': 'application/x-www-form-urlencoded'} | |
response, content = client.request('%s/shelf/add_to_shelf.xml' % url, | |
'POST', body, headers) | |
# check that the new resource has been created | |
if response['status'] != '201': | |
raise Exception('Cannot create resource: %s' % response['status']) | |
else: | |
print 'Book added!' | |
if add_to_list: | |
addABook() | |
## END ## |
# | |
# I addded all my books to 'owned books' with the Quick Add. | |
# Since none of those books were on an actual shelf I could not export them. | |
# This script will move _all_ owned books to a shelf. | |
# | |
# Use goodreads-oauth-example.py to get an oauth token for your application. | |
# Fill in the consumer and token strings. | |
# Be sure to set target_list to the list you want to move _all_ your owned books onto. | |
# | |
from string import Template | |
import oauth2 as oauth | |
import urlparse | |
import urllib | |
import time | |
import xml.dom.minidom | |
import sys, getopt | |
# If you get 'Title Messed Up By Unicode Error' messages try | |
# export PYTHONIOENCODING=utf-8 | |
target_list = 'own' | |
consumer = oauth.Consumer(key='Your-GoodReads-Key', | |
secret='Your-GoodReads-Secret') | |
token = oauth.Token('oauth token key', | |
'oauth token secret') | |
client = oauth.Client(consumer, token) | |
url = 'http://www.goodreads.com' | |
############################# | |
# | |
# who are we? | |
# | |
def getUserId(): | |
response, content = client.request('%s/api/auth_user' % url,'GET') | |
if response['status'] != '200': | |
raise Exception('Cannot fetch resource: %s' % response['status']) | |
# else: | |
# print 'User loaded.' | |
userxml = xml.dom.minidom.parseString(content) | |
user_id = userxml.getElementsByTagName('user')[0].attributes['id'].value | |
return str(user_id) | |
############################# | |
# | |
# fetch xml for a page of owned books | |
# | |
def getOwnedBooks(page): | |
owned_template = Template('${base}/owned_books/user?format=xml&id=${user_id}&page=${page}&per_page=100') | |
body = urllib.urlencode({}) | |
headers = {'content-type': 'application/x-www-form-urlencoded'} | |
request_url = owned_template.substitute(base=url, user_id=user_id, page=page) | |
response, content = client.request(request_url, 'GET', body, headers) | |
if response['status'] != '200': | |
raise Exception('Failure status: %s for page ' % response['status'] + page) | |
# else: | |
# print 'Page loaded!' | |
return content | |
############################# | |
# | |
# grab id and title from a <book> node | |
# | |
def getBookInfo(book): | |
book_id = book.getElementsByTagName('id')[0].firstChild.nodeValue | |
book_title = book.getElementsByTagName('title')[0].firstChild.nodeValue | |
return book_id, book_title | |
############################# | |
# | |
# ask api to add a book to a shelf | |
# | |
def addBookToList(book_id, shelf_name): | |
body = urllib.urlencode({'name': shelf_name, 'book_id': book_id}) | |
headers = {'content-type': 'application/x-www-form-urlencoded'} | |
response, content = client.request('%s/shelf/add_to_shelf.xml' % url,'POST', body, headers) | |
if response['status'] != '201': | |
raise Exception('Failure status: %s' % response['status']) | |
# else: | |
# print 'Book added!' | |
return True | |
############################# | |
# | |
# loop over each page of owned books | |
# loop over each book | |
# add book to list | |
# | |
user_id = getUserId() | |
print 'User id is: ' + user_id | |
current_page = 0 | |
total_books = 0 | |
while True: | |
current_page = current_page + 1 | |
content = getOwnedBooks(current_page) | |
xmldoc = xml.dom.minidom.parseString(content) | |
page_books = 0 | |
for book in xmldoc.getElementsByTagName('book'): | |
book_id , book_title = getBookInfo(book) | |
try: | |
print 'Book %10s : %s' % (str(book_id), book_title) | |
except UnicodeEncodeError: | |
print 'Book %10s : %s' % (str(book_id), 'Title Messed Up By Unicode Error') | |
page_books += 1 | |
total_books += 1 | |
addBookToList(book_id, target_list) | |
time.sleep(1) | |
print 'Found ' + str(page_books) + ' books on page ' + str(current_page) + ' (total = ' + str(total_books) + ')' | |
time.sleep(1) | |
if (page_books == 0): | |
break; | |
############################# | |
# | |
# so much fun | |
# | |
print 'Found ' + str(total_books) | |
print 'Done.' | |
## END ## |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
For those of you who are getting a 301 response when running the file
goodreads-oauth-example.py
, replacehttp
withhttps
in the url of Goodreads :)