Skip to content

Instantly share code, notes, and snippets.

@jmoy
Created February 25, 2011 04:56
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 jmoy/843376 to your computer and use it in GitHub Desktop.
Save jmoy/843376 to your computer and use it in GitHub Desktop.
Get Wikipedia watchlist as an RSS/ATOM feed
"""Get Wikipedia watchlist as an RSS/ATOM feed
(c) Jyotirmoy Bhattacharya, 2007
Usage: wikiwatch <username> <password> [format]
[format] is either 'rss' or 'atom'
"""
import sys
import xml.sax,xml.sax.handler
import urllib,urllib2,cookielib,httplib
#Constants
version="0.2alpha"
user_agent="wikiwatch.py (jmoy.matecon@gmail.com)/"+version
usage="Usage: wikiwatch <Username> <Password> [rss/atom]"
apiURL="http://en.wikipedia.org/w/api.php"
class LoginFailedException(Exception):
"""Login to Wikipedia failed
"""
def __init__(self,status):
self.message=status
class RunTimeError(Exception):
"""Run-time error
"""
def __init__(self,what):
self.message=what
class BadCmdException(Exception):
"""Bad command-line arguments to program
"""
def __init__(self):
self.message="Bad command-line argument"
def callapi(data,cookie_jar):
"""Make an API call
data: list of tuples containing data to be sent in the PUT request
cookie_jar: cookielib.CookieJar used for the request
Returns a file-like object containing the response
"""
opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie_jar))
req=urllib2.Request(apiURL,urllib.urlencode(data))
req.add_header("User-Agent",user_agent)
return opener.open(req)
def wikiauth(uname,passwd,cookie_jar):
"""Authenticate to Wikipedia and return authentication tokens as cookies
uname: Wikipedia username
passwd: Wikipedia password
cookie_jar: cookielib.CookieJar to store authentication cookies
Returns nothing
Raises LoginFailedException in case of failure
"""
class LoginResp(xml.sax.ContentHandler):
def __init__(self):
self.result=""
def startElement(self,name,attrs):
if name=="login":
self.result=attrs["result"]
try:
#Create SAX parser
parser=xml.sax.make_parser()
parser.setFeature(xml.sax.handler.feature_namespaces,0)
lr=LoginResp()
parser.setContentHandler(lr)
#Get login response
r=callapi([("action","login"),
("format","xml"),
("lgname",uname),
("lgpassword",passwd)],
cookie_jar)
#Parse login response to get tokens and see if login succeeded
parser.parse(r)
if lr.result!="Success":
raise LoginFailedException("Authentication denied: "+lr.result)
pass
except xml.sax.SAXException,inst:
raise LoginFailedException("Parse error in login response: "
+inst.getMessage())
def getfeed(uname,passwd,feedformat):
"""Get Wikipedia watchlist feed
uname: Wikipedia username
passwd: Wikipedia password
feedformat: format of the feed, must be 'rss' or 'atom'
Returns a file-like object containing the feed
"""
jar=cookielib.CookieJar()
wikiauth(uname,passwd,jar)
return callapi([("action","feedwatchlist"),
("feedformat",feedformat)],
jar)
def do_fetch(argv):
"""Parse command-line arguments and fetch feed
argv: list of command-line arguments
Returns feed as a string
Raises BadCmdException if arguments are not proper
"""
format="atom"
if len(argv)==3:
pass
elif len(argv)==4:
if (argv[3]=="rss" or argv[3]=="atom"):
format=argv[3]
else:
raise BadCmdException()
else:
raise BadCmdException()
try:
r=getfeed(argv[1],argv[2],format)
return r.read()
except httplib.HTTPException,inst:
raise RunTimeError("httplib Exception: "+str(inst))
except urllib2.URLError, inst:
raise RunTimeError("urllib Exception: "+str(inst.reason))
#Main program
if __name__=="__main__":
try:
print do_fetch(sys.argv)
except BadCmdException:
sys.stderr.write("%s\n"%usage)
sys.exit(1)
except LoginFailedException,inst:
sys.stderr.write("Login failed: %s\n"%inst.message)
sys.exit(2)
except RunTimeError, inst:
sys.stderr.write("Runtime error: %s\n"%inst.message)
sys.exit(2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment