Как извлечь данные из категории Digida

Материал из Поле цифровой дидактики
Описание Мы хотим проанализировать тексты, которые хранятся в статья определенной категории поля цифровой дидактики. Есть 2 способа - экспорт статей и использование MediaWiki API
Область знаний Лингвистика, Статистика
Область использования (ISTE)
Возрастная категория 16


Поясняющее видео
Близкие рецепту понятия
Среды и средства для приготовления рецепта: R, Semantic MediaWiki, MediaWiki API


Использовать Экспорт статей

Воспользоваться Служебная:Экспорт и скачать все статьи из категории

Использовать R

library(httr2)
library(jsonlite)
library(tidyverse)
library(ggplot2)
library(quanteda)
library(stopwords)

getwd()
base_url <- "http://digida.mgpu.ru/api.php"

ua <- "digida-research-bot/0.1 (contact: patarakined@mgpu.ru)" ## Agent

#############  Перечень статей в категории

get_category_pages <- function(category_name, limit = 500) {
  params <- list(
    action = "query",
    list = "categorymembers",
    cmtitle = paste0("Category:", category_name),
    cmlimit = limit,
    cmtype = "page",
    format = "json"
  )
  
  response <- request(base_url) %>%
    req_headers(
      `User-Agent` = ua,
      `Api-User-Agent` = ua
    ) %>%
    req_url_query(!!!params) %>%
    req_perform()
  
  data <- resp_body_string(response) %>% fromJSON()
  return(data$query$categorymembers)  # оставить
}

#################
get_page_content <- function(page_title) {
  params <- list(
    action = "query",
    titles = page_title,
    prop = "revisions",
    rvprop = "content",
    format = "json"
  )
  
  response <- request(base_url) %>%
    req_headers(
      `User-Agent` = ua,
      `Api-User-Agent` = ua
    ) %>%
    req_url_query(!!!params) %>%
    req_perform()
  
  data <- resp_body_string(response) %>% fromJSON()
  pages_data <- data$query$pages
  page_info <- pages_data[[1]]
  
  if (!is.null(page_info$revisions) && nrow(page_info$revisions) > 0) {
    page_text <- page_info$revisions$`*`[1]
  } else {
    page_text <- NA
  }
  
  result <- list(
    pageid = page_info$pageid,
    title = page_info$title,
    content = page_text
  )
  return(result)  
}

################ Все тексты категории
get_all_category_content <- function(category_name, limit = 500, sleep_sec = 0.5) {
  pages_df <- get_category_pages(category_name, limit = limit)
  all_content <- vector("list", nrow(pages_df))
  
  for (i in seq_len(nrow(pages_df))) {
    page_title <- pages_df$title[i]
    cat("Working with page", i, "from", nrow(pages_df), ":", page_title, "\n")
    
    tryCatch({
      content <- get_page_content(page_title)
      all_content[[i]] <- content
    }, error = function(e) {
      cat("Mistake in", page_title, ":", e$message, "\n")
    })
    
    Sys.sleep(sleep_sec)
  }
  
  return(all_content)  # 
}

#################
data <- get_all_category_content("Работы историков ИГН", limit = 50)
В результате получаем
> test_all <- get_all_category_content("Работы историков ИГН", limit = 50)
Working with page 1 from 40 : Адаптация европейских новшеств в XV-XVII в Русской повседневности 
Working with page 2 from 40 : Афганская война в советской прессе (1979 - 1989) 
Working with page 3 from 40 : Бургхард Кристоф Миних. Историография 
Working with page 4 from 40 : Взаимодействие опричной и земской администраций

Очистка и подготовка текста

## Only text
texts_vec <- vapply(test_all, function(x) x$content, FUN.VALUE = character(1))

####
clean_mediawiki_text <- function(text) {
  text <- gsub("\\{\\{[^}]*\\}\\}", "", text, perl = TRUE)          # шаблоны {{...}}
  text <- gsub("\\[\\[([^|\\]]*\\|)?([^\\]]+)\\]\\]", "\\2", text)  # [[ссылка|текст]]
  text <- gsub("\\[https?://[^ ]+ ([^\\]]+)\\]", "\\1", text)      # [url текст]
  text <- gsub("https?://\\S+", "", text)                          # голые URL
  text <- gsub("'{2,}", "", text)                                  # ''курсив''
  text <- gsub("={2,}", " ", text)                                 # заголовки ==
  text <- gsub("<[^>]+>", " ", text)                               # HTML‑теги
  text <- gsub("\\s+", " ", text)
  trimws(text)
}

cleaned_vec <- vapply(texts_vec, clean_mediawiki_text, FUN.VALUE = character(1))

corp <- corpus(texts_vec)

# токенизация с базовой очисткой
toks <- tokens(
  corp,
  remove_punct   = TRUE,   # убрать пунктуацию
  remove_symbols = TRUE,
  remove_numbers = TRUE
)

# приводим к нижнему регистру
toks <- tokens_tolower(toks)

# приводим к нижнему регистру
toks <- tokens_tolower(toks)
# стоп-слова (русский + английский, при необходимости)
sw_ru <- stopwords("ru")   # из пакета stopwords
sw_en <- stopwords("en")
toks <- tokens_remove(toks, c(sw_ru, sw_en))
# удалить совсем короткие токены (<=2 символа)
toks <- tokens_keep(toks, min_nchar = 3)


all_tokens <- unlist(toks)
voyant_text <- paste(all_tokens, collapse = " ")

outfile <- "digida_Histoty_for_voyant.txt"
writeLines(voyant_text, outfile, useBytes = TRUE)
В результате мы получили digida_Histoty_for_voyant.txt и использовали его в комбинации с VOYANT Tools на странице Обсуждение_категории:Работы_историков_ИГН

Voyant Tool