Именно этот вопрос возник у нас в процессе игры в "Города" пока мы ехали из Екатеринбурга в Тюмень, а названия городов то и дело заканчивались на "К". В тот момент город Курган был назван уже 25 раз. И нас озарило... Спарсим данные с RuWiki и посмотрим сколько городов в России начинаются и заканчиваются на букву К!

Наш подробный пайплайн исследования названий городов России:

1) Сбор данных

Мы решили спарсить данные с названиями городов и датой их первого упоминания с RuWiki.

Пример кода для парсинга данных с сайтов (Спасибо эре вайб кодинга)):

import requests
from bs4 import BeautifulSoup
import csv

url = "https://ru.ruwiki.ru/wiki/Список_городов_России"
resp = requests.get(url)
resp.raise_for_status()

soup = BeautifulSoup(resp.text, "html.parser")

# находим основную таблицу списка городов
table = soup.find("table")

rows = table.find_all("tr")

results = []

for row in rows[1:]:  # пропускаем заголовок
    cols = row.find_all(["td","th"])
    if len(cols) >= 7:
        # номер, герб, город, регион, округ, население, основание
        city = cols[2].get_text(strip=True) #берем 2 колонку
        first_mention = cols[6].get_text(strip=True)
        results.append((city, first_mention))

# сохраняем в CSV
with open("cities_first_mention.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerow(["Город", "Основание/Первое упоминание"])
    writer.writerows(results)

print(f"Записано {len(results)} строк.")

2) Нормализация данных

Данные с RuWiki не всегда однородные: в названиях могут быть пробелы, а даты находиться в форматах «1147» и «XII век». С помощью регулярок названия городов приведены к единому виду - убрали лишние пробелы, а также преобразовали века в годы: например, XII век → 1100.

import re

def extract_year(text):
    # Проверяем, что входное значение — строка, иначе возвращаем None
    if not isinstance(text, str):
        return None

    text = text.lower()  # приводим текст к нижнему регистру для упрощения поиска

    # ищем обычный год в формате 1000–1999 или 500–999
    year_match = re.search(r'\b(1[0-9]{3}|[5-9][0-9]{2})\b', text)
    if year_match:
        return int(year_match.group())  # если нашли год — возвращаем его как число

    # ищем века, записанные римскими цифрами 
    century_match = re.search(r'([ivxlcdm]+)\s*век', text)
    if century_match:
        roman = century_match.group(1).upper()  # получаем римское число и переводим в верхний регистр
        roman_map = {
            'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000
        }

        # Конвертация римских цифр в арабское число
        value = 0
        prev = 0
        for c in roman[::-1]:  # идём с конца строки
            if roman_map[c] < prev:  # если меньшая цифра перед большей — вычитаем
                value -= roman_map[c]
            else:  # иначе прибавляем
                value += roman_map[c]
                prev = roman_map[c]

        return (value - 1) * 100  # переводим век в начало века (например, XII в 1100)

    # Если ни обычный год, ни век не найдены — возвращаем None
    return None

3) Диахронический анализ (временная динамика)

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

Периодизация

Всё это получилось реализовать с помощью простых if, elif, else:

def period_historical(year):
    if year is None:
        return None
    elif year < 1300:  # VIII–XIII век
        return "Киевская Русь / Древнерусское государство"
    elif year < 1700:  # XIV–XVI век
        return "Московский период"
    elif year < 1917:  # XVII–1916
        return "Период Российской империи"
    elif year < 1991:  # 1917–1990
        return "Советский период"
    else:  # после 1991
        return "Постсоветский период"

С помощью pandas загружается CSV с названиями городов и годом их основания. Функция period_historical присваивает каждому городу исторический период: Киевская Русь, Московский период, Российская империя, Советский и Постсоветский. С помощью value_counts() и упорядочивания категорий по хронологии. И, конечно, визуализация:3 matplotlib строит столбчатую диаграмму, где видно количество городов, основанных в каждом периоде.

 Для наглядности столбчатая диаграмма с помощью matplotlib, где видно количество городов, основанных в каждом периоде.
Для наглядности столбчатая диаграмма с помощью matplotlib, где видно количество городов, основанных в каждом периоде.

4) Алфавитный анализ

Скрипт считает, сколько городов начинается с каждой буквы алфавита, и строит столбчатую диаграмму распределения по буквам.

import matplotlib.pyplot as plt

# Получаем первую букву каждого города
df["first_letter"] = (
    df["Город"]             # берем название города
    .str.strip()             # убираем пробелы по краям
    .str.upper()             # приводим букву к верхнему регистру
    .str[0]                  # берём только первую букву
)

# Считаем количество городов на каждую букву и сортируем по алфавиту
letter_counts = (
    df["first_letter"]
    .value_counts()          # подсчёт уникальных букв
    .sort_index()            # сортировка по алфавиту
)

# Строим столбчатую диаграмму
plt.figure()
letter_counts.plot(kind="bar")        # гистограмма
plt.xlabel("Первая буква названия города")  # подпись оси X
plt.ylabel("Количество городов")           # подпись оси Y
plt.title("Распределение названий городов России по начальной букве")  # заголовок
plt.xticks(rotation=0)                  # подписи букв горизонтально
plt.tight_layout()                      # подгонка графика
plt.show()                              # отображение графика
Распределение названий городов России по начальной букве
Распределение названий городов России по начальной букве

Подобная операция была выполнена для определения количества городов, заканчивающихся на какую-либо из букв алфавита.

Распределение названий городов России по последней букве
Распределение названий городов России по последней букве

И снова буква К в победителях) Городов, начинающихся на К: 175 Городов, заканчивающихся на К: 404 (не Error)).

5) Интересные закономерности:

  • Большинство городов основано в период Российской империи;

  • Буква «К» доминирует в названиях городов России, причем не только в начале слов, но и в конце;

  • Городов, начинающихся на Й - 1!!! Городов, заканчивающихся на Й, заметно больше - 80! Так что можно выигрывать за счет этого)));

  • Города-дубликаты! Найдено 27 близняшек))

  • Самые короткие названия (2-3 буквы): Уфа, Ом, Як. Длинные названия состоят из 15–20 букв, например Северодвинск, Новокузнецк, Новосибирск.

Комментарии (5)


  1. maedv
    09.01.2026 14:52

    Минусят вас что-то, а мне понравилось. Простенько, но душевно. И для меня, только начинающего осваивать Питон, как раз в тему для примера. Excel знаю отлично, а вот дальше спотык.
    Для серьезного же исследования, РуВики, конечно, так себе источник. Но понятно, что у вас и цели такой не было.
    А я как-то проводил научное исследование по поиску слова "Котлас" (мой город) и близких к нему по всему земному шару. Крайне много любопытного и неожиданного, особенно на Сахалине и в Америке.
    Статья, если вдруг кому интересно здесь _ttps://kotlasmuzei.ru/dvin-zemlya13.pdf


  1. putnik
    09.01.2026 14:52

    Статья ни о чём, зато со ссылкой на слоп-проект.

    И вот вам задачка: у «Рувики» в списке 1233 городов, а у Википедии, откуда этот список скопирован, только 1125. Найдите общий признак у этих 108 городов.


    1. maedv
      09.01.2026 14:52

      занятно... и тут политика


  1. anonymous
    09.01.2026 14:52


  1. eulampius
    09.01.2026 14:52

    А вы что-нибудь слышали о КЛАДР или ФИАС? )