Где жила Алиса Селезнева: поиск адресов «гостьи из будущего» с помощью Python

Литературный путь Алисы Селезневой начался в 1965 году под пером Кира Булычева. Со временем эта героиня превратилась в по-настоящему культовую фигуру, чей образ остался актуальным спустя десятилетия. Хотя часть приключений «девочки, с которой ничего не случится» разворачивается на Земле или в прошлых эпохах, в сознании большинства читателей её история неразрывно связана с бескрайним космосом.

Мною двигал исследовательский интерес: применив инструменты языка Python, я решил проанализировать весь цикл произведений, чтобы восстановить карту перемещений Алисы по Вселенной и определить точный список миров, которые она посетила лично.

Для анализа я собрал доступные в сети тексты всех рассказов и повестей в единый массив формата .txt.

Технический стек проекта включил стандартную библиотеку re для работы с регулярными выражениями и поиска текстовых паттернов. Ввиду того, что исходные данные имели разное происхождение, для корректной обработки кодировок использовалась библиотека chardet. Также в работе пригодились модули collections и defaultdict для эффективного подсчета частотных характеристик и структурирования словарей.

Первоочередной задачей стало извлечение всех упоминаний планет. Изначально поиск строился на детекции лексемы «планета» во всех падежных формах.

def find_planets_after_word(text):
    if text is None:
        return [], []
    pattern_planet_name = r'''
        (?

Однако на практике реализация столкнулась с определенными трудностями.

Первичный прогон алгоритма выдал избыточный результат — 663 объекта. Проблема крылась в использовании флага re.IGNORECASE: скрипт захватывал не только имена собственные, но и любые прилагательные, следующие за опорным словом (например, «другая», «эта», «неизвестная»).

Логику пришлось скорректировать: теперь программа учитывала только слова, начинающиеся с заглавной буквы. Дополнительно был внедрен список стоп-слов и ценз на минимальную длину, чтобы отсечь предлоги и союзы.

Также из выборки исключались астрономические термины («система», «звезда», «орбита», «атмосфера»), которые часто соседствуют со словом «планета», но не являются названиями. Фильтрация реализована через проверку вхождения в множество (set) исключений. Кроме того, пришлось научить код игнорировать слова, начинающие новое предложение.

В результате кропотливой очистки данных был сформирован итоговый перечень из 281 планеты, так или иначе фигурирующей в саге об Алисе.

Общий список планет, упомянутых в книгах
География упоминаний планет в произведениях об Алисе Селезневой

Ниже представлен рейтинг наиболее часто встречающихся небесных тел.

Рейтинг 25 самых упоминаемых планет
Топ-25 планет по частоте упоминаний

Стоит отметить, что многие миры присутствуют в тексте лишь в качестве фонового контекста. К примеру, планета Самора упоминается вскользь — её житель лишь однажды выигрывает приз в викторине. Чтобы выделить именно те локации, где Алиса присутствовала физически, я применил контекстный анализ.

Гипотеза заключалась в следующем: факт посещения подтверждается совместным появлением имени героини и глаголов движения в непосредственной близости от названия планеты. Для этого я подготовил регулярные выражения, охватывающие все падежные формы имени «Алиса», а также словарь из более чем двадцати глаголов перемещения (прилетела, высадилась, посетила и т.д.). Для каждого упоминания планеты проверялось окно контекста размером 100 символов в обе стороны.

def find_alisa_visited_planets(text, planets_list):
    if text is None:
        return [], []
    alisa_patterns = [
        r'\bалиса\b', r'\bалисы\b', r'\bалисе\b', 
        r'\bалису\b', r'\bалисой\b', r'\bалисою\b'
    ]
    travel_verbs = [
        r'\bприлетела\b', r'\bприлетели\b', r'\bприлетел\b',
        r'\bприземлилась\b', r'\bприземлились\b',
        r'\bпосетила\b', r'\bпосетили\b', r'\bпосетил\b',
        r'\bулетела\b', r'\bулетели\b', r'\bулетел\b',
        r'\bбыла\b', r'\bбыли\b', r'\bбыл\b',
        r'\bпобывала\b', r'\bпобывали\b',
        r'\bотправилась\b', r'\bотправились\b',
        r'\bдобралась\b', r'\bдобрались\b',
        r'\bдолетела\b', r'\bдолетели\b',
        r'\bприбыла\b', r'\bприбыли\b',
        r'\bнаходилась\b', r'\bнаходились\b',
        r'\bпутешествовала\b', r'\bпутешествовали\b',
        r'\bоказалась\b', r'\bоказались\b'
    ]
    visited_planets = []
    all_planet_checks = []
        for match in re.finditer(planet_pattern, text, re.IGNORECASE):
            position = match.start()
            context_start = max(0, position - 100)
            context_end = min(len(text), position + 100)
            context = text[context_start:context_end].replace('\n', ' ')
            alisa_found = False
            for alisa_pattern in alisa_patterns:
                if re.search(alisa_pattern, context, re.IGNORECASE):
                    alisa_found = True
                    break
            verb_found = False
            matched_verb = None
            for verb_pattern in travel_verbs:
                verb_match = re.search(verb_pattern, context, re.IGNORECASE)
                if verb_match:
                    verb_found = True
                    matched_verb = verb_match.group()
                    break                     
            is_visited = alisa_found and verb_found
            visit_data = {
                'planet': planet_name,
                'position': position,
                'context': context,
                'alisa_found': alisa_found,
                'verb_found': verb_found,
                'matched_verb': matched_verb,
                'is_visited': is_visited
            }
            planet_visits.append(visit_data)
        visited = any(v['is_visited'] for v in planet_visits)
        visit_count = sum(1 for v in planet_visits if v['is_visited'])
        all_planet_checks.append({
            'planet': planet_name,
            'total_mentions': len(planet_visits),
            'visited_mentions': visit_count,
            'is_visited': visited,
            'examples': [v for v in planet_visits if v['is_visited']][:3]  # Первые 3 примера
        })
        if visited:
            visited_planets.append({
                'planet': planet_name,
                'total_mentions': len(planet_visits),
                'visited_mentions': visit_count,
                'examples': [v for v in planet_visits if v['is_visited']][:3]
            })
      return visited_planets, all_planet_checks

Анализ показал, что из огромного многообразия упомянутых миров Алиса лично посетила 12. Это впечатляющий результат для десятилетней школьницы, которой, помимо межзвездных экспедиций, нужно уделять время учебе.

Для наглядности я визуализировал полученные данные с помощью библиотеки plotly. Вот как выглядит карта космических странствий Алисы Селезневой:

Карта посещенных Алисой планет
Перечень миров, в которых побывала героиня

Также я подготовил статистику посещаемости различных уголков Вселенной.

Частота визитов Алисы на разные планеты
Распределение визитов Алисы по планетам
 

Источник

Читайте также