Преподаватели, работающие в российских ВУЗах, периодически сталкиваются с необходимостью предоставить администрации список своих научных и учебно-методических работ. Например, для (пере)избрания на должность, присвоения звания и т. д. Формат представления информации, форма № 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}\.', content) # форма записи года ' 2020.' if not Ys: Ys = findall(r'\s\d{4}', content) # форма записи года ' 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, где и подвергнуть окончательным правкам типа изменения ширин столбцов, выбора шрифтов и т.д.
ссылка на оригинал статьи https://habr.com/ru/post/558190/
Добавить комментарий