Oct 032014
 

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)…

Console Screen Colours from the above codes

Console Screen Colours from the above codes

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('/')[5].split('-')[0] # 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('"')[5][:-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[1])
                    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[1]) * 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[1])
        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.

ks3.py KickStarter Tracker output

ks3.py KickStarter Tracker output

For a standalone KickStarter monitor, this is now working quite well. But obviously we could take it a lot further.

What Next?

We could incorporate…

  • tweeting
  • 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.

  7 Responses to “Programming a KickStarter Tracker in Python. Part 2.”

  1. AndrewS’s Python Tips ™ ;-)

    There’s a bit more about escape sequences in the “Make the output even more amusing” section of http://www.raspberrypi.org/learning/fart-detector/WORKSHEET.md
    You could also use the idea used there of using string-formatting to make your code slightly easier to read, by separating the formatting-codes from the text you’re actually displaying… (separating the ‘content’ from the ‘presentation’ is a very common programming paradigm)

    Strictly speaking, if you’re declaring “coding: utf-8” then you need to ensure your editor is saving in UTF-8 format too.

    IMHO you ought to make ‘someurl’ a parameter of the ‘scan’ function, rather than leaving it as a global variable. You could then change the last section of your code to:

    ks_urls = (
        'https://www.kickstarter.com/projects/pisupply/gert-vga-666-kit-hardware-vga-for-raspberry-pi',
        'https://www.kickstarter.com/projects/955730101/protocam-the-raspberry-pi-camera-module-prototypin',
        'https://www.kickstarter.com/projects/1059145052/mypifi-lcd-board-support'
    )
    while True:
        for ks in ks_urls:
            scan(ks)
            sleep(15)
    

    Another enhancement could be to display “Finished” if the time left is 0 seconds. And then you could get fancy and display the “Finished” in red or green text, depending on whether the project reached its target. :)

    • All good tips. Thanks Andrew.

      Putting the URLS in a list is much tidier. Had thought about doing it that way, but there was a short supply of round tuits and I hadn’t got one yet ;p

      My text editor is set to UTF-8 (TextWrangler for Mac), but good you mentioned that.

  2. […] is currently running a series on programming a Kickstarter tracker script on the Pi using Python. He’s just published part 2. Part 1 can be found […]

  3. hehe, this reminds me of when i was working with ASIC(actual compiled modes of BASIC, kinda GWBASIC)…le…sigh..

  4. i also remember trying to write to memory C800 in the old CGA days….wow…

  5. […] never done graphing on the Pi or in Python before, but for my KickStarter tracker I wanted something […]

Leave a Reply