Парсинг сайта «Приоритета 2030»
Для разных целей может понадобиться сводная таблица с текущими значениями, отражающими показатели университетов — участников программы «Приоритет 2030». Ниже представленное позволяет собрать всё в один файл.
Надо оговориться, что полученная сборка не содержит данные по треку «Дальний Восток», т.к. на начало мая 2023 года, университеты по данному треку отсутствуют на сайте.
import time
import requests
import pandas as pd
# Создаём объект сессии для работы с сайтом
session = requests.session()
# На всякий случай зайдём на главную за печеньками
home_resp = session.get('https://priority2030.ru/')
is_everything_okay = home_resp.status_code == 200
Список университетов
Для начал сформируем список университетов:
university_list_resp = session.get('https://lk.priority2030.ru/api/v0/priority/list')
university_list = pd.DataFrame()
if is_everything_okay and university_list_resp.status_code == 200:
university_list_json = university_list_resp.json()
if university_list_json['status'] == 'success':
university_list = pd.json_normalize(university_list_json['data']['participants'])
# Небольшие улучшения данных
university_list = university_list.rename(columns={'special': 'type'})
university_list['type'] = university_list['type'].apply(lambda x: x if x != '' else 'Базовая часть')
# Сохраняем полученный список университетов
university_list.to_csv('data/university_list.csv', index=False)
# Посмотрим количество по трекам
university_list[['type', 'id']].groupby(by='type').count().rename(columns={'id': 'count'})
count | |
---|---|
type | |
Базовая часть | 73 |
Исследовательское лидерство | 17 |
Территориальное/отраслевое лидерство | 31 |
Показатели программы
Чтобы не перегружать сайт «Приоритет 2030», по каждому университету данный собираются с задержкой в 0,5 секунды (относитесь с заботой к источникам своих данных 🤗), соответственно собирается всё около 1-2 минут.
university_kpis = pd.DataFrame()
for i, university in university_list.iterrows():
university_id = university['id']
resp = session.get(f"https://lk.priority2030.ru/api/v0/priority/{university_id}/indicator")
if is_everything_okay and resp.status_code == 200:
json_data = resp.json()
if json_data['status'] == 'success':
kpi_list = list(range(0, len(json_data['data'])))
for kpi_index in kpi_list:
kpi_type = 'Базовая часть'
elements = pd.json_normalize(json_data['data'][kpi_index]['elements'])
for j, kpi in elements.sort_values(by='indicator').iterrows():
data_ids = {}
# В API какая-то дичь творится...
# Далее будет использоваться только «Отражение факта» и «План», но есть ещё и «Факт» 🤷♂️
for data_id, data_item in enumerate(kpi['data']):
data_ids[data_item['description']] = data_id
for key, value in kpi['data'][data_ids['Отражение факта']]['data'].items():
if value is not None:
plan = kpi['data'][data_ids['План']]['data'][key]
# Выясняем трек по спец. части
if kpi_index > 0:
kpi_postfix = kpi['indicator'].split('_')[1]
kpi_type = 'Исследовательское лидерство' if kpi_postfix == 'с1' else 'Территориальное/отраслевое лидерство'
university_kpis = pd.concat([university_kpis, pd.DataFrame([{
'id': university_id,
'university': university['shortName'],
'type': kpi_type,
'indicator': kpi['indicator'],
'unit': kpi['unit'],
'year': key,
'plan': plan,
'fact': value,
'percent': round(value / plan, 2) if plan else 0,
'description': kpi['description'],
'formula': kpi['formula'],
'calculation_method': kpi['calculationMethod']
}])])
time.sleep(0.5)
# Сохраняем получившуюся сборку
university_kpis.to_csv('data/university_kpis.csv', index=False)
Вроде бы всё 👍 Исходный Jupiter Notebook для данной страницы находится по данной ссылке в Github.
Получившийся набор данных, на момент написания, вы можете ⬇️ скачать по данной ссылке.