I’m not sure why I waited so long to do this now that the Olympics are coming to an end. The thought came to me today, “I wonder how long it would take me to hack together a script to track and display medal counts.” Well, I had to find out and below is the result.
Disclaimer: I was not going for neat, well-organized code here. I was going for speed, so please be gentle.
The Platform
I cheated a little bit in that I already had the Pi configured and some hardware ready to go from my Skillshare Class (which is now free if you want to check it out) so I figured I’d just use what I already had. The project from the Skillshare class includes an LED, temperature sensor, and other things but all I really needed for this project was the seven segment display from Sparkfun. I was ready to immediately start coding in Python.
The Data Feed
My first step was to find a suitable data source for the medal count. It really came down to two sources and how easy it would be to parse the data. The first was NBC and the second was the official Sochi Olympics site. I liked the official site a little better because the HTML for the medals had specific CSS classes that would make extracting the data very straightforward. The problem I ran into though was when I ran my initial version of the script I got a Forbidden response.
I assume this has something to do with the Agent header and them trying to prevent people like me from mooching off their site. Well played sochi.ru, well played. Fortunately for us, the good folks at NBC do not have the same concern so that’s where I ended up getting the data. Here is what part of the page looks like and has a url of http://www.nbcolympics.com/medals.
So how do we fetch just the medal counts that we want to display? Well, in Chrome, all we have to do is right-click on the text “United States of America” and do Inspect Element to expose the page HTML which looks like this:
This was my first time parsing HTML in Python so there are probably much better ways to do this. If so, please tell me about it in the comments so I can learn something new. I chose to use some simple XPATH to locate the anchor element with the country name and then navigate to the neighboring elements with the medal counts in them. The result was this:
page = urllib.urlopen("http://www.nbcolympics.com/medals").read()
html = lxml.html.fromstring(page)
result = html.xpath('//a[text()=" United States of America"]/@href')
nameNode = result[0].getparent().getparent()
goldNode = nameNode.getnext()
silverNode = goldNode.getnext()
bronzeNode = silverNode.getnext()
Getting the actual integer value of the medal counts was then trivial. Remember, parsing out of the HTML will give you the values in string
s.
gold_count = int(goldNode.text_content().strip())
silver_count = int(silverNode.text_content().strip())
bronze_count = int(bronzeNode.text_content().strip()
Displaying the Data
With the data in hand, it was just a matter of getting it onto the 7 segment display. In my Skillshare class, I show how to configure and use SPI on the Pi to display stuff on a simple seven segment display so I already had all of the code for that. I just needed to format the display string appropriately. As my real estate was limited, I decided to just use simple string
s like “to:23
” for the total count, “go:14
” for gold, etc. I display each count 3 times and then query NBC again for an updated count. The interval could be much greater I suppose as medals don’t change every 10 seconds.
def display_medal_counts(bus, gold, silver, bronze):
total = gold + silver + bronze
totalstr = "to" + str(total)
goldstr = "go" + str(gold)
silverstr = "si" + str(silver)
bronzestr = "br" + str(bronze)
for i in range(3):
clear_display(bus)
spi_send(bus, totalstr)
spi_send(bus, [0x77, 0x10])
sleep(4)
clear_display(bus)
spi_send(bus, goldstr)
spi_send(bus, [0x77, 0x10])
sleep(4)
clear_display(bus)
spi_send(bus, silverstr)
spi_send(bus, [0x77, 0x10])
sleep(4)
clear_display(bus)
spi_send(bus, bronzestr)
spi_send(bus, [0x77, 0x10])
sleep(4)
Wrap Up
Throwing this together took me a little over an hour, much of which was spent learning how to parse HTML in Python. It’s a great example of how the Raspberry Pi is great for rapid prototyping of an idea.
The full code can be found in this gist. To view the original post and a Vine showing it working, head over to the source on The µBlog.
What Olympic-themed hardware projects can you think of?