Data Request and Extract From Star Wars ApI

Description: Using the requests library, download all the people in the Star Wars universe using the Star Wars API (https://swapi.dev/documentation). Show the name of the oldest person (or robot or alien) and list the titles of all the films they appeared in.

The Requests Package

The requests module allows us to send HTTP requests using Python.

The HTTP request returns a Response Object with all the response data (content, encoding, status, etc).

In this blog, we use it to fetch characters from StarWars from the the Star Wars API.

A Quick Look at Our 1st Character – Luke Skywalker

It’s quite easy to featch content from web API using request.

import requests

#Fetch
resp = requests.get('https://swapi.dev/api/people/1')

#Show Request
resp
<Response [200]>

Let’s look at our first character!

#Transform to json
character_json = resp.json()
character_json
{'name': 'Luke Skywalker',
 'height': '172',
 'mass': '77',
 'hair_color': 'blond',
 'skin_color': 'fair',
 'eye_color': 'blue',
 'birth_year': '19BBY',
 'gender': 'male',
 'homeworld': 'http://swapi.dev/api/planets/1/',
 'films': ['http://swapi.dev/api/films/1/',
  'http://swapi.dev/api/films/2/',
  'http://swapi.dev/api/films/3/',
  'http://swapi.dev/api/films/6/'],
 'species': [],
 'vehicles': ['http://swapi.dev/api/vehicles/14/',
  'http://swapi.dev/api/vehicles/30/'],
 'starships': ['http://swapi.dev/api/starships/12/',
  'http://swapi.dev/api/starships/22/'],
 'created': '2014-12-09T13:50:51.644000Z',
 'edited': '2014-12-20T21:17:56.891000Z',
 'url': 'http://swapi.dev/api/people/1/'}

Much clear when transforming JASON into pandas dataframe.

import pandas as pd

#Transform to DataFrame
character_df = pd.json_normalize(data)
character_df
name height mass hair_color skin_color eye_color birth_year gender homeworld films species vehicles starships created edited url
0 Luke Skywalker 172 77 blond fair blue 19BBY male http://swapi.dev/api/planets/1/ [http://swapi.dev/api/films/1/, http://swapi.d… [] [http://swapi.dev/api/vehicles/14/, http://swa… [http://swapi.dev/api/starships/12/, http://sw… 2014-12-09T13:50:51.644000Z 2014-12-20T21:17:56.891000Z http://swapi.dev/api/people/1/

All right, next step, we gonna load all characters from Star Wars.

Welcome All Characters from Star Wars

Before we start, we need to deal with something tricky. The detail about somebody cannot be found in the Star War dataset.

data_full = requests.get('https://swapi.dev/api/people/17').json()
data_full
{'detail': 'Not found'}

So we have to check wheather each person exists or not. How can we do that?

I find that it returns a status code of 200 when requests is succesful.

c1 = requests.get('https://swapi.dev/api/people/1')
c1.status_code
200

However, it returns a status code of 404 when requests fails.

person17 = requests.get('https://swapi.dev/api/people/17')
person17.status_code
404

Also, we can see we have 82 characters in total in the dataset.

count = requests.get('https://swapi.dev/api/people').json()['count']
count
82

Therefore, we loop through until we get 82 successful requests:

df_full = pd.DataFrame()

i = 1

while df_full.shape[0] < count: 
    
    #Make request
    character_request = requests.get('https://swapi.dev/api/people/' + str(i))

    #Check if a character was found:
    status_code = character_request.status_code
    if status_code == 200:

        #Transform to JSON
        character_json = character_request.json()

        #Transform to pandas dataframe
        character_df = pd.json_normalize(character_json)

        #Concatenate to existing dataframe
        df_full = df_full.append(character_df)

    i += 1

Set the column ‘name’ as the index of the dataframe and replace all ‘unknown’ in the column ‘birth_year’ as np.nan.

df_full = df_full.set_index(['name'])
df_full["birth_year"] = df_full["birth_year"].replace('unknown',np.nan)
df_full
height mass hair_color skin_color eye_color birth_year gender homeworld films species vehicles starships created edited url
name
Luke Skywalker 172 77 blond fair blue 19BBY male http://swapi.dev/api/planets/1/ [http://swapi.dev/api/films/1/, http://swapi.d… [] [http://swapi.dev/api/vehicles/14/, http://swa… [http://swapi.dev/api/starships/12/, http://sw… 2014-12-09T13:50:51.644000Z 2014-12-20T21:17:56.891000Z http://swapi.dev/api/people/1/
C-3PO 167 75 n/a gold yellow 112BBY n/a http://swapi.dev/api/planets/1/ [http://swapi.dev/api/films/1/, http://swapi.d… [http://swapi.dev/api/species/2/] [] [] 2014-12-10T15:10:51.357000Z 2014-12-20T21:17:50.309000Z http://swapi.dev/api/people/2/
R2-D2 96 32 n/a white, blue red 33BBY n/a http://swapi.dev/api/planets/8/ [http://swapi.dev/api/films/1/, http://swapi.d… [http://swapi.dev/api/species/2/] [] [] 2014-12-10T15:11:50.376000Z 2014-12-20T21:17:50.311000Z http://swapi.dev/api/people/3/
Darth Vader 202 136 none white yellow 41.9BBY male http://swapi.dev/api/planets/1/ [http://swapi.dev/api/films/1/, http://swapi.d… [] [] [http://swapi.dev/api/starships/13/] 2014-12-10T15:18:20.704000Z 2014-12-20T21:17:50.313000Z http://swapi.dev/api/people/4/
Leia Organa 150 49 brown light brown 19BBY female http://swapi.dev/api/planets/2/ [http://swapi.dev/api/films/1/, http://swapi.d… [] [http://swapi.dev/api/vehicles/30/] [] 2014-12-10T15:20:09.791000Z 2014-12-20T21:17:50.315000Z http://swapi.dev/api/people/5/
Grievous 216 159 none brown, white green, yellow NaN male http://swapi.dev/api/planets/59/ [http://swapi.dev/api/films/6/] [http://swapi.dev/api/species/36/] [http://swapi.dev/api/vehicles/60/] [http://swapi.dev/api/starships/74/] 2014-12-20T19:43:53.348000Z 2014-12-20T21:17:50.488000Z http://swapi.dev/api/people/79/
Tarfful 234 136 brown brown blue NaN male http://swapi.dev/api/planets/14/ [http://swapi.dev/api/films/6/] [http://swapi.dev/api/species/3/] [] [] 2014-12-20T19:46:34.209000Z 2014-12-20T21:17:50.491000Z http://swapi.dev/api/people/80/
Raymus Antilles 188 79 brown light brown NaN male http://swapi.dev/api/planets/2/ [http://swapi.dev/api/films/1/, http://swapi.d… [] [] [] 2014-12-20T19:49:35.583000Z 2014-12-20T21:17:50.493000Z http://swapi.dev/api/people/81/
Sly Moore 178 48 none pale white NaN female http://swapi.dev/api/planets/60/ [http://swapi.dev/api/films/5/, http://swapi.d… [] [] [] 2014-12-20T20:18:37.619000Z 2014-12-20T21:17:50.496000Z http://swapi.dev/api/people/82/
Tion Medon 206 80 none grey black NaN male http://swapi.dev/api/planets/12/ [http://swapi.dev/api/films/6/] [http://swapi.dev/api/species/37/] [] [] 2014-12-20T20:35:04.260000Z 2014-12-20T21:17:50.498000Z http://swapi.dev/api/people/83/

82 rows × 15 columns

Get The Oldest Character

birth_year = pd.DataFrame(df_full.birth_year)
birth_year
birth_year
name
Luke Skywalker 19BBY
C-3PO 112BBY
R2-D2 33BBY
Darth Vader 41.9BBY
Leia Organa 19BBY
Grievous NaN
Tarfful NaN
Raymus Antilles NaN
Sly Moore NaN
Tion Medon NaN

82 rows × 1 columns

set([each[-3:] for each in df_full.birth_year.to_list() if each is not np.nan])
{'BBY'}

Here we can see that all characters born in XX BBY (except from ‘NaN’).

What does BBY mean?

It means Before the Battle of Yevin. Now it is clear that the number before BBY larger, older the character is.

Who is the oldest character in the Star Wars? ‘Yoda’

birth_year['age'] = (birth_year.birth_year.str.
                   replace('BBY','').
                   astype('float'))
birth_year = birth_year.sort_values(['age'],ascending = False)
birth_year.head(1)
birth_year age
name
Yoda 896BBY 896.0

All the Films Yoda Appeared in

films = df_full.loc['Yoda',:]['films']

films_title = []
for each in films:
    films_title.append(requests.get(each).json()['title'])

films_title
['The Empire Strikes Back',
 'Return of the Jedi',
 'The Phantom Menace',
 'Attack of the Clones',
 'Revenge of the Sith']