Форма № 16
- четверг, 20 мая 2021 г. в 00:37:40
Преподаватели, работающие в российских ВУЗах, периодически сталкиваются с необходимостью предоставить администрации список своих научных и учебно-методических работ. Например, для (пере)избрания на должность, присвоения звания и т. д. Формат представления информации, форма № 16, разработан невесть когда и до сих пор используется в бюрократических недрах Министерства Науки и Высшего Образования РФ. Мне стало лень заполнять эту форму вручную и я написал небольшой python сценарий, который генерирует нужную таблицу на основе информации, полученной из научной электронной библиотеки elibrary.ru. Возможно, кому-то это будет интересно, так что ниже приведено описание этой процедуры...
Итак, для начала нужно зайти на сайт elibrary.ru, авторизоваться, перейти в раздел «авторам» и далее в «мои публикации». Справа на экране есть колонка «инструменты», в которой есть кнопка «Вывести на печать список публикаций автора». Нажимаем на нее и в отдельном окне получаем таблицу со списком публикаций, которую сохраняем себе на диск в виде html-файла, который для простоты назовем index.html
. Каждая публикация в этом списке выглядит примерно так:
Однако согласно приказу №268 Минобрнауки РФ (приложение №3 на с. 52) таблица зачем-то должна выглядеть иначе:
Сценарий для преобразования формата таблицы основан на использовании библиотеки BeautifulSoup, с которой я ознакомился весьма поверхностно и использовал первый раз в жизни. Вот что у меня вышло:
#!/usr/bin/env python3
from bs4 import BeautifulSoup
from random import randint
from re import findall
YFrom, YTo = 2015, 2020 # фильтр по годам публикаций
def NP(s): # функция для непредвзятого определения количества страниц в статье
pages = s.split()[-1]
if '-' in pages:
P = pages.split('-')
np = 1 + int(float(P[1])-float(P[0]))
else:
np = randint(5, 10)
return '%d' % np # возвращает строку с числом
def Year(s, FROM, TO): # функция для отбора по году публикации
Ys = findall(r'\s\d{4}\.', s) # форма записи года ' 2020.'
if not Ys: Ys = findall(r'\s\d{4}', s) # форма записи года ' 2020'
if not Ys: return False # если ничего не нашлось - выбрасываем
for y in Ys: Y = int(float(y)) # в случае более чем одного совпадения берем последнее
if Y<FROM or Y>TO: return False
else: return True
with open('index.html', 'r') as fp:
soup = BeautifulSoup(fp, 'html.parser') # загружаем исходный файл
soup.head.style.decompose() # убираем заголовок, css и т.д.
aname = soup.title.get_text().split('-')[1] # имя автора
aname = f'СПИСОК опубликованных и приравненных к ним научных и учебно-методических работ {aname:s}\n'
soup.title.string = aname # новый заголовок
soup.find('span').string = aname # новый заголовок
soup.find('i').decompose() # убираем что-то лишнее
soup.find('table').decompose() # находим и удаляем первую таблицу
table = soup.find('table') # находим вторую таблицу
table['border'] = 1 # меняем оформление
table['width'] = '100%' # меняем ширину
N = 1 # новый счетчик
rows = table.find_all('tr') # ищем все строки в таблице
for i in range(len(rows)): # цикл для замены содержимого строк
cols = rows[i].find_all('td') # ищем все столбцы
if len(cols)==3 and cols[1].find('span'): # проверка на соответствие стандартному шаблону
content = cols[1].get_text() # читаем запись из второго столбца
title = cols[1].find('span').get_text() # тут название
authors = cols[1].find('i').get_text() # тут авторы
cites = int(cols[2].get_text()) # количество цитирований статьи
content = content.replace(title, '') # убираем навзвание, убираем список авторов:
content = content.replace(authors, '') # в content остаются только выходные данные
thesis = content.replace('В сборнике: ','') # далее идет определение типа публикации
abbook = content.replace('В книге: ','') #
if thesis != content: #
title += ' (тезисы)'; content = thesis #
elif abbook != content: #
title += ' (тезисы)'; content = abbook #
else: #
if 'автореф' in content: title+= ' (монография)'#
elif 'диссер' in content: title+= ' (монография)'#
else: title += ' (статья)' #
authors = authors.split(', ') # получаем список авторов
if cites<10 or not Year(content, YFrom, YTo): # некоторые записи можно выбросить
rows[i].decompose() #
else: # для других - определить кол-во соавторов
anumber = len(authors)
if anumber<5: PS = ''
else: PS = f' и др., всего {anumber:d} чел.'
authors = ', '.join(authors[0:5]) + PS
cols[0].string = f'{N:3d}' # показания счетчика
cols[1].string = title # название
cols[2].string = "печ." # тип работы
for info in [content, NP(content), authors]: # еще три столбца
A = soup.new_tag('td'); A.string = info ; rows[i].append(A)
N+= 1
else:
rows[i].decompose()
tr = soup.new_tag('tr') # вставляем заголовок таблицы
names = ['№ п\п', 'Наименование работы, её вид', 'Форма работы', 'Выходные данные', 'Объём в п.л. или с.', 'Соавторы']
for name in names:
th = soup.new_tag('th')
th.string = name
tr.append(th)
table.insert(0, tr)
with open('table.html', 'w', encoding='utf-8') as fp: fp.write(str(soup))
Для выполнения задачи нужно запустить сценарий в папке, в которой содержится файл index.html
, в который мы сохранили таблицу с elibrary.ru. На выходе генерируется файл table.html
, который можно легко загрузить в google docs, где и подвергнуть окончательным правкам типа изменения ширин столбцов, выбора шрифтов и т.д.