TMDb [^ 1](The Movie Database) is a community-based database that collects data on movies and TV programs. This service has an API [^ 2], and various information can be obtained programmatically. To use the API, you need to apply for use after registering your account. (By the way, this API doesn't seem to have API rate limiting at this time![^ 3])
Define a Python class that hits the API. This time, I will focus on the movie information and try it. The token uses what is called an API read access token, which is generated after applying for API usage.
import requests
import json
from pprint import pprint
class TMDB:
def __init__(self, token):
self.token = token
self.headers_ = {'Authorization': f'Bearer {self.token}', 'Content-Type': 'application/json;charset=utf-8'}
self.base_url_ = 'https://api.themoviedb.org/3/'
self.img_base_url_ = 'https://image.tmdb.org/t/p/w500'
def _json_by_get_request(self, url, params={}):
res = requests.get(url, headers=self.headers_, params=params)
return json.loads(res.text)
def search_movies(self, query):
params = {'query': query}
url = f'{self.base_url_}search/movie'
return self._json_by_get_request(url, params)
def get_movie(self, movie_id):
url = f'{self.base_url_}movie/{movie_id}'
return self._json_by_get_request(url)
def get_movie_account_states(self, movie_id):
url = f'{self.base_url_}movie/{movie_id}/account_states'
return self._json_by_get_request(url)
def get_movie_alternative_titles(self, movie_id, country=None):
url = f'{self.base_url_}movie/{movie_id}/alternative_titles'
return self._json_by_get_request(url)
def get_movie_changes(self, movie_id, start_date=None, end_date=None):
url = f'{self.base_url_}movie/{movie_id}'
return self._json_by_get_request(url)
def get_movie_credits(self, movie_id):
url = f'{self.base_url_}movie/{movie_id}/credits'
return self._json_by_get_request(url)
def get_movie_external_ids(self, movie_id):
url = f'{self.base_url_}movie/{movie_id}/external_ids'
return self._json_by_get_request(url)
def get_movie_images(self, movie_id, language=None):
url = f'{self.base_url_}movie/{movie_id}/images'
return self._json_by_get_request(url)
def get_movie_keywords(self, movie_id):
url = f'{self.base_url_}movie/{movie_id}/keywords'
return self._json_by_get_request(url)
def get_movie_release_dates(self, movie_id):
url = f'{self.base_url_}movie/{movie_id}/release_dates'
return self._json_by_get_request(url)
def get_movie_videos(self, movie_id, language=None):
url = f'{self.base_url_}movie/{movie_id}/videos'
return self._json_by_get_request(url)
def get_movie_translations(self, movie_id):
url = f'{self.base_url_}movie/{movie_id}/translations'
return self._json_by_get_request(url)
def get_movie_recommendations(self, movie_id, language=None):
url = f'{self.base_url_}movie/{movie_id}/recommendations'
return self._json_by_get_request(url)
def get_similar_movies(self, movie_id, language=None):
url = f'{self.base_url_}movie/{movie_id}/similar'
return self._json_by_get_request(url)
def get_movie_reviews(self, movie_id, language=None):
url = f'{self.base_url_}movie/{movie_id}/reviews'
return self._json_by_get_request(url)
def get_movie_lists(self, movie_id, language=None):
url = f'{self.base_url_}movie/{movie_id}/lists'
return self._json_by_get_request(url)
def get_latest_movies(self, language=None):
url = f'{self.base_url_}movie/latest'
return self._json_by_get_request(url)
def get_now_playing_movies(self, language=None, region=None):
url = f'{self.base_url_}movie/now_playing'
return self._json_by_get_request(url)
def get_popular_movies(self, language=None, region=None):
url = f'{self.base_url_}movie/popular'
return self._json_by_get_request(url)
def get_top_rated_movies(self, language=None, region=None):
url = f'{self.base_url_}movie/top_rated'
return self._json_by_get_request(url)
def get_upcoming_movies(self, language=None, region=None):
url = f'{self.base_url_}movie/upcoming'
return self._json_by_get_request(url)
You can see all the following execution results in the notebook linked below
https://colab.research.google.com/drive/11jK7yuluSdA-YBAsrm7wmHJpEwJSyE7L?authuser=0
Create an instance, first search for the movie and get the ID of the movie in this API
api = TMDB(token) #token substitutes the issued character string
res = api.search_movies("Shoplifters")
pprint(res)
{'page': 1,
'results': [{'adult': False,
'backdrop_path': '/xOpQ4jIQJ0HSUhVDixZA9yWqVBP.jpg',
'genre_ids': [18, 80],
'id': 505192,
'original_language': 'ja',
'original_title': 'Shoplifters',
'overview': 'After one of their shoplifting sessions, Osamu and '
'his son come across a little girl in the freezing '
'cold. At first reluctant to shelter the girl, '
'Osamu’s wife agrees to take care of her after '
'learning of the hardships she faces. Although the '
'family is poor, barely making enough money to '
'survive through petty crime, they seem to live '
'happily together until an unforeseen incident '
'reveals hidden secrets, testing the bonds that '
'unite them.',
'popularity': 16.385,
'poster_path': '/4nfRUOv3LX5zLn98WS1WqVBk9E9.jpg',
'release_date': '2018-06-02',
'title': 'Shoplifters',
'video': False,
'vote_average': 7.9,
'vote_count': 1128}],
'total_pages': 1,
'total_results': 1}
Since there was only one search result this time, specify the first index and keep the movie ID. You can specify this ID to get more information
movie_id = res['results'][0]['id']
api.get_movie(movie_id)
#=>
{'adult': False,
'backdrop_path': '/xOpQ4jIQJ0HSUhVDixZA9yWqVBP.jpg',
'belongs_to_collection': None,
'budget': 0,
'genres': [{'id': 18, 'name': 'Drama'}, {'id': 80, 'name': 'Crime'}],
'homepage': 'https://www.shopliftersfilm.com',
'id': 505192,
'imdb_id': 'tt8075192',
'original_language': 'ja',
'original_title': 'Shoplifters',
'overview': 'After one of their shoplifting sessions, Osamu and his son come across a little girl in the freezing cold. At first reluctant to shelter the girl, Osamu’s wife agrees to take care of her after learning of the hardships she faces. Although the family is poor, barely making enough money to survive through petty crime, they seem to live happily together until an unforeseen incident reveals hidden secrets, testing the bonds that unite them.',
'popularity': 16.385,
'poster_path': '/4nfRUOv3LX5zLn98WS1WqVBk9E9.jpg',
'production_companies': [{'id': 84048,
'logo_path': '/nu8Q8IvG2fazeI7axTnUhAvzrqy.png',
'name': 'Gaga Corporation',
'origin_country': 'JP'},
{'id': 3341,
'logo_path': '/dTG5dXE1kU2mpmL9BNnraffckLU.png',
'name': 'Fuji Television Network',
'origin_country': 'JP'},
{'id': 39804,
'logo_path': None,
'name': 'AOI Promotion',
'origin_country': 'JP'},
{'id': 75214, 'logo_path': None, 'name': 'Bunbuku', 'origin_country': 'JP'}],
'production_countries': [{'iso_3166_1': 'JP', 'name': 'Japan'}],
'release_date': '2018-06-02',
'revenue': 0,
'runtime': 121,
'spoken_languages': [{'iso_639_1': 'ja', 'name': 'Japanese'}],
'status': 'Released',
'tagline': '',
'title': 'Shoplifters',
'video': False,
'vote_average': 7.9,
'vote_count': 1128}
The image is divided into two parts, backdrops and posters. Backdrops can be used for one shot in the movie, and posters can be used for information on poster images in the screening country. I will leave only backdrops as a trial.
You can also see all the images at the links below. There are quite a few, so it's fun to watch (or rather, there are quite a few posters that the Japanese version doesn't have ...)
https://colab.research.google.com/drive/11jK7yuluSdA-YBAsrm7wmHJpEwJSyE7L?authuser=0#scrollTo=7rpSM-9lrRg8
res = api.get_movie_images(movie_id)
for backdrop in res['backdrops']:
print(f"<img src={api.img_base_url_}{backdrop['file_path']}>")
#=>
If there are various titles depending on the country, you can get the title for each country. I feel that this area is information that is difficult to obtain with other data and services.
pprint(api.get_movie_alternative_titles(movie_id))
#=>
{'id': 505192,
'titles': [{'iso_3166_1': 'JP', 'title': 'Manbiki Kazoku', 'type': 'romaji'},
{'iso_3166_1': 'US',
'title': 'Shoplifting Family',
'type': 'literal translation'},
{'iso_3166_1': 'KR', 'title': '어느 가족', 'type': ''},
{'iso_3166_1': 'UA', 'title': 'Магазинні злодюжки', 'type': ''},
{'iso_3166_1': 'GB', 'title': 'Shoplifters', 'type': ''},
{'iso_3166_1': 'JP',
'title': 'Manbiki kazoku (Shoplifters)',
'type': ''},
{'iso_3166_1': 'AR', 'title': 'Somos una familia', 'type': ''},
{'iso_3166_1': 'CN', 'title': 'Shoplifters', 'type': ''},
{'iso_3166_1': 'BR', 'title': 'Assunto de Família', 'type': ''}]}
There are budget and revenue in the returned value, so it seems to be about money, but this time there is no information in particular and I do not understand well
pprint(api.get_movie_changes(movie_id, start_date="2018/06/08", end_date="2018/06/15"))
#=>
{'adult': False,
'backdrop_path': '/xOpQ4jIQJ0HSUhVDixZA9yWqVBP.jpg',
'belongs_to_collection': None,
'budget': 0,
'genres': [{'id': 18, 'name': 'Drama'}, {'id': 80, 'name': 'Crime'}],
'homepage': 'https://www.shopliftersfilm.com',
'id': 505192,
'imdb_id': 'tt8075192',
'original_language': 'ja',
'original_title': 'Shoplifters',
'overview': 'After one of their shoplifting sessions, Osamu and his son come '
'across a little girl in the freezing cold. At first reluctant to '
'shelter the girl, Osamu’s wife agrees to take care of her after '
'learning of the hardships she faces. Although the family is '
'poor, barely making enough money to survive through petty crime, '
'they seem to live happily together until an unforeseen incident '
'reveals hidden secrets, testing the bonds that unite them.',
'popularity': 16.385,
'poster_path': '/4nfRUOv3LX5zLn98WS1WqVBk9E9.jpg',
'production_companies': [{'id': 84048,
'logo_path': '/nu8Q8IvG2fazeI7axTnUhAvzrqy.png',
'name': 'Gaga Corporation',
'origin_country': 'JP'},
{'id': 3341,
'logo_path': '/dTG5dXE1kU2mpmL9BNnraffckLU.png',
'name': 'Fuji Television Network',
'origin_country': 'JP'},
{'id': 39804,
'logo_path': None,
'name': 'AOI Promotion',
'origin_country': 'JP'},
{'id': 75214,
'logo_path': None,
'name': 'Bunbuku',
'origin_country': 'JP'}],
'production_countries': [{'iso_3166_1': 'JP', 'name': 'Japan'}],
'release_date': '2018-06-02',
'revenue': 0,
'runtime': 121,
'spoken_languages': [{'iso_639_1': 'ja', 'name': 'Japanese'}],
'status': 'Released',
'tagline': '',
'title': 'Shoplifters',
'video': False,
'vote_average': 7.9,
'vote_count': 1128}
It seems that you can get information on the cast and staff who appeared. It seems that credit_id is also assigned to these data, so from here It seems that you can get more information about that person. There seems to be an image
pprint(api.get_movie_credits(movie_id))
#=>
{'cast': [{'cast_id': 0,
'character': 'Osamu Shibata',
'credit_id': '5a845387c3a3682dbf012ac5',
'gender': 2,
'id': 123739,
'name': 'Lily Franky',
'order': 0,
'profile_path': '/8T3I7KQX0SH6twXsuqe12Sc7Hxr.jpg'},
{'cast_id': 1,
'character': 'Nobuyo Shibata',
'credit_id': '5a845394c3a36862e100c84a',
'gender': 1,
'id': 100766,
'name': 'Sakura Ando',
'order': 1,
'profile_path': '/lR1YVfjMYKCMOHzvY3pHTFM5zSI.jpg'},
...
Keywords on TMDb
pprint(api.get_movie_keywords(movie_id))
#=>
{'id': 505192,
'keywords': [{'id': 1328, 'name': 'secret'},
{'id': 10235, 'name': 'family relationships'},
{'id': 12279, 'name': 'family drama'},
{'id': 12369, 'name': 'tokyo, japan'},
{'id': 12987, 'name': 'poverty'},
{'id': 13014, 'name': 'orphan'},
{'id': 155419, 'name': 'shoplifting'},
{'id': 190823, 'name': 'social realism'},
{'id': 209085, 'name': 'shoplifter'},
{'id': 232817, 'name': 'petty crimes'},
{'id': 241445, 'name': 'asian origins'}]}
List of release dates in screening countries
pprint(api.get_movie_release_dates(movie_id))
#=>
{'id': 505192,
'results': [{'iso_3166_1': 'TR',
'release_dates': [{'certification': '',
'iso_639_1': '',
'note': 'Filmekimi',
'release_date': '2018-10-06T00:00:00.000Z',
'type': 1},
{'certification': '',
'iso_639_1': '',
'note': '',
'release_date': '2019-01-18T00:00:00.000Z',
'type': 3}]},
{'iso_3166_1': 'HU',
'release_dates': [{'certification': '',
'iso_639_1': '',
'note': '',
'release_date': '2019-01-10T00:00:00.000Z',
'type': 3}]},
...
pprint(api.get_movie_videos(movie_id))
#=>
{'id': 505192,
'results': [{'id': '5bd4ea970e0a2622dd022b3b',
'iso_3166_1': 'US',
'iso_639_1': 'en',
'key': '9382rwoMiRc',
'name': 'Shoplifters - Official Trailer',
'site': 'YouTube',
'size': 1080,
'type': 'Trailer'}]}
You can use this key to view Youtube videos
You can get a translation of the summary sentence as well as the title. This also seems to be only for the screening country
pprint(api.get_movie_translations(movie_id))
#=>
{'id': 505192,
'translations': [{'data': {'homepage': '',
'overview': 'Едно семейство живее на ръба на '
'бедността като джебчии на дребно. '
'След един „набег” из магазините, '
'Осаму и синът му откриват едно малко '
'момиченце, изоставено в студа. '
'Съпругата на Осаму решава да помогне '
'на детето, след като научава през '
'какви перипетии е преминало. Всички у '
'дома са задружни и щастливи, въпреки '
'обстоятелствата, които са ги '
'принудили да връзват двата края с '
'помощта на малки кражби всеки ден, но '
'непредвиден инцидент разкрива тайни, '
'които поставят на изпитание връзките '
'между членовете на семейството.',
'runtime': 121,
'tagline': '',
'title': 'Джебчии'},
'english_name': 'Bulgarian',
'iso_3166_1': 'BG',
'iso_639_1': 'bg',
'name': 'български език'},
...
It will return a recommendation for this movie by TMDb. The algorithm is unknown
The first recommendation was a Korean remake based on Haruki Murakami.
pprint(api.get_movie_recommendations(movie_id))
#=>
{'page': 1,
'results': [{'adult': False,
'backdrop_path': '/v6eOq707lwWFIG96Rv9sSR6lnnT.jpg',
'genre_ids': [9648, 18, 53],
'id': 491584,
'original_language': 'ko',
'original_title': '버닝',
'overview': 'Deliveryman Jongsu is out on a job when he runs '
'into Haemi, a girl who once lived in his '
"neighborhood. She asks if he'd mind looking after "
"her cat while she's away on a trip to Africa. On "
'her return she introduces to Jongsu an enigmatic '
'young man named Ben, who she met during her trip. '
'And one day Ben tells Jongsu about his most unusual '
'hobby...',
'popularity': 19.981,
'poster_path': '/8ak33l6lfvBPmWOMH9sUCOaC6lq.jpg',
'release_date': '2018-05-17',
'title': 'Burning',
'video': False,
'vote_average': 7.4,
'vote_count': 801},
...
Unlike the recommendation, it seems that the similarity is calculated using the information of keywords and genre.
pprint(api.get_similar_movies(movie_id))
#=>
{'page': 1,
'results': [{'adult': False,
'backdrop_path': '/gSIfujGhazIvswp4R9G6tslAqW7.jpg',
'genre_ids': [18, 10751, 14],
'id': 11236,
'original_language': 'en',
'original_title': 'The Secret Garden',
'overview': 'A young British girl born and reared in India loses '
'her neglectful parents in an earthquake. She is '
"returned to England to live at her uncle's castle. "
'Her uncle is very distant due to the loss of his '
'wife ten years before. Neglected once again, she '
'begins exploring the estate and discovers a garden '
'that has been locked and neglected. Aided by one of '
"the servants' boys, she begins restoring the "
'garden, and eventually discovers some other secrets '
'of the manor.',
'popularity': 11.531,
'poster_path': '/2B8yOYHrp0AopX3gk4b7jWH3Q5a.jpg',
'release_date': '1993-08-13',
'title': 'The Secret Garden',
'video': False,
'vote_average': 7.3,
'vote_count': 571},
...
It seems that user reviews can be taken. There was nothing this time (Fu)
pprint(api.get_movie_reviews(movie_id))
#=>
{'id': 505192, 'page': 1, 'results': [], 'total_pages': 0, 'total_results': 0}
The documentation said it would return a list to which this movie belongs. (What is a list in TMDb ...)
pprint(api.get_movie_lists(movie_id))
#=>
{'id': 505192,
'page': 1,
'results': [{'description': '',
'favorite_count': 0,
'id': 107706,
'iso_639_1': 'en',
'item_count': 4434,
'list_type': 'movie',
'name': 'Watched Movies',
'poster_path': None},
{'description': 'Vari',
'favorite_count': 0,
'id': 137511,
'iso_639_1': 'en',
'item_count': 89,
'list_type': 'movie',
'name': 'Film esteri',
'poster_path': None},
{'description': '',
'favorite_count': 0,
'id': 130541,
'iso_639_1': 'it',
'item_count': 196,
'list_type': 'movie',
'name': '2020',
'poster_path': None},
...
After this, it is a format that extracts from the entire work, not the searched movie
pprint(api.get_latest_movies())
#=>
{'adult': False,
'backdrop_path': None,
'belongs_to_collection': None,
'budget': 0,
'genres': [],
'homepage': '',
'id': 761504,
'imdb_id': None,
'original_language': 'fr',
'original_title': 'Otto Skorzeny, chef de commando nazi et agent du Mossad',
'overview': '',
'popularity': 0.0,
'poster_path': None,
'production_companies': [],
'production_countries': [],
'release_date': '',
'revenue': 0,
'runtime': 0,
'spoken_languages': [{'iso_639_1': 'fr', 'name': 'Français'}],
'status': 'Released',
'tagline': '',
'title': 'Otto Skorzeny, chef de commando nazi et agent du Mossad',
'video': False,
'vote_average': 8.0,
'vote_count': 1}
pprint(api.get_now_playing_movies())
#=>
{'dates': {'maximum': '2020-11-12', 'minimum': '2020-09-25'},
'page': 1,
'results': [{'adult': False,
'backdrop_path': '/86L8wqGMDbwURPni2t7FQ0nDjsH.jpg',
'genre_ids': [28, 53],
'id': 724989,
'original_language': 'en',
'original_title': 'Hard Kill',
'overview': 'The work of billionaire tech CEO Donovan Chalmers '
'is so valuable that he hires mercenaries to protect '
'it, and a terrorist group kidnaps his daughter just '
'to get it.',
'popularity': 2025.862,
'poster_path': '/ugZW8ocsrfgI95pnQ7wrmKDxIe.jpg',
'release_date': '2020-10-23',
'title': 'Hard Kill',
'video': False,
'vote_average': 4.8,
'vote_count': 86},
...
pprint(api.get_popular_movies())
#=>
{'page': 1,
'results': [{'adult': False,
'backdrop_path': '/86L8wqGMDbwURPni2t7FQ0nDjsH.jpg',
'genre_ids': [28, 53],
'id': 724989,
'original_language': 'en',
'original_title': 'Hard Kill',
'overview': 'The work of billionaire tech CEO Donovan Chalmers '
'is so valuable that he hires mercenaries to protect '
'it, and a terrorist group kidnaps his daughter just '
'to get it.',
'popularity': 2025.862,
'poster_path': '/ugZW8ocsrfgI95pnQ7wrmKDxIe.jpg',
'release_date': '2020-10-23',
'title': 'Hard Kill',
'video': False,
'vote_average': 4.8,
'vote_count': 86},
...
pprint(api.get_top_rated_movies())
#=>
{'page': 1,
'results': [{'adult': False,
'backdrop_path': '/jtAI6OJIWLWiRItNSZoWjrsUtmi.jpg',
'genre_ids': [10749],
'id': 724089,
'original_language': 'en',
'original_title': "Gabriel's Inferno Part II",
'overview': 'Professor Gabriel Emerson finally learns the truth '
"about Julia Mitchell's identity, but his "
'realization comes a moment too late. Julia is done '
'waiting for the well-respected Dante specialist to '
'remember her and wants nothing more to do with him. '
'Can Gabriel win back her heart before she finds '
"love in another's arms?",
'popularity': 9.491,
'poster_path': '/pci1ArYW7oJ2eyTo2NMYEKHHiCP.jpg',
'release_date': '2020-07-31',
'title': "Gabriel's Inferno Part II",
'video': False,
'vote_average': 8.9,
'vote_count': 915},
...
pprint(api.get_upcoming_movies())
#=>
{'dates': {'maximum': '2020-11-30', 'minimum': '2020-11-13'},
'page': 1,
'results': [{'adult': False,
'backdrop_path': '/8rIoyM6zYXJNjzGseT3MRusMPWl.jpg',
'genre_ids': [14, 10751, 12, 35, 27],
'id': 531219,
'original_language': 'en',
'original_title': "Roald Dahl's The Witches",
'overview': 'In late 1967, a young orphaned boy goes to live '
'with his loving grandma in the rural Alabama town '
'of Demopolis. As the boy and his grandmother '
'encounter some deceptively glamorous but thoroughly '
'diabolical witches, she wisely whisks him away to a '
'seaside resort. Regrettably, they arrive at '
"precisely the same time that the world's Grand High "
'Witch has gathered.',
'popularity': 1867.444,
'poster_path': '/betExZlgK0l7CZ9CsCBVcwO1OjL.jpg',
'release_date': '2020-10-26',
'title': "Roald Dahl's The Witches",
'video': False,
'vote_average': 7.1,
'vote_count': 530},
...
Recommended Posts