CoderCastrov logo
CoderCastrov
IMDb

Как парсить IMDB для определения пересечения между актерским составом и съемочной группой

Как парсить IMDB для определения пересечения между актерским составом и съемочной группой
просмотров
5 мин чтение
#IMDb

Анализ последней тенденции супергеройских шоу и людей, работающих над ними

Я, наверное, не единственный, кто смотрел телешоу и заметил сходство с другим шоу или фильмом. Для меня последний случай произошел, когда я смотрел Doom Patrol на HBO Max и заметил некоторые схожие моменты с Umbrella Academy на Netflix.

Я не был единственным, кто увидел сходства между этими двумя шоу, и после некоторого исследования я обнаружил, что некоторые продюсеры работали как над Doom Patrol, так и над Umbrella Academy. Это, конечно, объясняет, почему эти шоу имеют схожую эстетику и моменты с персонажами.

У меня возникла идея использовать данные для определения пересечения между актерским составом и съемочной группой телешоу и использовать это в качестве прокси для анализа сходства между шоу.

Как всегда, код для этого проекта находится в моем репозитории "data-science-projects" на Github. Конкретная папка для этого проекта находится здесь.

Я разработал этот проект для видео на Youtube, в котором анализируются сходства между "сюрреалистическими супергеройскими шоу", которое вы можете посмотреть ниже!


Парсинг данных

Первый шаг в этом проекте - получить список всех людей, которые работали над определенным шоу. IMDB делает это очень простым.

Screenshot of IMDB credits for Doom Patrol.

IMDB имеет страницу "полный актерский состав и съемочная группа" для каждого телешоу в их базе данных (вот ссылка на Doom Patrol). Этот список удобен, потому что он группирует всех людей по их ролям (например, сценаристы/актеры/визажисты и т.д.). Обратите внимание, что люди могут быть перечислены в нескольких категориях, если у них есть более одной роли в данном производстве.

Парсинг этой информации относительно прост, так как страница создана с использованием HTML-таблиц. Ниже приведена функция, которую я использовал для парсинга этих данных:

def scrapeCrew(url): #парсинг актерского состава и съемочной группы с IMDB
    html = urlopen(url)
    soup = BeautifulSoup(html, 'html.parser')
    tables = soup.find_all('table')
    headers = soup.find_all('h4')
    dfs = []
    for i in range(len(tables)):
        header = headers[i].text.strip().replace('\n', '')
        rows = tables[i].find_all('tr')
        names = []
        roles = []
        presence = []
        if header == 'Series       Cast':
            for row in rows[1::2]:
                names.append(row.find_all('a')[1].text)
                roles.append(row.find_all('a')[2].text)
                presence.append(row.find_all('a')[3].text)
            df = pd.DataFrame() 
            df['name'] = names
            df['role'] = roles
            df['presence'] = presence
            dfs.append(df)
        else:
            for row in rows:
                names.append(row.find('a').text)
                presence.append(row.find('td', class_='credit').text)
            df = pd.DataFrame() 
            df['name'] = names
            df['role'] = header
            df['presence'] = presence
            dfs.append(df)
    temp = pd.concat(dfs)
    temp['show'] = soup.find('h3').text.strip()
    return temp

Стоит отметить, что IMDB отображает информацию о актерском составе по-другому, чем для всех остальных членов съемочной группы, поэтому я написал условие if для определения, является ли данный заголовок "Cast".

После подачи этой функции URL вы получите фрейм данных, который может выглядеть так:

DataFrame of Doom Patrol’s cast and crew.

Очевидно, что этот фрейм данных нужно очистить (простая замена строк для "\n" и любых других специальных символов должна справиться с этим).

Другое, на что вы можете обратить внимание, это то, что я включил столбец "show", даже если все строки в фрейме данных должны иметь одно и то же значение (в данном случае Doom Patrol). Однако, целью этого упражнения является определение перекрытия актерского состава между несколькими шоу, поэтому вам придется запустить эту функцию scrapeCrew несколько раз, а затем объединить фреймы данных с помощью метода concat из библиотеки pandas. Столбец show будет полезен, когда у нас будет несколько шоу в фрейме данных.

Определение пересечения актерского состава

Для моего проекта я собрал информацию о актерском составе и съемочной группе сериалов "Doom Patrol", "Wandavision", "Umbrella Academy" и "Legion" - все они популярные, сюрреалистические телесериалы, основанные на комиксах.

Как я уже упоминал ранее, некоторые люди указаны несколько раз в титрах сериала, если у них было несколько ролей. Мы можем использовать комбинацию методов drop_duplicates и value_counts из библиотеки pandas, чтобы определить список людей, которые работали над несколькими сериалами (а не имели несколько ролей).

Ниже приведен код, который я использовал для определения людей, которые работали над более чем одним сериалом из "Doom Patrol", "Wandavision", "Umbrella Academy" и "Legion". Переменная "all_shows" относится к моему фрейму данных со всеми участниками актерского состава и съемочной группы.

all_shows[["name", "show"]].drop_duplicates()["name"].value_counts().head(20) # удаляем дубликаты из-за нескольких ролей

Мы также можем сгруппировать наш фрейм данных "all_shows" по столбцу "name", чтобы достичь аналогичного эффекта. Таким образом, у нас будут не только имена всех людей, которые работали над несколькими сериалами, но и информация о сериале и роли.

grouped = all_shows.groupby("name").agg(lambda x: pd.unique(x))

Функция агрегатора вызывает метод unique из библиотеки pandas, чтобы сохранить всю информацию для каждого имени. Как видно на скриншоте ниже, столбцы "role", "presence" и "show" для Аарона Шора теперь имеют массивы в качестве значения, а не отдельную строку. Это потому, что Аарон Шор работал как над "Doom Patrol", так и над "Wandavision".

Фрейм данных, сгруппированный по имени.

Я также создал столбец "num_shows", вычислив длину массива в столбце "show". Однако, если вы посмотрите на скриншот, вы обязательно заметите, что что-то странное происходит с этим столбцом "num_shows".

Это связано с тем, что столбец "show" имеет смешанные типы. Если человек работал только над 1 сериалом, тип значения - строка. В противном случае это массив. Теперь, поскольку мы использовали функцию len для вычисления "num_shows", если тип значения - строка, то "num_shows" представляет собой количество символов в строке, а не количество сериалов, над которыми работал человек.

Есть способы обойти это. Однако, меня интересовали только люди, которые работали над несколькими сериалами, поэтому я в итоге отфильтровал любую строку, у которой значение num_shows было больше 4.

Фрейм данных участников съемочной группы, которые работали над несколькими сериалами из моего набора данных (Doom Patrol, Wandavision, Legion и Umbrella Academy).

В результате у вас будет фрейм данных людей, которые работали над несколькими сериалами из указанных вами (в моем случае "Doom Patrol", "Wandavision", "Legion" и "Umbrella Academy").

С такими данными можно проводить интересный анализ сети или даже изучать различия в ролях между сериалами для определенных людей (например, возможно, они режиссировали целый сезон одного сериала и только гостевое участие в другом). Возможности здесь практически безграничны!