So this is part 2 of the KickStarter Tracker in Python. (If you’ve not seen part 1 yet, that’s here.)
We got the basics working last time. Now we want to make it look nicer, add more campaigns and have it running continously. So first let’s see about how we can introduce some colour…
Adding Colour To Console Output
There may well be more elegant ways to get the job done here, but I found a way that uses what’s called “escape sequences”. These are basically codes which can be used to modify the characteristics of console output. For example…
\033[1mBold\033[0m would print Bold
\033[1m is the code for “Bold On” and
\033[0m is the code for “all attributes off” i.e. normal text. So we use this at the end of each line.
Here are some of the escape sequences for modifying text on your console output…
print """ \033[0mAll attributes off\033[0m \033[1mBold\033[0m \033[4mUnderline\033[0m # underline doesn't seem to work \033[5mBlink\033[0m \033[8mHide\033[0m \033[30mBlack\033[0m \033[31mRed\033[0m \033[32mGreen\033[0m \033[33mYellow\033[0m \033[34mBlue\033[0m \033[35mMagenta\033[0m \033[36mCyan\033[0m \033[37mWhite\033[0m \033[40m\033[37mBlack Background\033[0m \033[41mRed Background\033[0m \033[42mGreen Background\033[0m \033[43mYellow Background\033[0m \033[44mBlue Background\033[0m \033[1m\033[44mBold White Text with Blue Background\033[0m \033[45mMagenta Background\033[0m \033[46mCyan Background\033[0m \033[47mWhite Background\033[0m \033[30m\033[47mBlack text with White Background\033[0m \033[33m\033[44mYellow Text with Blue Background\033[0m \033[1m\033[33m\033[44mBold Yellow Text with Blue Background\033[0m """
And here’s the output of this on the screen (although yellow seems to have gone a bit ‘wonky’ and only works when bolded)…
The disadvantage of using these escape sequences is that they make it very difficult to read your code. So I recommend this is the last thing you do. Get your code working first, then think about making it look pretty.
I Want A £ Sign
I’ve never tried to display financials in a Python script before. When trying to use a £ in my script, I kept getting an error…
SyntaxError: Non-ASCII character '\xc2' in file test.py on line 1, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
It turns out that to use Non-ASCII characters, like the £, you have to specify the character set you are using. A good one is utf-8. So we’ll use that. We need to place the following code as either first or second line in our script.
# -*- coding: utf-8 -*-
So that gives us colours and £ to make things look more interesting.
Adding More Campaigns And Looping
Now we’ve got our code working AND looking pretty with colours, bolds and £, we need to make it work for more than one campaign. This is relatively easy if we dump pretty much all the code we wrote so far into a function. Then we can call this function for each of the campaign URLs that we want to monitor.
In the below code, lines 7-45 define our function
We’ve imported ‘sleep’ in line 4 so we can have a time delay between readings
In lines 20-24 we used the splitting/slicing technique to get the project title from the URL
In line 48 we have a loop which will go on forever, cycling through our chosen campaign URLs with a 15s wait in between.
So here’s the full code (updated 17 Jan 2015). I called it ks3.py…
#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- from urllib2 import Request, urlopen, URLError from time import sleep # we need sleep for a delay between readings pc='%' # I find defining % as a variable avoids confusion def scan(): # we've put all the page scanning bits into a function req = Request(someurl) try: response = urlopen(req) except URLError as e: if hasattr(e, 'reason'): print 'We failed to reach a server.' print 'Reason: ', e.reason elif hasattr(e, 'code'): print 'The server couldn\'t fulfill the request.' print 'Error code: ', e.code else: the_page = response.readlines() project_name = someurl.split('/').split('-') # take project name from URL print '\033[34m\033[1m' + project_name + '\033[0m' # bold and blue title for line in the_page: if 'data-duration' in line: # line 457 time_left = float(line.split('"')[:-2]) if time_left >= 24: time_left_unit = "days" time_left = str(int(time_left / 24)) else: time_left_unit = "hours" time_left = str(time_left) if 'data-goal' in line: # line 449 words = line.split(" ") for word in words: if 'data-goal' in word: target = word.split('"') # bold and yellow for labels, bold and white for figures print '\033[33m\033[1mtarget:\033[0m \033[1m\033[37m£%.2f\033[0m' % float(target) if 'data-percent-raised' in word: percent = word.split('"') print '\033[33m\033[1mpercentage raised:\033[0m \033[1m\033[37m%.2f%s\033[0m' % ((float(percent) * 100) , pc) if 'data-pledged' in word: amount_raised = word.split('"') print '\033[33m\033[1mTotal so far:\033[0m \033[1m\033[37m£%.2f\033[0m' % float(amount_raised) print '\033[33m\033[1mTime left:\033[0m \033[1m\033[37m%s %s\033[0m \n' % (time_left, time_left_unit) # Now we'll have a continuous loop which calls our function for each URL we define while True: someurl= 'https://www.kickstarter.com/projects/raspitv/raspio-duino-affordable-arduino-programming-on-ras' scan() sleep(15)
What Does The Output Look Like Now?
I think it looks much nicer, and you now have a continous, rolling update of each of the campaigns you’re tracking.
For a standalone KickStarter monitor, this is now working quite well. But obviously we could take it a lot further.
We could incorporate…
- hourly push notifications to a phone
- logging and prediction (something like a personal KickTraq)
- milestone notifications (a tweet every £10k or 5%)
The possibilities are limited only by our imagination and resources. We’ll see how it goes. Maybe there will be a part 3 in due course? I already have hourly push notifications to my Nexus 5/7 working and running from a Cron job.