Skip to content

Instantly share code, notes, and snippets.

@afraca
Created June 12, 2018 10:58
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save afraca/a2ae4086bc6b1a11aca63ef86f313ed6 to your computer and use it in GitHub Desktop.
Save afraca/a2ae4086bc6b1a11aca63ef86f313ed6 to your computer and use it in GitHub Desktop.
Python (typed) script to move your IMDb rating history to Netflix upvotes/downvotes
from selenium import webdriver
from selenium.webdriver.firefox.firefox_profile import FirefoxProfile
from selenium.webdriver.remote.webelement import WebElement
from selenium.common.exceptions import *
from selenium.webdriver.firefox.options import Options
import getpass
from typing import Dict, Tuple, List
import os
import csv
import re
from difflib import SequenceMatcher
import time
import json
import click
# These type aliases makes the dictionary passing easier to understand
ImdbId = str
ImdbTitle = str
ImdbRating = int
# Netflix renders quickly enough, but finishes very slowly
DRIVER_TIMEOUT = 15
NETFLIX_LOGIN_URL = 'https://www.netflix.com/nl-en/login'
# IMDB will set something (url?) required up in the "pre-login page"
IMDB_PRE_LOGIN_URL = 'https://www.imdb.com/registration/signin'
IMDB_LOGIN_URL = 'https://www.imdb.com/ap/signin?clientContext=133-8770098-9132729&openid.pape.max_auth_age=0&openid.return_to=https%3A%2F%2Fwww.imdb.com%2Fap-signin-handler&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.assoc_handle=imdb_us&openid.mode=checkid_setup&siteState=eyJvcGVuaWQuYXNzb2NfaGFuZGxlIjoiaW1kYl91cyIsInJlZGlyZWN0VG8iOiJodHRwczovL3d3dy5pbWRiLmNvbS8_cmVmXz1sb2dpbiJ9&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&&tag=imdbtag_reg-20 '
IMDB_TEMP_FILE_NAME = 'ratings.csv'
RESULTS_FILE = 'results.json'
RESULTS = {}
# Poor man's ENUM
RESULT_FOUND_VOTED_UP = 0
RESULT_FOUND_VOTED_DOWN = 1
RESULT_NOT_FOUND = 2
RESULTS_SHOULD_BE_IGNORED = False
def get_driver(headful: bool = False) -> webdriver.Firefox:
options = Options()
if not headful:
options.headless = True
profile = FirefoxProfile()
profile.set_preference("browser.download.folderList", 2)
profile.set_preference("browser.download.manager.showWhenStarting", False)
profile.set_preference("browser.download.dir", os.getcwd())
profile.set_preference("browser.helperApps.neverAsk.saveToDisk", 'text/csv')
driver = webdriver.Firefox(firefox_options=options, firefox_profile=profile)
driver.set_page_load_timeout(DRIVER_TIMEOUT)
return driver
###################################################################################################
def should_update_ratings() -> bool:
answer = input('(Re-)download imdb ratings? (Y/N) (default: N):')
if answer == 'Y':
return True
if answer == 'N' or answer == '':
return False
# Repeat question on invalid input
return should_update_ratings()
def login_to_imdb(driver: webdriver.Firefox, username: str, password: str):
# As stated on global value, IMDB does something weird in login flow, so we need the 'pre-login' visit
driver.get(IMDB_PRE_LOGIN_URL)
login_button_elem = driver.find_element_by_partial_link_text('Sign in with IMDb')
login_button_elem.click()
user_elem = driver.find_element_by_id('ap_email')
user_elem.send_keys(username)
pass_elem = driver.find_element_by_id('ap_password')
pass_elem.send_keys(password)
submit = driver.find_element_by_id('signInSubmit')
submit.click()
def fetch_history(driver: webdriver.Firefox, download_csv: bool, user_id: str = None) -> \
Dict[Tuple[ImdbId, ImdbTitle], ImdbRating]:
if download_csv:
if user_id is None:
raise ValueError('user_id for imdb fetching is required')
if os.path.exists(IMDB_TEMP_FILE_NAME):
remove_history_file()
history_url = 'https://imdb.com/user/{}/ratings/export'.format(user_id)
# Download finishes quick, but somehow we never register an 'end',
# so just set timeout and continue if file is there
driver.set_page_load_timeout(5)
try:
driver.get(history_url)
except TimeoutException:
if not os.path.exists(IMDB_TEMP_FILE_NAME):
raise
driver.set_page_load_timeout(DRIVER_TIMEOUT)
return read_history_file_to_dict()
def read_history_file_to_dict() -> Dict[Tuple[ImdbId, ImdbTitle], ImdbRating]:
ratings = {}
with open(IMDB_TEMP_FILE_NAME, newline='') as csvfile:
reader = csv.reader(csvfile, delimiter=',')
# skip header
next(reader, None)
for row in reader:
try:
imdb_id, title, rating = csv_row_to_dict_entry(row)
ratings[(imdb_id, title)] = rating
except ValueError as e:
print(e, row[0])
print('Movie-To-Rating mapping created')
return ratings
def csv_row_to_dict_entry(row: List) -> Tuple[ImdbId, ImdbTitle, ImdbRating]:
if len(row) < 10:
raise ValueError('csv malformed')
if row[5] != 'movie':
raise ValueError('Not a movie')
return str(row[0]), str(row[3]), int(row[1])
def remove_history_file():
print('Removing ratings file')
os.remove(IMDB_TEMP_FILE_NAME)
###################################################################################################
def login_to_netflix(driver: webdriver.Firefox, username: str, password: str):
driver.get(NETFLIX_LOGIN_URL)
user_elem = driver.find_element_by_id('email')
user_elem.send_keys(username)
pass_elem = driver.find_element_by_id('password')
pass_elem.send_keys(password)
submit = driver.find_element_by_css_selector('.btn.login-button.btn-submit')
submit.click()
print('Logged in to Netflix')
def choose_netflix_profile(driver: webdriver.Firefox, profile_id: str):
print('Choosing netflix profile.')
driver.get('https://www.netflix.com/SwitchProfile?tkn={}'.format(profile_id))
def vote_with_mapping(driver: webdriver.Firefox, mapping: Dict[Tuple[ImdbId, ImdbTitle], ImdbRating],
ignore_results: bool = False):
for (imdb_id, title), rating in mapping.items():
if not should_try_vote(imdb_id, rating, ignore_results):
print('No netflix action required for {}'.format(title))
continue
try:
driver.get('https://netflix.com/search?q={}'.format(title))
except TimeoutException:
RESULTS[imdb_id] = RESULT_NOT_FOUND
print('Searched timed out for {}'.format(title))
continue
links_for_query = driver.find_elements_by_xpath('//a[@href][@aria-label]')
# Last results are bad, exclude them, speeds it up
if len(links_for_query) > 25:
links_for_query = links_for_query[:25]
ids_with_similarity = ids_with_similarity_all_links(links_for_query, title)
if len(ids_with_similarity) == 0:
print('No results found for {}'.format(title))
RESULTS[imdb_id] = RESULT_NOT_FOUND
continue
best_matching_id = max(ids_with_similarity, key=lambda key: ids_with_similarity[key])
if ids_with_similarity[best_matching_id] < 0.9:
print('Could not find similar enough match for {}'.format(title))
RESULTS[imdb_id] = RESULT_NOT_FOUND
if ids_with_similarity[best_matching_id] > 0.75:
print('(But it was really similar!...)')
continue
print('Closest id for {} was {}'.format(title, best_matching_id))
vote_movie(driver, best_matching_id, imdb_id, rating)
def should_try_vote(imdb_id: str, rating: int, ignore_results: bool = False) -> bool:
if ignore_results:
return True
# Movie not yet processed
if imdb_id not in RESULTS:
return True
# It was not on Netflix in previous processing
# (So only way to accommodate Netflix changes is to rerun it ALL unfortunately)
if RESULTS[imdb_id] == RESULT_NOT_FOUND:
return False
vote_up = rating >= 7
# Movie was voted incorrectly
if RESULTS[imdb_id] == RESULT_FOUND_VOTED_UP and not vote_up:
return True
# Movie was voted incorrectly
if RESULTS[imdb_id] == RESULT_FOUND_VOTED_DOWN and vote_up:
return True
# Movie was voted correctly
return False
def ids_with_similarity_all_links(links: List[WebElement], title: str) -> Dict[str, float]:
ids_with_similarity = {}
for elem in links:
label = elem.get_attribute('aria-label')
href = elem.get_attribute('href')
if label is None or href is None:
print('XPath returned illegal element')
continue
maybe_id = re.search(r"\d{5,10}", href)
if maybe_id is None:
continue
entry_id = maybe_id.group()
ids_with_similarity[entry_id] = SequenceMatcher(None, label, title).ratio()
return ids_with_similarity
def vote_movie(driver: webdriver.Firefox, netflix_id: str, imdb_id: str, rating: int):
# Netflix renders quick, completes slowly! Just try to get movie details couple of times
tries = 3
for i in range(tries):
try:
driver.get('https://netflix.com/title/{}'.format(netflix_id))
break
except TimeoutException:
if i == (tries - 1):
# Now we register it as really problematic
raise
try:
driver.find_element_by_css_selector('.thumbs-component.rated')
rated = True
except NoSuchElementException:
rated = False
if rated:
# remove old vote
# Even though manual inspection only shows 1, we get 2 elements (1 for up 1 for down??)
# Simply try them both for now...
unvote_elements = driver.find_elements_by_css_selector('a.nf-svg-button.simpleround')
def register_success():
print('Removed old vote for {}'.format(id))
try:
unvote_elements[0].click()
register_success()
except ElementClickInterceptedException:
unvote_elements[1].click()
register_success()
upvoting = rating >= 7
data_rating_val = '"2"' if upvoting else '"1"'
print('Rating was {} so voting {} for {}'.format(rating, 'up' if upvoting else 'down', imdb_id))
if upvoting:
RESULTS[imdb_id] = RESULT_FOUND_VOTED_UP
else:
RESULTS[imdb_id] = RESULT_FOUND_VOTED_DOWN
selector = 'a.nf-svg-button[data-rating={}]'.format(data_rating_val)
thumb = driver.find_element_by_css_selector(selector)
# After "unvoting" we need to wait before we can register new vote. This SHOULD work with the
# "expected conditions" of selenium (element_to_be_clickable), but did not work for me. Use stupid sleep...
time.sleep(0.5)
thumb.click()
###################################################################################################
def print_statistics():
# Just to know where we are at start and end of script
num_not_found = sum(1 for result in RESULTS.items() if result[1] == RESULT_NOT_FOUND)
num_found_voted_up = sum(1 for result in RESULTS.items() if result[1] == RESULT_FOUND_VOTED_UP)
num_found_voted_down = sum(1 for result in RESULTS.items() if result[1] == RESULT_FOUND_VOTED_DOWN)
print('Not found:{}'.format(num_not_found))
print('Found, voted up: {}'.format(num_found_voted_up))
print('Found, voted down: {}'.format(num_found_voted_down))
def set_results_from_file():
global RESULTS
if os.path.exists(RESULTS_FILE):
with open(RESULTS_FILE) as f:
RESULTS = json.load(f)
print('Loaded results from json')
def set_file_from_results():
with open(RESULTS_FILE, 'w') as f:
f.write(json.dumps(RESULTS))
print('Wrote results to json')
@click.command()
@click.argument('netflix-username')
@click.argument('netflix-profile-id')
@click.option('--imdb-username')
@click.option('--imdb-id', default=None)
@click.option('--headful', default=False, is_flag=True)
@click.option('--ignore-results', default=False, is_flag=True)
def main(netflix_username: str, netflix_profile_id: str, imdb_username: str, imdb_id: str, headful: bool,
ignore_results: bool):
driver = None
set_results_from_file()
print_statistics()
def shutdown():
nonlocal driver
set_file_from_results()
print_statistics()
if driver is not None:
driver.quit()
download_csv = should_update_ratings()
if download_csv:
if imdb_username is None:
raise ValueError('Missing --imdb-username value')
if imdb_id is None:
raise ValueError('Missing --imdb-id value')
imdb_pass = getpass.getpass('IMDB Password:')
else:
imdb_pass = None
netflix_pass = getpass.getpass('Netflix Password:')
try:
driver = get_driver(headful)
if download_csv:
login_to_imdb(driver, imdb_username, imdb_pass)
login_to_netflix(driver, netflix_username, netflix_pass)
mapping = fetch_history(driver, download_csv, imdb_id)
choose_netflix_profile(driver, netflix_profile_id)
vote_with_mapping(driver, mapping, ignore_results)
print('All done!')
shutdown()
remove_history_file()
except:
shutdown()
raise
if __name__ == '__main__':
main()
@afraca
Copy link
Author

afraca commented Jun 12, 2018

Statistics after running:
Not found:1141
Found, voted up: 68
Found, voted down: 98

Results (in case I lose it)

{"tt1000095": 2, "tt1001526": 1, "tt1007029": 0, "tt0100802": 2, "tt1010048": 2, "tt1013753": 2, "tt0101414": 2, "tt1014759": 2, "tt0101587": 2, "tt0101745": 2, "tt1019452": 2, "tt1022603": 2, "tt0102685": 1, "tt0102798": 2, "tt1028528": 2, "tt0102926": 2, "tt0103064": 2, "tt0103241": 2, "tt1032755": 2, "tt1032846": 2, "tt0103639": 2, "tt1037705": 2, "tt0103776": 2, "tt1038988": 2, "tt1043842": 2, "tt0104431": 2, "tt0104437": 2, "tt1045658": 2, "tt0104797": 2, "tt0104868": 2, "tt1049413": 2, "tt0105151": 2, "tt0105236": 2, "tt0105417": 2, "tt1054606": 2, "tt0105629": 2, "tt0105690": 1, "tt0105812": 2, "tt1059786": 1, "tt1060277": 0, "tt0106226": 2, "tt0106308": 1, "tt1065073": 2, "tt0106627": 2, "tt0106673": 2, "tt1068646": 2, "tt1068680": 2, "tt1069238": 2, "tt0106965": 2, "tt0107048": 2, "tt1071804": 2, "tt0107290": 2, "tt1073498": 2, "tt0107362": 2, "tt1074638": 2, "tt0107614": 2, "tt0107688": 2, "tt1077258": 2, "tt1077262": 2, "tt1077368": 2, "tt1078588": 2, "tt1080016": 2, "tt0108052": 2, "tt0108147": 2, "tt0108399": 2, "tt0109040": 2, "tt1091722": 2, "tt0109190": 2, "tt1092019": 2, "tt0109254": 2, "tt0109445": 2, "tt0109686": 1, "tt0109707": 2, "tt0109813": 2, "tt0109830": 0, "tt1099212": 1, "tt0109936": 2, "tt0110074": 2, "tt0110099": 2, "tt0110357": 2, "tt0110366": 1, "tt1104001": 2, "tt0110413": 2, "tt0110475": 2, "tt0110478": 2, "tt0110725": 2, "tt0110857": 2, "tt0110912": 0, "tt1109624": 2, "tt0110989": 2, "tt0111070": 2, "tt0111161": 2, "tt1111833": 1, "tt0111257": 2, "tt0111280": 2, "tt0111282": 2, "tt1119646": 2, "tt1121931": 2, "tt0112255": 2, "tt0112281": 2, "tt0112431": 2, "tt0112442": 2, "tt0112462": 2, "tt0112573": 0, "tt1125849": 2, "tt0112697": 1, "tt0112896": 2, "tt1130080": 2, "tt0113071": 2, "tt1130884": 2, "tt0113189": 2, "tt0113243": 2, "tt0113247": 2, "tt1132626": 2, "tt0113277": 2, "tt1133985": 2, "tt0113492": 2, "tt0113497": 2, "tt1135985": 1, "tt1136608": 2, "tt1139797": 2, "tt0114048": 2, "tt0114069": 2, "tt0114148": 1, "tt0114369": 2, "tt0114436": 2, "tt0114623": 2, "tt0114709": 2, "tt0114746": 2, "tt0114781": 1, "tt0114814": 2, "tt0114825": 2, "tt0114898": 2, "tt1149362": 2, "tt1152836": 0, "tt1155076": 2, "tt1156398": 0, "tt0115683": 2, "tt0115751": 2, "tt0115798": 2, "tt0116126": 1, "tt0116151": 2, "tt0116225": 2, "tt0116250": 2, "tt0116282": 0, "tt0116483": 1, "tt0116778": 2, "tt0116996": 2, "tt0117008": 2, "tt1170358": 2, "tt0117060": 0, "tt0117218": 2, "tt0117705": 2, "tt0117731": 2, "tt0117786": 2, "tt1178663": 2, "tt0117951": 2, "tt1179904": 2, "tt0117998": 2, "tt1182345": 2, "tt0118539": 2, "tt1185616": 2, "tt0118571": 2, "tt0118583": 2, "tt0118665": 2, "tt0118691": 2, "tt1187043": 2, "tt0118708": 2, "tt0118715": 2, "tt0118799": 2, "tt0118880": 2, "tt0118884": 2, "tt0118928": 2, "tt0118954": 2, "tt0118972": 2, "tt0118998": 2, "tt1191111": 2, "tt0119116": 2, "tt0119137": 2, "tt0119173": 2, "tt0119174": 2, "tt0119217": 0, "tt1193138": 2, "tt0119396": 2, "tt0119528": 2, "tt0119567": 2, "tt1196141": 2, "tt0119630": 2, "tt0119643": 2, "tt0119654": 2, "tt0119698": 2, "tt0119896": 2, "tt1201607": 2, "tt0120179": 2, "tt0120184": 2, "tt0120199": 2, "tt0120338": 2, "tt0120347": 2, "tt0120363": 2, "tt0120382": 2, "tt0120434": 2, "tt1205489": 2, "tt1205558": 2, "tt0120586": 2, "tt0120587": 1, "tt0120591": 2, "tt0120595": 2, "tt0120601": 2, "tt0120611": 2, "tt0120616": 2, "tt0120623": 2, "tt0120647": 2, "tt0120663": 2, "tt0120667": 2, "tt0120669": 2, "tt0120685": 2, "tt0120689": 2, "tt0120735": 2, "tt0120737": 2, "tt0120746": 2, "tt0120755": 1, "tt0120762": 2, "tt0120773": 2, "tt0120783": 2, "tt0120789": 2, "tt0120794": 0, "tt0120812": 2, "tt0120815": 0, "tt0120844": 2, "tt0120891": 2, "tt0120903": 2, "tt0120912": 2, "tt0120913": 2, "tt0120915": 2, "tt1210166": 2, "tt1211837": 0, "tt1211956": 1, "tt1213644": 2, "tt1213663": 2, "tt1216475": 2, "tt1217209": 2, "tt0121765": 2, "tt0121766": 2, "tt1219827": 2, "tt1220719": 2, "tt1224366": 2, "tt1228705": 2, "tt0122933": 2, "tt1229340": 2, "tt1231583": 2, "tt1231587": 2, "tt1232776": 2, "tt1232829": 2, "tt1233227": 2, "tt0012349": 2, "tt1245492": 2, "tt1250777": 0, "tt1253863": 2, "tt0125439": 1, "tt0125664": 2, "tt0126029": 0, "tt1270798": 2, "tt1282140": 2, "tt1285016": 2, "tt0128853": 2, "tt1289406": 2, "tt1291150": 1, "tt0129167": 2, "tt0129290": 2, "tt0129387": 2, "tt1298650": 2, "tt1300854": 2, "tt1302011": 1, "tt0130827": 2, "tt1313104": 2, "tt0131369": 2, "tt1320352": 2, "tt0132245": 2, "tt1329457": 2, "tt0133093": 2, "tt0133152": 2, "tt0133240": 2, "tt1333125": 2, "tt1335975": 2, "tt1337051": 2, "tt1340138": 2, "tt1343092": 2, "tt0013442": 2, "tt1345836": 2, "tt0134847": 2, "tt1355644": 2, "tt1371111": 2, "tt0137494": 2, "tt0137523": 2, "tt1375666": 2, "tt0138097": 2, "tt1385956": 2, "tt1386588": 2, "tt1386697": 2, "tt1386703": 2, "tt0138749": 1, "tt0139134": 2, "tt1392170": 1, "tt1392190": 2, "tt0139654": 2, "tt0139809": 2, "tt1403865": 0, "tt1409024": 2, "tt1411250": 1, "tt1411697": 2, "tt0141369": 1, "tt1418377": 1, "tt0142342": 2, "tt1426378": 2, "tt1431045": 2, "tt0143145": 2, "tt1436562": 2, "tt0144084": 0, "tt0144528": 2, "tt1446714": 2, "tt1454029": 2, "tt1454468": 2, "tt0145487": 2, "tt0145660": 2, "tt0146316": 2, "tt1464540": 2, "tt1465522": 2, "tt1467061": 1, "tt1468843": 2, "tt0147612": 2, "tt0147800": 2, "tt1483013": 2, "tt1486192": 2, "tt1490017": 2, "tt0149261": 2, "tt1499658": 2, "tt1504320": 2, "tt0150662": 2, "tt1512235": 2, "tt1515091": 2, "tt0151738": 2, "tt0151804": 2, "tt1524930": 2, "tt1527186": 2, "tt1528100": 2, "tt1534085": 2, "tt1535108": 2, "tt1542344": 2, "tt0154420": 2, "tt0155711": 2, "tt1560747": 2, "tt1568346": 2, "tt1571222": 2, "tt0157503": 2, "tt0015864": 2, "tt1587707": 2, "tt1588398": 2, "tt1596350": 2, "tt0160127": 2, "tt1601913": 1, "tt1608290": 1, "tt0160862": 2, "tt0161083": 2, "tt1611224": 2, "tt1612774": 2, "tt1617661": 2, "tt1619029": 1, "tt0162222": 1, "tt0163025": 2, "tt0163187": 2, "tt1634122": 1, "tt0163651": 2, "tt1636826": 2, "tt1637725": 2, "tt1638355": 2, "tt1639084": 1, "tt0164052": 2, "tt1645170": 1, "tt1646971": 1, "tt1646987": 2, "tt0164912": 2, "tt1650062": 2, "tt1650554": 2, "tt1655442": 2, "tt1659337": 2, "tt1663202": 2, "tt0166813": 1, "tt0166896": 2, "tt0166924": 2, "tt1670345": 0, "tt0167190": 2, "tt0167260": 2, "tt0167261": 2, "tt0167404": 2, "tt1674771": 2, "tt1675434": 2, "tt0168563": 2, "tt0168629": 2, "tt1686821": 2, "tt1687247": 2, "tt1690953": 2, "tt1690967": 1, "tt1692486": 2, "tt0169547": 0, "tt0170016": 2, "tt1706593": 1, "tt1706620": 2, "tt1707386": 2, "tt0017136": 2, "tt0172156": 2, "tt1723121": 2, "tt1723811": 2, "tt0172495": 0, "tt1727770": 2, "tt1731141": 1, "tt1735898": 2, "tt0173840": 2, "tt0175142": 1, "tt1753743": 2, "tt1754656": 2, "tt0175880": 2, "tt1767372": 2, "tt1772264": 2, "tt1772341": 2, "tt1776196": 2, "tt0177789": 2, "tt1790809": 2, "tt1790864": 2, "tt0017925": 2, "tt1798709": 2, "tt1800241": 2, "tt0180093": 2, "tt0181689": 1, "tt0181739": 2, "tt0181852": 2, "tt0181875": 2, "tt1823664": 2, "tt1823672": 2, "tt1825683": 2, "tt0182789": 2, "tt0183505": 2, "tt0183649": 2, "tt1840309": 1, "tt1843866": 2, "tt0184894": 2, "tt0185183": 2, "tt0018528": 2, "tt1853728": 2, "tt1854564": 2, "tt0185937": 2, "tt1859650": 2, "tt0186566": 2, "tt0187078": 2, "tt1872181": 2, "tt0187738": 2, "tt1877832": 2, "tt1895587": 0, "tt0189998": 2, "tt0190332": 2, "tt0190590": 2, "tt0190641": 2, "tt1912398": 2, "tt0191754": 2, "tt0192614": 2, "tt1929263": 0, "tt1935859": 2, "tt1937390": 2, "tt1951264": 0, "tt1951265": 2, "tt1951266": 1, "tt0195714": 2, "tt0196229": 1, "tt1964418": 2, "tt1971325": 2, "tt1979388": 2, "tt0198021": 2, "tt1981115": 2, "tt0198781": 2, "tt2004420": 2, "tt0200465": 2, "tt2005151": 2, "tt2015381": 0, "tt2024544": 0, "tt0203009": 2, "tt0205000": 2, "tt0020629": 2, "tt0206634": 2, "tt0207201": 2, "tt0208092": 2, "tt0208298": 2, "tt2084970": 2, "tt0209144": 2, "tt0209163": 2, "tt2094766": 2, "tt2096673": 2, "tt2101569": 2, "tt0210234": 2, "tt2103281": 2, "tt0211915": 2, "tt0211933": 2, "tt0212338": 2, "tt0212346": 2, "tt0212720": 2, "tt0212985": 0, "tt0213149": 2, "tt2132285": 2, "tt2140373": 2, "tt2170439": 2, "tt0021749": 2, "tt0217869": 2, "tt2194499": 2, "tt2207467": 2, "tt2209764": 2, "tt0022100": 2, "tt2229499": 2, "tt0223897": 2, "tt2245084": 2, "tt2250912": 2, "tt0227538": 2, "tt2277860": 2, "tt2278388": 2, "tt2279373": 2, "tt2292707": 2, "tt2294449": 2, "tt2294629": 2, "tt0230011": 1, "tt2310332": 2, "tt0231775": 2, "tt2322441": 2, "tt0232500": 2, "tt2333804": 2, "tt2338151": 2, "tt0234215": 2, "tt0235679": 2, "tt2357291": 2, "tt2361509": 2, "tt2381111": 2, "tt2381249": 2, "tt2382009": 2, "tt0238380": 2, "tt0238546": 2, "tt0239395": 2, "tt2395427": 2, "tt2397535": 2, "tt2404425": 0, "tt0240462": 2, "tt0240772": 2, "tt0241303": 2, "tt0241527": 2, "tt0242423": 2, "tt0242445": 2, "tt0242527": 2, "tt0242653": 2, "tt0243155": 2, "tt0243585": 2, "tt0244244": 2, "tt2452042": 2, "tt0245429": 2, "tt0245844": 2, "tt0246460": 2, "tt0246464": 2, "tt0246578": 2, "tt0247586": 2, "tt0247638": 2, "tt2488496": 2, "tt0250258": 2, "tt0250494": 2, "tt0250687": 2, "tt0252503": 1, "tt0252866": 2, "tt0253474": 2, "tt0253556": 2, "tt0253754": 2, "tt0253867": 2, "tt2544766": 0, "tt2557490": 2, "tt2562232": 2, "tt0257076": 2, "tt0257106": 2, "tt0258000": 2, "tt0258153": 2, "tt2582846": 2, "tt0258463": 0, "tt0258470": 2, "tt2591814": 2, "tt0259324": 2, "tt0259711": 2, "tt2608732": 2, "tt0261392": 2, "tt2637276": 2, "tt2637294": 2, "tt2639254": 1, "tt0264464": 0, "tt0265086": 1, "tt0265087": 2, "tt0265208": 2, "tt0265666": 2, "tt2660888": 1, "tt0266308": 2, "tt0266543": 0, "tt0266697": 2, "tt0266915": 2, "tt0267913": 2, "tt0268288": 2, "tt0268380": 2, "tt0268695": 2, "tt0268978": 2, "tt2691498": 1, "tt0270288": 2, "tt0270846": 2, "tt0270980": 2, "tt0271668": 1, "tt0272152": 2, "tt2726560": 2, "tt0273822": 2, "tt2739338": 2, "tt0274166": 2, "tt0276919": 2, "tt0277296": 2, "tt0277371": 2, "tt2788710": 2, "tt0027977": 2, "tt2802144": 2, "tt0280460": 2, "tt0280486": 2, "tt0280590": 2, "tt0280720": 2, "tt0282667": 2, "tt0283026": 2, "tt0283054": 2, "tt0283111": 2, "tt0284490": 2, "tt0286106": 2, "tt0286499": 2, "tt0286716": 2, "tt0286788": 2, "tt2870708": 2, "tt2872518": 2, "tt2872732": 2, "tt0287635": 2, "tt0287717": 2, "tt0287978": 2, "tt0288045": 2, "tt2884206": 2, "tt2885450": 2, "tt0289043": 2, "tt0289765": 0, "tt0289848": 2, "tt0289879": 2, "tt0290002": 2, "tt0290095": 2, "tt0290334": 2, "tt2910904": 2, "tt2911342": 2, "tt2911666": 1, "tt0293564": 2, "tt0295178": 2, "tt0295297": 2, "tt0295700": 2, "tt0295701": 2, "tt0029583": 2, "tt0296572": 2, "tt0296845": 2, "tt0297162": 2, "tt0297284": 2, "tt2975590": 2, "tt2980516": 1, "tt0298130": 2, "tt0298148": 1, "tt0298203": 2, "tt0298814": 2, "tt0299977": 2, "tt0300471": 2, "tt0301357": 2, "tt0302297": 2, "tt0302640": 2, "tt0303933": 2, "tt3040964": 1, "tt0304141": 2, "tt0304669": 2, "tt0305224": 2, "tt0305357": 2, "tt0306047": 1, "tt3062096": 2, "tt0306841": 2, "tt0306892": 2, "tt0307156": 2, "tt0307453": 1, "tt0307479": 2, "tt3079380": 2, "tt0308208": 2, "tt0308644": 2, "tt0309530": 1, "tt0310775": 2, "tt0310793": 2, "tt3110958": 1, "tt0311113": 2, "tt0311429": 2, "tt0313792": 2, "tt0313911": 2, "tt3149038": 2, "tt0315327": 2, "tt0316654": 2, "tt0317198": 2, "tt0317219": 2, "tt0317248": 2, "tt0317303": 2, "tt0317705": 2, "tt0317919": 2, "tt3183660": 2, "tt0318649": 1, "tt0319061": 2, "tt0319262": 0, "tt0319343": 2, "tt0320661": 2, "tt0320691": 1, "tt0032138": 2, "tt0322259": 2, "tt0322330": 2, "tt0322420": 2, "tt0322589": 1, "tt0323572": 2, "tt0032455": 2, "tt0032553": 2, "tt0325703": 2, "tt0325710": 2, "tt0325980": 2, "tt3263904": 2, "tt0326856": 2, "tt0326900": 2, "tt0327597": 2, "tt0327679": 2, "tt0330373": 2, "tt3312830": 2, "tt3315342": 2, "tt3316948": 1, "tt0332379": 2, "tt0332452": 2, "tt0333766": 2, "tt0333780": 2, "tt0033467": 2, "tt0335119": 2, "tt0335266": 2, "tt0335438": 2, "tt0337697": 2, "tt0338013": 0, "tt0338094": 2, "tt0338459": 1, "tt0338466": 2, "tt0338526": 1, "tt3385516": 2, "tt0338564": 2, "tt0338751": 2, "tt0339034": 2, "tt0339300": 2, "tt3410834": 2, "tt3416742": 2, "tt0342508": 2, "tt0342735": 2, "tt0343660": 2, "tt0343737": 2, "tt0343818": 1, "tt0034492": 2, "tt0034583": 2, "tt0345950": 0, "tt3464902": 2, "tt0347149": 2, "tt0347246": 2, "tt0347791": 2, "tt0348150": 2, "tt0348333": 2, "tt0349205": 2, "tt3498820": 2, "tt0349903": 2, "tt3501632": 2, "tt0351283": 1, "tt3521164": 2, "tt3531824": 2, "tt0354575": 2, "tt3553976": 2, "tt0356150": 2, "tt0356470": 2, "tt0356910": 2, "tt0357277": 2, "tt0357413": 0, "tt0358082": 2, "tt0358273": 2, "tt0358294": 2, "tt0359013": 2, "tt0359950": 2, "tt0360486": 2, "tt0360717": 2, "tt0361467": 2, "tt0361748": 0, "tt0361862": 2, "tt0362120": 1, "tt3622592": 2, "tt0362270": 2, "tt0363163": 2, "tt0363282": 2, "tt0363589": 2, "tt0363771": 2, "tt0364569": 2, "tt0365748": 0, "tt0365830": 2, "tt3659388": 2, "tt0365957": 1, "tt0366548": 2, "tt0367085": 2, "tt3672742": 2, "tt0367594": 2, "tt0367652": 2, "tt0036775": 2, "tt0367882": 2, "tt0368667": 2, "tt0368794": 2, "tt0368891": 2, "tt0368933": 2, "tt0369610": 2, "tt0370032": 1, "tt0370263": 2, "tt0370986": 2, "tt0371724": 2, "tt0371746": 2, "tt0372183": 0, "tt3722070": 2, "tt0372237": 1, "tt0372334": 2, "tt0372588": 2, "tt0372784": 2, "tt0372873": 2, "tt0373051": 2, "tt0373469": 2, "tt0373889": 2, "tt3748528": 2, "tt0374900": 2, "tt0375063": 2, "tt0375679": 2, "tt0376105": 2, "tt0376994": 2, "tt0377092": 1, "tt0377109": 2, "tt0378194": 2, "tt3783958": 2, "tt0378947": 2, "tt0379725": 0, "tt0379786": 2, "tt0381061": 2, "tt0381111": 2, "tt0381348": 2, "tt0381707": 2, "tt0382330": 2, "tt0382625": 2, "tt0382932": 2, "tt0383028": 2, "tt0383216": 2, "tt0038348": 2, "tt0383574": 2, "tt0385700": 2, "tt0385752": 2, "tt3859052": 2, "tt0386032": 2, "tt0386117": 2, "tt0038650": 2, "tt0386588": 2, "tt3874544": 2, "tt0387564": 2, "tt0387808": 1, "tt0387898": 2, "tt0388795": 2, "tt3896198": 2, "tt0389790": 1, "tt0389860": 2, "tt0390521": 2, "tt0391198": 2, "tt3913244": 2, "tt3922818": 2, "tt0392878": 2, "tt3949660": 2, "tt0395169": 2, "tt0395699": 2, "tt0396171": 2, "tt0396269": 2, "tt0396555": 2, "tt0396652": 2, "tt0397065": 2, "tt0397313": 2, "tt0397535": 2, "tt0398165": 2, "tt0398286": 0, "tt0398808": 2, "tt0399201": 2, "tt0399295": 0, "tt4005402": 2, "tt0401233": 2, "tt0401383": 2, "tt0401711": 2, "tt0401729": 2, "tt0401792": 2, "tt0401997": 2, "tt0402022": 2, "tt0403702": 2, "tt0403703": 2, "tt0404203": 2, "tt0404496": 2, "tt4046784": 2, "tt0405094": 2, "tt0405159": 2, "tt0405296": 2, "tt0407304": 2, "tt0407887": 2, "tt0408236": 2, "tt0408790": 2, "tt0409459": 2, "tt0410377": 2, "tt0410764": 0, "tt0411477": 1, "tt4116284": 2, "tt0412922": 2, "tt0413267": 1, "tt0413300": 2, "tt0414993": 2, "tt0415306": 2, "tt0416449": 2, "tt0416508": 2, "tt0417741": 2, "tt0418279": 2, "tt0041959": 2, "tt0420076": 2, "tt0421054": 2, "tt0421073": 2, "tt0421082": 2, "tt0421715": 2, "tt0422861": 2, "tt0423977": 2, "tt0424136": 2, "tt0424345": 2, "tt0425061": 2, "tt0425112": 2, "tt0425123": 2, "tt0425210": 2, "tt0425413": 2, "tt0426578": 2, "tt0426883": 2, "tt0426931": 2, "tt0427309": 2, "tt0427470": 2, "tt0427944": 2, "tt4287320": 2, "tt0043014": 2, "tt0430308": 2, "tt0432283": 2, "tt0432348": 2, "tt0433362": 2, "tt0433383": 2, "tt0433386": 2, "tt0434409": 2, "tt0435705": 2, "tt0435761": 2, "tt0436697": 2, "tt0438097": 2, "tt0438488": 2, "tt0044081": 2, "tt0440963": 0, "tt0441773": 1, "tt4425200": 2, "tt0442933": 2, "tt0443274": 2, "tt0443453": 2, "tt0443489": 2, "tt0443649": 2, "tt0443706": 2, "tt4438848": 2, "tt0445953": 2, "tt0446029": 0, "tt4468740": 2, "tt0448134": 2, "tt4481514": 2, "tt0448157": 2, "tt0449059": 2, "tt0449088": 2, "tt4500922": 2, "tt0450278": 2, "tt0450385": 2, "tt0451279": 2, "tt0045152": 2, "tt0452608": 2, "tt0453467": 2, "tt0453556": 2, "tt0454848": 0, "tt0454876": 2, "tt0454921": 2, "tt0454945": 1, "tt0455538": 2, "tt0455590": 2, "tt0455857": 2, "tt0456396": 2, "tt4572792": 2, "tt0457430": 2, "tt0457513": 2, "tt0458339": 2, "tt0458481": 1, "tt0458525": 2, "tt0460791": 0, "tt0462322": 2, "tt0462538": 0, "tt0462590": 1, "tt0463854": 2, "tt0464049": 2, "tt4649466": 2, "tt0465234": 2, "tt0465494": 2, "tt0465538": 2, "tt0467200": 2, "tt0467406": 2, "tt0468569": 2, "tt0468644": 1, "tt0469494": 2, "tt0470752": 2, "tt0473075": 2, "tt0047396": 2, "tt0475290": 2, "tt0477078": 2, "tt0477348": 0, "tt0478087": 2, "tt0478134": 2, "tt0478304": 2, "tt0478311": 2, "tt0478970": 2, "tt0479500": 2, "tt0479884": 2, "tt0479952": 1, "tt0480025": 2, "tt0480249": 2, "tt0482088": 2, "tt0482571": 2, "tt4846340": 2, "tt0485947": 2, "tt0048624": 2, "tt0486358": 2, "tt0486576": 2, "tt0486655": 2, "tt0486822": 2, "tt4877122": 2, "tt0489099": 2, "tt0489270": 2, "tt0493464": 1, "tt0049406": 0, "tt0494238": 2, "tt0496806": 2, "tt0497116": 2, "tt0049762": 2, "tt0049833": 2, "tt0498353": 2, "tt0499448": 2, "tt0499549": 2, "tt0499603": 2, "tt0050083": 2, "tt0050825": 2, "tt0050974": 2, "tt0052357": 0, "tt0053125": 2, "tt0053146": 2, "tt0053291": 2, "tt0053946": 2, "tt0054215": 2, "tt0054331": 0, "tt0054743": 2, "tt0055254": 2, "tt5541240": 0, "tt0055630": 2, "tt5580390": 2, "tt0056172": 2, "tt0056193": 2, "tt0056592": 0, "tt0056869": 2, "tt0057012": 2, "tt0057076": 2, "tt0058150": 2, "tt0058331": 2, "tt0059742": 2, "tt0060196": 2, "tt0061418": 2, "tt0061722": 2, "tt0061852": 1, "tt0062622": 2, "tt0063518": 2, "tt0064116": 2, "tt0066921": 2, "tt0066995": 2, "tt0067992": 2, "tt0068428": 2, "tt0068646": 0, "tt0070328": 2, "tt0070511": 2, "tt0070707": 2, "tt0070909": 2, "tt0071315": 2, "tt0071562": 0, "tt0071807": 2, "tt0071853": 0, "tt0071877": 2, "tt0072684": 2, "tt0073341": 2, "tt0073486": 2, "tt0074207": 2, "tt0074958": 0, "tt0075148": 2, "tt0075314": 2, "tt0075686": 0, "tt0758730": 2, "tt0758758": 2, "tt0760311": 2, "tt0762073": 2, "tt0765429": 2, "tt0765443": 2, "tt0076759": 2, "tt0770772": 2, "tt0770802": 2, "tt0770828": 2, "tt0077631": 1, "tt0780622": 2, "tt0783233": 2, "tt0078346": 2, "tt0787474": 0, "tt0078748": 2, "tt0787524": 2, "tt0078788": 2, "tt0792986": 2, "tt0079470": 2, "tt0079501": 2, "tt0079522": 2, "tt0795441": 2, "tt0079574": 2, "tt0796366": 0, "tt0079817": 2, "tt0799934": 2, "tt0799949": 2, "tt0800369": 2, "tt0080120": 2, "tt0803096": 2, "tt0080339": 2, "tt0080453": 2, "tt0080455": 2, "tt0805564": 2, "tt0080678": 2, "tt0080684": 2, "tt0808151": 1, "tt0808417": 2, "tt0808506": 2, "tt0811080": 2, "tt0811138": 2, "tt0813547": 2, "tt0081398": 2, "tt0814255": 2, "tt0814314": 2, "tt0081505": 2, "tt0815245": 2, "tt0081573": 2, "tt0816692": 2, "tt0817177": 2, "tt0820142": 2, "tt0822854": 1, "tt0824747": 2, "tt0825232": 2, "tt0826711": 2, "tt0082694": 2, "tt0082971": 2, "tt0830515": 2, "tt0831888": 2, "tt0083564": 2, "tt0083658": 2, "tt0083866": 2, "tt0083907": 2, "tt0083944": 2, "tt0083987": 2, "tt0084021": 2, "tt0840361": 2, "tt0842926": 2, "tt0084329": 2, "tt0844471": 1, "tt0084503": 2, "tt0084602": 2, "tt0846040": 2, "tt0084726": 2, "tt0848228": 2, "tt0084827": 2, "tt0851578": 2, "tt0857191": 2, "tt0085959": 2, "tt0086034": 2, "tt0086190": 2, "tt0086250": 2, "tt0862846": 2, "tt0086465": 2, "tt0865556": 1, "tt0086567": 2, "tt0086879": 2, "tt0086960": 2, "tt0086979": 2, "tt0869977": 2, "tt0870111": 2, "tt0870984": 2, "tt0087332": 2, "tt0087363": 2, "tt0875609": 2, "tt0876563": 2, "tt0087843": 2, "tt0087928": 2, "tt0880502": 2, "tt0880578": 2, "tt0088170": 2, "tt0088184": 2, "tt0088247": 2, "tt0088323": 2, "tt0884328": 1, "tt0088763": 2, "tt0887883": 2, "tt0088847": 2, "tt0890870": 2, "tt0089153": 2, "tt0892769": 0, "tt0089822": 2, "tt0089880": 2, "tt0090264": 2, "tt0903624": 2, "tt0090605": 2, "tt0090685": 2, "tt0090756": 2, "tt0091042": 0, "tt0910970": 2, "tt0091129": 2, "tt0914863": 2, "tt0091777": 2, "tt0918927": 2, "tt0091949": 2, "tt0092005": 2, "tt0092007": 2, "tt0092067": 2, "tt0926063": 1, "tt0926084": 2, "tt0092644": 2, "tt0926762": 2, "tt0092929": 2, "tt0929425": 1, "tt0929632": 2, "tt0092991": 2, "tt0093058": 2, "tt0093389": 2, "tt0093405": 2, "tt0936501": 0, "tt0093756": 2, "tt0093779": 2, "tt0093818": 2, "tt0093822": 2, "tt0093936": 2, "tt0094012": 2, "tt0942385": 2, "tt0945513": 1, "tt0094625": 0, "tt0094651": 2, "tt0947798": 2, "tt0948470": 2, "tt0094898": 1, "tt0949731": 2, "tt0951216": 2, "tt0952640": 1, "tt0095327": 2, "tt0953318": 2, "tt0095705": 2, "tt0095765": 2, "tt0095882": 2, "tt0095953": 0, "tt0095956": 2, "tt0960731": 2, "tt0960890": 2, "tt0096283": 2, "tt0096438": 2, "tt0964517": 2, "tt0964539": 2, "tt0970411": 1, "tt0970416": 1, "tt0970472": 2, "tt0097115": 2, "tt0097123": 2, "tt0097165": 2, "tt0097235": 2, "tt0974015": 2, "tt0097428": 2, "tt0974554": 2, "tt0097523": 1, "tt0097576": 2, "tt0976051": 2, "tt0097757": 2, "tt0978759": 2, "tt0978762": 2, "tt0978764": 2, "tt0980970": 0, "tt0098105": 2, "tt0983193": 2, "tt0986263": 2, "tt0988045": 2, "tt0993846": 0, "tt0099487": 2, "tt0099685": 2, "tt0099739": 2, "tt0099785": 2}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment