Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Python

Tracking Olympic Medals with the Raspberry Pi

0.00/5 (No votes)
20 Feb 2014CPOL3 min read 6.6K  
A quick hack to display the current medal count from the winter Olympics using a Raspberry Pi and a 7-segment display.

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.

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.

Medal Count Display

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:

Medal Count HTML

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:

C#
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 strings.

C#
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 strings 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.

C#
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?

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)