[Python, HTML] Форма № 16

Автор Сообщение
news_bot ®

Стаж: 6 лет 3 месяца
Сообщений: 27286

Создавать темы news_bot ® написал(а)
19-Май-2021 16:32

Преподаватели, работающие в российских ВУЗах, периодически сталкиваются с необходимостью предоставить администрации список своих научных и учебно-методических работ. Например, для (пере)избрания на должность, присвоения звания и т. д. Формат представления информации, форма № 16, разработан невесть когда и до сих пор используется в бюрократических недрах Министерства Науки и Высшего Образования РФ. Мне стало лень заполнять эту форму вручную и я написал небольшой python сценарий, который генерирует нужную таблицу на основе информации, полученной из научной электронной библиотеки elibrary.ru. Возможно, кому-то это будет интересно, так что ниже приведено описание этой процедуры...
Итак, для начала нужно зайти на сайт elibrary.ru, авторизоваться, перейти в раздел «авторам» и далее в «мои публикации». Справа на экране есть колонка «инструменты», в которой есть кнопка «Вывести на печать список публикаций автора». Нажимаем на нее и в отдельном окне получаем таблицу со списком публикаций, которую сохраняем себе на диск в виде html-файла, который для простоты назовем index.html. Каждая публикация в этом списке выглядит примерно так:
Строка таблицы от elibrary.ruОднако согласно приказу №268 Минобрнауки РФ (приложение №3 на с. 52) таблица зачем-то должна выглядеть иначе:
Строка таблицы в соответствии с формой №16Сценарий для преобразования формата таблицы основан на использовании библиотеки 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, где и подвергнуть окончательным правкам типа изменения ширин столбцов, выбора шрифтов и т.д.
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_python, #_html, #_vuz (ВУЗ), [url=https://torrents-local.xyz/search.php?nm=%23_forma_№16&to=0&allw=0&o=1&s=0&f%5B%5D=820&f%5B%5D=959&f%5B%5D=958&f%5B%5D=872&f%5B%5D=967&f%5B%5D=954&f%5B%5D=885&f%5B%5D=882&f%5B%5D=863&f%5B%5D=881&f%5B%5D=860&f%5B%5D=884&f%5B%5D=865&f%5B%5D=873&f%5B%5D=861&f%5B%5D=864&f%5B%5D=883&f%5B%5D=957&f%5B%5D=859&f%5B%5D=966&f%5B%5D=956&f%5B%5D=955]#_forma_№16 (Форма №16)[/url], #_beautifulsoup, #_python, #_html
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 20-Май 03:16
Часовой пояс: UTC + 5