Trivia Time!
LAB18

trivia.jpg

Welcome

They say there are a few things that bring people together. Among these are food and trivia games.

Why not make a trivia game of your own? You can! And guess what? You don’t have to create your own questions. There are APIs out there with questions and answers that you can pull in to your own apps. In this lab, we’ll see how that’s done.

What We Will Learn

APIs JSON HTTP Requests The requests package

Activity

As always, make sure you are in your virtual environment. Install the requests library with:

  pip install requests

Create the file ~/cmsi1010/lab18/trivia.py. Prime it with the following skeleton code that fetches a random multiple-choice question from the Open Trivia Database:

import requests
url = "https://opentdb.com/api.php?amount=1&type=multiple&encode=url3986"
response = requests.get(url)
if response.status_code != 200:
    raise ValueError(f'API error: {response.status_code}')
body = response.json()
print(body)

Here we used the get function from the requests module to programmatically do the same thing your web browser would do if you’d typed that url in to the browser yourself. When you make that GET request, the server (yep, it’s called a server) responds with a status code. You want a 200 because that means OK. (If you are interested, check out this full list of response status codes.)

Exercise: Browse the list of response codes. Make note of 200, 201, 401, 403, 404, 410, 418, 420, 451, and 500. What do they mean? Why are they important?

When running this program, you’ll either get an error response or a response containing a random question such as this one:

{
  'response_code': 0,
  'results': [
    {
      'type': 'multiple',
      'difficulty': 'medium',
      'category': 'History',
      'question': 'What%20was%20the%20total%20length%20of%20the%20Titanic%3F',
      'correct_answer': '882%20ft%20%7C%20268.8%20m',
      'incorrect_answers': [
        '759%20ft%20%7C%20231.3%20m',
        '1042%20ft%20%7C%20317.6%20m',
        '825%20ft%20%7C%20251.5%20m'
      ]
    }
  ]
}

Hey, that is a Python dictionary! The server actually responded with a big string in JSON format, which we turned into a dictionary when we called response.json(). So what’s in this dictionary? That’s explained in the Open Trivia Database’s API documentation, but here’s a quick summary:

That looks kinda ugly and weird

The Open Trivia Database API is convenient and completely free! But ngl, its weirder and uglier than most public APIs. First it requires some encoding that most APIs do not—like why the heck to we have to specify url3986 and why are there so many weird characters in the response? Furthermore the fact there is a response_code in the response itself is super confusing because the web protocol (HTTPS) has its own response code.

I’m thinking of finding a better API for the future. But maybe this quirkiness builds character. I dunno.

Unfortunately, this API encodes its text responses, something that is not necessary in modern APIs, 99% of which use the worldwide standard UTF-8. The encoding scheme looks really messy, so we have to clean it up. And that inner response code is annoying! Let’s fix things up so that our program checks for errors in the response code and returns only the question data in its clean decoded form:

import requests
from urllib.parse import unquote

url = "https://opentdb.com/api.php?amount=1&type=multiple&encode=url3986"
response = requests.get(url)
if response.status_code != 200:
    raise ValueError(f'API error: {response.status_code}')
body = response.json()
if body['response_code'] != 0:
    raise ValueError(f'OpenTDB error: {body["response_code"]}')
question = body['results'][0]
question['category'] = unquote(question['category'])
question['question'] = unquote(question['question'])
question['correct_answer'] = unquote(question['correct_answer'])
question['incorrect_answers'] = [unquote(ans) for ans in question['incorrect_answers']]
print(question)

Here’s an example run with the new code:

{
  'type': 'multiple',
  'difficulty': 'medium',
  'category': 'History',
  'question': 'What was the total length of the Titanic?',
  'correct_answer': '882 ft | 268.8 m',
  'incorrect_answers': [
    '759 ft | 231.3 m',
    '1042 ft | 317.6 m',
    '825 ft | 251.5 m'
  ]
}

Remember you don’t have to do these steps for most APIs.

Believe it or not, that’s it for the work we do together! As the last lab in the course, it’s up to you, during your time, to put everything together into an app that is interesting! Ideas are in the Challenges below. Have fun! Work Hard! Don’t Give Up! And importantly, don’t flail: if you get stuck work with your classmates and ask the instructor or TA for help when needed.

Challenges

Now it’s your turn. Here are some ideas for you to extend the activities above:

Further Study

APIs, especially those that work over the web, are an important part of modern software systems. Although this was our last lab of the course, don’t stop learning! Continue your studies with:

Summary

We’ve covered:

  • What an API is
  • The requests package
  • Parsing JSON
  • The Open Trivia Database API
  • HTTP Response Codes
  • Encoding and decoding

Recall Practice

Here are some questions useful for your spaced repetition learning. Many of the answers are not found on this page. Some will have popped up in lecture. Others will require you to do your own research.

  1. What is an API?
    An Application Programming Interface, which allows different software systems to communicate with each other.
  2. What is a Web API?
    An API that uses the HTTP protocol to allow communication over the internet.
  3. What is the requests package?
    A Python library that allows you to send HTTP requests easily.
  4. What is JSON?
    A “data interchange format” that is easy to read and write for humans and machines.
  5. What is the Open Trivia Database?
    A free-to-use API that provides trivia questions and answers in various categories and difficulties.
  6. What is an HTTP response code?
    A status code returned by a server to indicate the result of an HTTP request.
  7. What does a 200 response code mean?
    The request was successful and the server returned the requested data.
  8. What does a 404 response code mean?
    The requested resource was not found on the server.
  9. What does a 500 response code mean?
    Server error.
  10. What are two reasons why the Open Trivia Database is messy?
    First, it requires an rare and atypical encoding (url3986) that most APIs do not use. Second, the presence of a response_code in the response itself is confusing, as the web protocol (HTTPS) has its own response codes.