Проект по анализу корпуса текстов

Исследование биографий русских писателей на основе методов анализа текстов

Автор
принадлежность

Зеленкова Анастасия

Университет ИТМО

Дата публикации

18 февраля 2026 г.

1 Введение

Коротко о данных

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

1.1 Библиотеки

library(rvest)
library(tidyverse)
library(stopwords)
library(udpipe)
library(tm)
library(topicmodels)
library(tidytext)
library(ggplot2)
library(stringr)
library(purrr)
library(wordcloud)
library(RColorBrewer)
library(quanteda)
library(quanteda.textstats)

2 Сбор и обработка данных

closeAllConnections()

url <- "https://ru.wikipedia.org/wiki/Категория:Русские_писатели"

page <- tryCatch(
  read_html(url),
  error = function(e) NULL
)
author_nodes <- page %>%
  html_nodes("div.mw-category a")

names <- author_nodes %>%
  html_text() %>%
  str_squish()
links <- author_nodes %>%
  html_attr("href") %>%
  str_c("https://ru.wikipedia.org", .)
df_authors <- tibble(
  name = names,
  link = links
) %>%
  distinct(name, .keep_all = TRUE) %>%
  filter(str_detect(name, ","))
Sys.sleep(0.2)

Вывод по результатам выполнения чанка
1. Закрыты активные соединения с помощью closeAllConnections(), чтобы при парсинге не вызывались ошибки соединений.
2. Загружена HTML-страница категории «Русские писатели».
3. Извлечены HTML-узлы, содержащие имена авторов.
4. Получены и очищены текстовые значения ФИО писателей.

pattern <- "Библиография.*|Сочинения.*|Публикации.*|Написал множество статей.*|Среди произведений.*"

get_bio <- function(link) {
  tryCatch({
    
    full_url <- ifelse(
      str_starts(link, "/wiki/"),
      paste0("https://ru.wikipedia.org", link),
      link
    )
    
    page <- read_html(full_url)
    
    bio <- page %>%
      html_nodes("div.mw-parser-output > p") %>%
      html_text() %>%
      paste(collapse = " ") %>%
      str_replace_all("[\r\n\t]", " ") %>%
      str_remove_all("\\[\\d+\\]") %>%
      str_remove(pattern) %>%
      str_squish()
    
    if (bio == "") NA_character_ else bio
    
  }, error = function(e) NA_character_)
}

df_authors$biographies <- map_chr(df_authors$link, function(x) {
  Sys.sleep(0.3)
  get_bio(x)
})

df_authors <- df_authors %>%
  filter(!is.na(biographies),
         biographies != "")

По итогам выполнения кода были выполнены следующие действия:

  1. Выведены первые две строки датафрейма df_authors для проверки корректности структуры данных.
  2. Задан шаблон pattern для удаления разделов «Библиография», «Сочинения» и «Публикации» из текста.
  3. Промежуточным шагом были извлечены ссылки на биографии авторов из верстки,
  4. Также произведена очистка от служебных CSS и HTML символов с помощью регулярных выражений

Пример структуры датафрейма с биографиями

head(df_authors$biographies, 2)
[1] "Бори́с Алексе́евич Ана́шенков (род. 15 января 1931, Москва, РСФСР, СССР) — советский и российский писатель. Родился 15 января 1931 года в Москве. В 1953 году окончил Московский институт международных отношений. Печатался с 1957 года. Первые книги Анашенкова — сборники рассказов и повестей, такие как «Сестрёнка» (1959) и «Чужая жизнь» (1962). Позднее переходит к очерку, преимущественно о рабочем классе, например «Когда рядом товарищ» (1964), «Пока гром не грянет» (1966). Во многих статьях писал о проблемах литературы о рабочем классе эпохи научно-технической революции, например, «И встанут новые бойцы. Рабочий в современной зарубежной литературе» (1976), «Этот простой сложный человек: научно-техническая революция — социальный прогресс — литература» (1977)."                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
[2] "Анна Алексеевна Бабина (11 декабря 1990, Ленинград) — российская писательница. Родилась в Ленинграде. Окончила юридический факультет СПбГУ по специальности «уголовный процесс, криминалистика, оперативно-розыскная деятельность». Живёт в Санкт-Петербурге. Работает юристом. С 2018 года занимается литературным творчеством. Публиковалась в журналах: «Урал», «Юность», «Нева», «Лиterraтура», «Север», «Нижний Новгород» и др. Лауреат российских и международных конкурсов. Участница Форума молодых писателей России, стран СНГ и зарубежья «Липки» (2023). В октябре 2024 года в издательстве «Азбука-Аттикус» вышел дебютный роман Анны «Презумпция вины». В том же году в издательстве «Перископ-Волга» вышел сборник короткой прозы «Коэффициент сцепления». С 2024 года — редактор отдела прозы в литературном интернет-журнале «ПРОЛИТКУЛЬТ». Литературным учителем считает Алексея Иванова. В 2025 году с романом «Знаки безразличия» стала лауреатом Премии «Лицей» имени А.С. Пушкина. Иван Родионов в предисловии к двум рассказам Анны Бабиной говорит о яркой индивидуальности её стиля. По суждению критика, ей удаётся описать узнаваемые и даже обыденные ситуации проникновенными, берущими за душу словами, не впадая при этом в сентиментальность. Литературный критик Елена Нещерет отмечает использование писателем того богатого опыта, который дала ей работа практикующим юристом . Писатель Сергей Шаргунов описывает роман «Знаки безразличия» как крепкую работу, где искусный и умелый детективный сюжет изложен с психологической глубиной и человечностью."
df_authors <- df_authors %>%
  mutate(
    biographies = biographies %>%
      
      # Удаление остатков CSS и HTML разметки, одиночных тех. символов с помощью регуярных выражений, так как не все удалилось на предыдущем шаге.
      str_remove_all("\\.ts-[^ ]*") %>%
      str_remove_all("\\.reference-[^ ]*") %>%
      str_remove_all("body\\.[^ ]*") %>%
      str_remove_all("\\{[^}]*\\}") %>%
      str_remove_all(",?\\s*\\.[^ ]+") %>%
      str_remove_all("\\s+\\.") %>%
      str_squish()
  )
head(df_authors$biographies, 2)
[1] "Бори́с Алексе́евич Ана́шенков (род. 15 января 1931, Москва, РСФСР, СССР) — советский и российский писатель. Родился 15 января 1931 года в Москве. В 1953 году окончил Московский институт международных отношений. Печатался с 1957 года. Первые книги Анашенкова — сборники рассказов и повестей, такие как «Сестрёнка» (1959) и «Чужая жизнь» (1962). Позднее переходит к очерку, преимущественно о рабочем классе, например «Когда рядом товарищ» (1964), «Пока гром не грянет» (1966). Во многих статьях писал о проблемах литературы о рабочем классе эпохи научно-технической революции, например, «И встанут новые бойцы. Рабочий в современной зарубежной литературе» (1976), «Этот простой сложный человек: научно-техническая революция — социальный прогресс — литература» (1977)."                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
[2] "Анна Алексеевна Бабина (11 декабря 1990, Ленинград) — российская писательница. Родилась в Ленинграде. Окончила юридический факультет СПбГУ по специальности «уголовный процесс, криминалистика, оперативно-розыскная деятельность». Живёт в Санкт-Петербурге. Работает юристом. С 2018 года занимается литературным творчеством. Публиковалась в журналах: «Урал», «Юность», «Нева», «Лиterraтура», «Север», «Нижний Новгород» и др. Лауреат российских и международных конкурсов. Участница Форума молодых писателей России, стран СНГ и зарубежья «Липки» (2023). В октябре 2024 года в издательстве «Азбука-Аттикус» вышел дебютный роман Анны «Презумпция вины». В том же году в издательстве «Перископ-Волга» вышел сборник короткой прозы «Коэффициент сцепления». С 2024 года — редактор отдела прозы в литературном интернет-журнале «ПРОЛИТКУЛЬТ». Литературным учителем считает Алексея Иванова. В 2025 году с романом «Знаки безразличия» стала лауреатом Премии «Лицей» имени А Пушкина. Иван Родионов в предисловии к двум рассказам Анны Бабиной говорит о яркой индивидуальности её стиля. По суждению критика, ей удаётся описать узнаваемые и даже обыденные ситуации проникновенными, берущими за душу словами, не впадая при этом в сентиментальность. Литературный критик Елена Нещерет отмечает использование писателем того богатого опыта, который дала ей работа практикующим юристом Писатель Сергей Шаргунов описывает роман «Знаки безразличия» как крепкую работу, где искусный и умелый детективный сюжет изложен с психологической глубиной и человечностью."

2.1 Выбор 50 случайных записей для последующего сопоставления автор-биография

df_sample <- df_authors %>%
  dplyr::filter(!is.na(biographies)) %>%  
  dplyr::slice_sample(n = 50, replace = FALSE) %>%  
  dplyr::as_tibble()  
sample_rows <- df_sample %>% slice_head(n = 1)

Пример сопоставления полученных данных автор: библиография

set.seed(123) 
i <- sample(1:nrow(df_sample), 1)

cat("Автор:", df_sample$name[i], "\n\n")
Автор: Бакинский, Виктор Семёнович 
cat("Биография:\n", df_sample$biographies[i], "\n")
Биография:
 Виктор Семёнович Бакинский (7 ноября 1907 — 6 марта 1990) — писатель и литературовед. Участник Великой Отечественной войны. Виктор Семёнович Бакинский родился в 1907 году в семье рабочего. В 1931 году окончил филологический факультет ЛГУ. Литературную деятельность начал в 1930-х годах. В 1934 году опубликовал первый рассказ «Перепечь». Преподавал в Вологодском педагогическом институте и Карело-финском университете в Петрозаводске. Когда началась Великая Отечественная война, как доброволец вступил в народное ополчение. Служил на Ленинградском фронте. После окончания войны продолжил преподавательскую деятельность. Среди его учеников были С. Довлатов, В. Губин, И. Ефимов и другие. Был членом Союза писателей. Автор статей о творчестве русских писателей. В 1952 году опубликовал монографию «Маяковский в борьбе за социалистический реализм». Виктор Семёнович Бакинский умер в 1990 году. Был похоронен на Северном кладбище. 

2.2 Лемматизация биографий

ud_model <- tryCatch({
  if(!file.exists("russian-ud-2.5-191206.udpipe")) {
    model_file <- udpipe_download_model(language = "russian")$file_model
  } else {
    model_file <- "russian-ud-2.5-191206.udpipe"
  }
  udpipe_load_model(model_file)
}, error = function(e) {
  stop("Не удалось загрузить модель UDPIPE: ", e$message)
})
df_sample <- df_sample %>%
  mutate(
    lemmatized = map_chr(biographies, ~{
      tryCatch({
        annotation <- udpipe_annotate(ud_model, x = .x)
        df_ann <- as.data.frame(annotation)
        df_ann %>%
          filter(!upos %in% c("PUNCT", "SYM")) %>%   
          pull(lemma) %>%
          paste(collapse = " ")
      }, error = function(e) {
        NA_character_ 
      })
    })
  )

set.seed(42)
sample_author <- df_sample %>% slice_sample(n = 1)
cat("Автор:", sample_author$name, "\n")
Автор: Певцов, Василий Герасимович 
cat("Биография (оригинал):\n", sample_author$biographies, "\n\n")
Биография (оригинал):
 Василий Герасимович Певцов (1836—1908) — протоиерей Русской православной церкви, педагог и духовный писатель. Василий Певцов родился в 1836 году. Получив необходимые знания в духовных учебных заведениях стал магистром Санкт-Петербургской духовной академии; преподавал церковное право в Императорском училище правоведения и в Александровской военно-юридической академии. В 1871 году В. Г. Певцов открыл народные чтения при педагогическом музее военно-учебных заведений в Соляном городке. Василий Герасимович Певцов скончался в 1908 году. Из упомянутых выше чтений Певцова были напечатаны следующие: Другие изданные отдельно труды Певцова: 
cat("Биография (лемматизированная):\n", sample_author$lemmatized, "\n")
Биография (лемматизированная):
 Василий Герасимович Певцы 1836 1908 протоиь русский православный церковь педагог и духовный писатель Василий Певцы родиться в 1836 год получить необходимый знание в духовный учебный заведение стать магистр Санкт-Петербургский духовный академия преподавать церковный право в Императорский училище правоведение и в Александровский военно-юридический академия в 1871 год В. Г. Певцы открыть народный чтение при педагогический музей военно-учебный заведение в Соляный городок Василий Герасимович Певцы скончаться в 1908 год из упомянутой высокий чтение Певцова быть напечатать следующий другой издать отдельно труд Певцова 

2.3 Визуализация

3 Облако слов по биографиям авторов

# Стоп слова (русские + добавленные, которые не отражают специфику выбранной области)
custom_stopwords <- c(
  stopwords("russian"),
  "год", "который", "родиться", "свой", "также", "почему", "—", "время", "работать", "в", "на"
)
corpus <- Corpus(VectorSource(df_sample$lemmatized)) %>%
  tm_map(content_transformer(tolower)) %>%
  tm_map(removeNumbers) %>%
  tm_map(removePunctuation) %>%
  tm_map(stripWhitespace) %>%
  tm_map(removeWords, custom_stopwords) %>%
  tm_map(content_transformer(function(x) gsub("[^а-яё\\s]", " ", x)))
dtm <- DocumentTermMatrix(corpus)
m <- as.matrix(dtm)
word_freq <- sort(colSums(m), decreasing = TRUE)

top_words <- head(word_freq, 100)
set.seed(123)
wordcloud(
  words = names(top_words),
  freq = top_words,
  min.freq = 2,
  scale = c(3, 0.5),
  colors = brewer.pal(8, "Dark2"),
  random.order = FALSE,
  rot.per = 0.25
)

В этом блоке была выполнена визуализация наиболее часто встречающихся слов в биографиях авторов. Перед построением облака слов были выполнены следующие шаги: - Приведение текста к нижнему регистру
- Удаление чисел, пунктуации и лишних символов
- Исключение стандартных стоп-слов и часто встречающихся малоинформативных слов
- Подсчет частот слов и выбор топ-100 наиболее популярных лексем
В результате получено облако слов, где более крупные слова встречаются чаще, что позволяет визуально определить ключевые темы и термины в биографиях.

4 Тематическое моделирование биографий авторов

dtm_lda <- removeSparseTerms(dtm, 0.95) 

# LDA с 4 темами
set.seed(123)
lda_model <- LDA(dtm_lda, k = 4, control = list(seed = 123))
topics <- tidy(lda_model, matrix = "beta")

# Топ-10 слов по каждой теме
top_terms <- topics %>%
  group_by(topic) %>%
  slice_max(beta, n = 10) %>%
  ungroup() %>%
  arrange(topic, -beta)

# Визуализация топ-слов по темам
ggplot(top_terms, aes(x = reorder_within(term, beta, topic), y = beta, fill = factor(topic))) +
  geom_col(show.legend = FALSE) +
  facet_wrap(~ topic, scales = "free") +
  coord_flip() +
  scale_x_reordered() +
  theme_minimal() +
  ggtitle("Топ-10 слов в каждой теме (LDA)")

По результатам моделирования на корпусе текстов было выделено 4 устойчивые темы:

  • Личная жизнь и происхождение авторов
  • Ориентир на издательский аспект и жанровую литературу
  • Фокус на публикационной активности и профессиональном признании.
  • Институциональная принадлежность авторов и историческая география.

Популярные биграммы в биографиях

# корпус quanteda из лемм
q_corpus <- corpus(df_sample$lemmatized)
tokens <- tokens(q_corpus, remove_punct = TRUE, remove_symbols = TRUE)
tokens <- tokens_remove(tokens, custom_stopwords)

# Поиск 2-словных коллокаций
tokens_bigrams <- tokens_ngrams(tokens, n = 2)

# матрица "документ-термин"
dfm_bigrams <- dfm(tokens_bigrams)

# Частота биграмм
freq_bigrams <- textstat_frequency(dfm_bigrams, n = 20)

# Визуализация самых популярных биграмм
ggplot(freq_bigrams, aes(x = reorder(feature, frequency), y = frequency)) +
  geom_col(fill = "steelblue") +
  coord_flip() +
  theme_minimal() +
  labs(title = "Топ-20 биграмм (популярные выражения лемм)", x = "Выражение", y = "Частота")

В этом блоке сложно описать темы на основе сформированного списка слов, так как датафрейм всегда уникальный из-за случайной выборки 50 записей # Распределение годов рождения авторов

df_births <- df_authors %>%
  mutate(
    birth_fragment = str_extract(
      biographies,
      "Родил[а-я]*[^.]{0,100}"
    ),
    birth_year = str_extract(
      birth_fragment,
      "\\b(1[6-9]\\d{2}|20\\d{2})\\b"
    ),
    
    birth_year = as.numeric(birth_year)
  ) %>%
  filter(!is.na(birth_year))
n <- nrow(df_births)
iqr_value <- IQR(df_births$birth_year)
bin_width <- 2 * iqr_value / (n^(1/3))
bin_width <- round(bin_width)
if(bin_width <= 0) bin_width <- 10
ggplot(df_births, aes(x = birth_year)) +
  geom_histogram(
    binwidth = bin_width,
    fill = "steelblue",
    color = "white"
  ) +
  theme_minimal() +
  labs(
    title = "Распределение авторов по годам рождения",
    subtitle = paste("Ширина интервала", bin_width, "лет"),
    x = "Год рождения",
    y = "Количество авторов"
  )

В этом блоке я проанализировала годы рождения авторов, извлечённые из их биографий после слов “родился”/“родилась”. Основные шаги:

  • Извлечение года рождения с помощью регулярных выражений
  • Игнорирование биографий без указанного года рождения
  • Построение гистограммы распределения годов рождения
  • Автоматическое определение оптимальных диапазонов (бинов) методом Диксона, чтобы сгруппировать годы в интервалы
  • Визуализация частоты рождения авторов по этим интервалам

Результат позволяет увидеть, в какие периоды родилось больше всего авторов и как распределены годы рождения в выборке

Сноски

  1. Писатель- автор художественных произведений в прозе или поэзии↩︎