close

Вход

Забыли?

вход по аккаунту

Соломченко Дарья Олеговна. Разработка электронного справочника научных журналов

код для вставки
2
3
СОДЕРЖАНИЕ
АННОТАЦИЯ ………………………………………………………….
5
ABSTRACT ……………………………………………………………
7
ВВЕДЕНИЕ ……………………………………………………………..
8
ГЛАВА 1. МЕТОДЫ ОЦЕНКИ КАЧЕСТВА НАУЧНЫХ
ЖУРНАЛОВ ……………………………………………………………
11
1.1 Понятие и критерии научного журнала ……………………….
11
1.2 Определение импакт-фактора научного издания …………….
13
1.3 Источники данных о научных изданиях ………………………
16
1.4 Способы оценки качества научных журналов ………………...
19
ГЛАВА 2. СОЗДАНИЕ БАЗЫ ДАННЫХ СПРАВОЧНИКА ……….
35
2.1 Структуры таблиц базы данных ………………………………..
35
2.2 Импорт данных о журналах в базу веб-приложения ………….
42
ГЛАВА 3. РАЗРАБОТКА ВЕБ-ПРИЛОЖЕНИЯ ……………………..
45
3.1 Архитектура проекта ……………………………………………
45
3.2 Разработка дизайна проекта …………………………………….
47
3.3 Проектирование веб-интерфейса ……………………………….
49
ЗАКЛЮЧЕНИЕ ………………………………………………………
62
СПИСОК ЛИТЕРАТУРЫ …………………………………………...
65
ПРИЛОЖЕНИЕ. Исходный код проекта …………………………..
67
4
АННОТАЦИЯ
Магистерская диссертация на тему «Разработка электронного справочника
научных журналов» содержит 131 страница текста, рисунков – 8, таблиц – 2,
использованных источников - 35.
Предложенная разработанная программа позволит не только облегчить
процесс поиска научных журналов в специализированных информационных
системах, но и автоматически интегрирует данные в базу.
Ключевые слова: электронный справочник, научный журнал, критерии
оценки, программное обеспечение, база данных.
Предмет исследования. Разработка электронного справочника научных
журналов.
Объект исследования. Электронные справочники.
Целью работы является разработка электронного справочника научных
журналов для информационно-аналитической системы мониторинга научноисследовательской работы университета
Задачи работы:
●
Определить критерии оценки качества научных журналов.
●
Спроектировать базу данных справочника.
●
Создать веб-приложение для работы с базой данных справочника.
Метод исследования. Для исследования применялись следующие методы:
изучение и анализ литературы, синтез, сравнительный анализ, объектноориентированный анализ и проектирование.
Результаты
работы.
В
магистерской
диссертации
разработано
и
реализовано веб-приложение на основе созданной базы данных для поиска
научных журналов, описываются его структура и возможности.
5
Работа имеет теоретическое и практическое значение, т.к. разработано
веб-приложение, предназначенное для поиска научных журналов, которое
поможет научным работникам определить качество журнала, его значимость и
ценность для науки.
6
ABSTRACT
Master's thesis on "Development of electronic reference books of scientific
journals" contains 131 pages of text, figures-8, tables-2, sources-35.
The proposed program will not only facilitate the process of finding scientific
journals in specialized information systems, but also automatically integrates the data
into the database.
Key words: electronic reference book, scientific journal, evaluation criteria,
software, database.
Subject of research. Development of an electronic directory of scientific journals.
Object of research. Electronic reference book.
The aim of the work is to develop an electronic directory of scientific journals for
information and analytical monitoring system of research work of the University
Work tasks:
● Determine the criteria for assessing the quality of scientific journals.
● Design the directory database.
● Create a web application to work with the directory database.
Method of research. The following methods were used for the study: the study and
analysis of literature, synthesis, comparative analysis, object-oriented analysis and
design.
Result of work. In the master's thesis developed and implemented a web
application based on the database created to search for scientific journals, describes its
structure and capabilities.
The work is of theoretical and practical importance, as developed web application
designed to search for scientific journals, which will help researchers to determine the
quality of the journal, its importance and value for science.
7
ВВЕДЕНИЕ
В
настоящее
время
каждому
научному
сотруднику
рекомендуется
публиковаться в специализированных научных изданиях, одобренных научным
сообществом. Чаще всего ему просто требуется из огромного объёма информации
о научных журналах выбрать наиболее подходящие издания для публикации
собственной статьи или научной работы [1]. Несмотря на большое количество баз
данных, содержащих информацию о научных журналах, очень трудно бывает
сориентироваться среди потока данных, которые хоть и отражают искомые
сведения, но часто содержат много информации, которая не нужна конечному
пользователю.
Актуальность темы заключается в том, что требуется программный
инструмент для автоматизированного получения информации о научных
журналах, которую в обычном случае пришлось бы проверять вручную с затратой
большого количества времени. Разработанный справочник позволит не только
облегчить
процесс
поиска
научных
журналов
в
специализированных
информационных системах, но и автоматически интегрирует данные в базу.
Каждый журнал предварительно проверяется на принадлежность к перечню
рецензируемых научных изданий, рекомендованных для публикации научных
результатов, благодаря чему можно практически моментально получить результат
и узнать необходимую информацию об интересующем научном издании.
Предмет исследования. Разработка электронного справочника научных
журналов.
Объект исследования. Электронные справочники.
Целью работы является разработка электронного справочника научных
журналов для информационно-аналитической системы мониторинга научноисследовательской работы университета
Задачи работы:
1. Определить критерии оценки качества научных журналов.
2. Спроектировать базу данных справочника.
3. Создать веб-приложение для работы с базой данных справочника.
8
На первом этапе следует ознакомиться с понятием научного журнала и
разработать критерии для добавления издания в информационную систему.
На втором этапе следует познакомиться с международными базами данных и
решить, какие данные о научных журналах из них стоит включать в базу данных, а
какими можно пренебречь. Необходимо провести исследование, которое покажет,
как правильно заполнить базу и получить информацию из информационноаналитических систем так, чтобы сервера, на которых хранятся данные, выдавали
сведения о конкретном журнале.
На третьем этапе необходимо составить программу на каком-нибудь языке
программирования для ЭВМ. При этом к языку предъявляются определенные
требования – такие, как распространенность языка, наличие динамической
типизации, поддержка юникода (заранее известно, что большинство журналов в
базе имеют русскоязычные названия), а также модульность и универсальность, без
чего не обойтись в процессе выполнения работы. Далее следует выполнить
тестирование программы. Необходимо провести также проверку на предмет
корректного сохранения данных в базу.
На последнем этапе проводится анализ полученных данных о научных
журналах и их сравнение с той информацией, которая имелась о них ранее.
Происходит
сохранение
данных
о
научных
журналах
в
созданную
информационную систему. В итоге получается база данных, содержащая только
корректную и необходимую информацию об изданиях. На данном этапе
производится разработка интерфейса для созданной базы данных о журналах,
который должен быть интуитивно понятным для конечного пользователя.
Структура и краткое содержание работы. Квалификационная работа
состоит из введения, трёх глав, заключения, списка использованной литературы и
приложений.
В главе 1 даётся понятие научного журнала, а также указываются признаки,
по которым его можно отличить от другой периодической литературы.
Раскрывается понятие импакт-фактора и его важности для научного сообщества.
Описываются основные международные специализированные базы данных и
9
индексы цитирования, из которых была взята информация для работы с
журналами. Предлагаются различные способы оценки качества научных
журналов.
В главе 2 идет речь о моделировании базы данных, которая впоследствии
будет содержать структурированную информацию о научных журналах.
В главе 3 описывается разработка и реализация веб-приложения на основе
созданной базы данных, описываются его структура и возможности.
В заключении излагаются результаты проделанной работы.
В
приложении
приведены
листинги
обеспечения.
10
разработанного
программного
ГЛАВА 1. МЕТОДЫ ОЦЕНКИ КАЧЕСТВА НАУЧНЫХ ЖУРНАЛОВ
1.1 Понятие и критерии научного журнала
Прежде чем познакомиться с понятием научного журнала, следует иметь
четкое представление о том, что такое журнал и чем научный журнал отличается
от обычного.
Рассмотрим понятие журнала согласно ГОСТ 7.60–90 «Издания. Основные
виды. Термины и определения». Журнал - периодическое журнальное издание,
содержащее статьи или рефераты по различным общественно-политическим,
научным, производственным и другим вопросам, литературно-художественные
произведения, имеющее постоянную рубрикацию, официально утвержденное в
качестве данного вида издания.
Главное отличие научного журнала от любого другого периодического
издания состоит в том, что все статьи перед публикацией в нём проходят
рецензирование, о чём подробнее упоминается в самом его понятии.
Научный журнал (рецензируемый или реферируемый научный журнал) —
журнал, в котором присылаемые статьи перед публикацией представляются на
рецензирование независимым специалистам, которые обычно не входят в состав
редакции журнала и ведут исследования в областях, близких с тематикой статьи.
Научный журнал является одной из главных составляющих научной
литературы. Рецензирование материалов выполняется для того, чтобы постараться
оградить читателей от методологических ошибок или фальсификаций. Чтобы
оригинальное научное исследование было напечатано в таком журнале, оно
должно быть написано в соответствии с требованиями его редколлегии. После
опубликования в рецензируемом издании статья становится доступной не только
для всех ученых без ограничения, но также для реферирования и включения
сведений о ней в базы информационных аналитических систем: реферативные
журналы, системы поиска научно-технической информации [1]. Соблюдение
последнего условия необходимо для того, чтобы сведения, содержащиеся в статье,
были доступны для широкого научного сообщества. Печати в научном журнале
11
может предшествовать печать препринта (предпубликации), выпускаемого в свет
до публикации статей для обсуждения или уточнения полученных результатов
работ.
Рассмотрим основные признаки научных журналов. К таковым относятся:
1)
2)
3)
4)
узкоспециализированность
структурированность
стандартизированность
верифицируемость
Под узкоспециализированностью имеется в виду то, что каждый научный
журнал публикует статьи только по заданной редакционной коллегией тематике,
вследствие чего научные работы должны быть все связаны с темой данного
издания. Тема может касаться какой-либо научной отрасли или групп научных
специальностей,
а
также
иметь
привязку
к
учебному
производственной организации. К примеру, журнал
заведению
или
“Философия и науки”
публикует материалы, относящиеся только к философским наукам, а журнал
“Ученые записки Петрозаводского государственного университета” содержит
статьи, написанные в данном учебном заведении и нигде больше. Узкая
специализация журнала помогает научному работнику получить сведения об
исследованиях, связанных с его областью или местом работы [2].
Под структурированностью научного журнала понимается наличие четкой и
понятной структуры издания. Каждый научный журнал обязан иметь правильно
оформленный титульный лист, а также содержание, подразумевающее список
научных статей, рядом с которыми в алфавитном порядке указываются их авторы,
введение, знакомящее с основными исследованиями, содержащимися в нем, и
заключение, подводящее итог развитию той области, в которой специализируется
данное издание.
Стандартизированность
определенного
стандарта,
научного
которому
журнала
следует
подразумевает
данный
журнал.
наличие
Стандарт
применяется не только к общему виду издания, но также структуре текста работ и
к языку, которым оно написано [2]. Эта особенность научного издания необходима
для того, чтобы не отвлекаться от основной информации, содержащейся в
12
работах,
представленных
в
нём.
Преимущество
стандартизированности
заключается в том, что научные работники с разными познаниями в своей
предметной области могут понять основное содержание и направленность работ
издания.
Под верифицируемостью научного журнала следует понимать то, что
каждый читатель подобного издания при желании сможет найти способ
подтверждения или опровержения с помощью доказательств любого из
материалов, размещенных в нем, а также воспроизвести результаты исследований,
если таковые имеются. Верификация или эмпирическое подтверждение является
основным критерием научности текстов, размещенных в журнале.
При наличии всех этих признаков журнал считается научным изданием,
имеющим право на публикацию исследовательских и теоретических работ. На
основе вышеизложенного понятно, что публикация работ в подобных журналах
невозможна без предварительного изучения их специалистами различной
квалификации, профессионального уровня и должностных категорий, благодаря
чему достигается их максимальная информативность.
1.2 Определение импакт-фактора научного издания
Научный работник должен иметь возможность сравнить научные журналы
между собой для выбора наиболее подходящего издания с целью публикации
собственного труда. Для этого широко используются объективные численные
показатели, такие как импакт-фактор.
Импакт-фактор — численный показатель важности научного журнала,
ежегодно рассчитываемый с 1961 года в США [3]. Импакт-фактор журнала
зависит от области исследований и его типа; из года в год он может заметно
меняться, например, опускаясь до предельно низких значений при изменении
названия журнала и так далее.
Импакт-фактор – важная характеристика научных журналов. Изначально он
рассчитывался каждый год Институтом научной информации (ISI), который в 1992
году был приобретён корпорацией Thomson (с 2016 года этим занимается копания
13
Clarivate Analytics) и публикуется в журнале «Journal Citation Report», входящем в
науко - и библиометрическую службу Web of Science. Он является одним из самых
авторитетных импакт-факторов современности, известным как JCR импактфактор. Импакт-фактор журнала равен отношению ссылок за определенный
период (обычно 3 года) на статьи в данном журнале к количеству опубликованных
в нем статей. В соответствии с ним (в основном в других странах, но в последнее
время всё больше и в России) оценивают уровень журналов и качество статей,
опубликованных в них.
В Российской Федерации имеется собственный импакт-фактор на базе
РИНЦ
(Российской
системы
научного
цитирования),
принадлежащий
информационной базе elibrary.ru. Он рассчитывается лишь для российских
научных журналов, иностранных журналов на русском языке, а также зарубежных
журналов, обладающих лицензионным соглашением с НЭБ (Научной электронной
библиотекой) на передачу данных в РИНЦ. Для переводных русских журналов
импакт-фактор рассчитывается исключительно для оригинальной российской
версии. Никак не рассматриваются реферативные журналы, а также журналы, не
выходящие в данный момент.
Импакт-фактор рассчитывается на основе предоставленных данных по
цитированию журнала в РИНЦ за предыдущие два года (либо пять лет) [4]. При
этом данные по цитированию берутся из публикаций года, для которого
рассчитывается импакт-фактор. При расчете импакт-фактора число ссылок,
сделанных в расчетном году из всех обрабатываемых в РИНЦ журналов на статьи,
опубликованные в данном журнале за предыдущие два года (или пять лет),
делится на общее число этих статей. То есть, по сути, данный показатель отражает
среднее число цитирований одной статьи в журнале.
Существуют и другие показатели значимости изданий, к примеру, рейтинг
SJR и активно используемый базой данных Scopus SNIP.
Появилась новая журнальная метрика CiteScore - это простой и ясный
способ измерения значения цитирований научных периодических публикаций,
таких как журналы, книжные серии и т.д. CiteScore определяется отношением
14
числа ссылок, сделанных в определенный год, на документы, опубликованные в
предыдущие 3 года в данном журнале, к числу документов (того же типа, что и
ссылки), опубликованных в данном журнале в предыдущие 3 года.
Метрика CiteScore основана на данных Scopus для более 22,000
периодических изданий ― рецензируемых журналов, книжных серий, сборников
трудов конференций и специализированных журналов ―
в 330 предметных
областях. Основанный на той же версии Scopus, которая доступна пользователям,
данный показатель может быть легко проверен любым пользователем базы
данных.
SJR (SCIMago Journal Ranking) - разработанный университетом Гранады
рейтинг журналов, в котором учитываются не только общее количество
цитирований, но и взвешенные показатели цитирований по годам и качественные
показатели, такие как авторитетность ссылок – вес ссылки в журнале Nature на
статью в журнале «А» будет отличаться от веса ссылки на ту же статью в журнале
«Вестник N-ского университета», на который ссылок в Scopus совсем или почти
нет. В целом SJR не очень сильно отличается от привычного импакт-фактора,
привлекая лишь более широким спектром журналов и публикацией в свободном
доступе в интернете.
SNIP - показатель весомости научного издания, учитывающий уже и
уровень цитирований в каждой научной области, так что может быть использован
для сравнения публикаций в разных научных направлениях. В показателе
учитываются ссылки, сделанные в текущем году, на статьи, вышедшие в течение
трех предыдущих лет. Публикационное окно = 3 года, Окно цитирования = 1 год,
Типы документов одинаковы для всех этапов подсчета показателя. Этим
показателем вводится специальное определение «индивидуальной области науки»
для журнала, или «окружения журнала»: все статьи, опубликованные в текущем
году (в любом издании), которые хотя бы однажды цитировали выпуски журнала,
вышедшие за последние десять лет.
Импакт-фактор обладает хоть и крупным, однако спорно расцениваемым
влиянием на оценку результатов научных исследований. Всё-таки на данный
15
момент импакт-фактор является одним из существенных критериев, по которому
можно сравнивать уровень научных исследований в близких сферах знаний.
1.3 Источники данных о научных изданиях
Каждый год, согласно данным журнала Scientific American, в мире издается
около 157 тысяч научных журналов [12]. Для того, чтобы не утонуть в таком
огромном количестве информации, были созданы так называемые базы
международного и регионального научного цитирования. Благодаря им можно
отсортировать
поиск
изданий
по
области
знаний
или
региональной
принадлежности, а не только по индексу цитируемости для каждого из журналов.
В работе для получения необходимых данных о научных журналах в
основном использовались следующие открытые источники:
1. Российский
информационный
портал
в
области
науки,
медицины,
технологии и образования eLIBRARY.ru [19].
2. Перечень рецензируемых научных изданий, в которых должны быть
опубликованы основные научные результаты диссертаций на соискание ученой
степени кандидата наук, на соискание ученой степени доктора наук Высшей
Аттестационной Комиссии Российской Федерации perechen.vak2.ed.gov.ru [25]
3. Сайт ведущего российского издательства научных журналов “МАИК
Наука/Интерпериодика” maik.ru [9]
4. Интерактивная база данных журналов, книжных серий, книг, справочных
материалов и архивов для исследователей и ученых международной издательской
компании SPRINGER link.springer.com [17]
По сути, сайт eLIBRARY.ru представляет из себя одну из самых популярных
электронных
библиотек,
предоставляющих
на
некоммерческой
основе
информацию о российских научных изданиях – от периодических до электронных
версий. И также в настоящее время он является Российским индексом научного
цитирования
(РИНЦ),
который
представляет
из
себя
национальную
информационно-аналитическую систему, аккумулирующую более 4,7 миллиона
публикаций российских авторов, а также информацию о цитировании этих
публикаций из более 4000 российских журналов. Её предназначение заключается
16
не только в том, чтобы оперативно обеспечить научные исследования актуальной
справочно-библиографической информацией. Она также является мощным
инструментом,
позволяющим
осуществлять
оценку
результативности
и
эффективности деятельности научно-исследовательских организаций, ученых,
уровень научных журналов и т.д. в Российской Федерации.
Список научных журналов ВАК является перечнем ведущих рецензируемых
научных журналов, включённых Высшей аттестационной комиссией России в
список
изданий,
рекомендуемых
для
опубликования
основных
научных
результатов диссертации на соискание учёной степени кандидата и доктора наук.
Издания, попадающие в этот перечень, рассматриваются научными работниками в
первую очередь как журналы, публикация в которых является необходимой для
успешного получения ученой степени, а также престижной на территории России.
Согласно решению Министерства образования и науки РФ от 12 декабря
2016 г. N 1586 с изменениями от 12 февраля 2018 года в данный список
включаются:
● Научные издания, удовлетворяющие необходимым критериям (в частности,
наличие института рецензирования, информационная открытость издания,
включение в систему Российского индекса научного цитирования (РИНЦ), строгая
периодичность и др).
● Научные издания, удовлетворяющие достаточному условию (включение
текущих номеров либо его переводной версии на иностранном языке в хотя бы
одну из международных и признанных европейским научным сообществом
систем цитирования: Web of Science, Scopus, Web of Knowledge, Astrophysics,
PubMed, Mathematics, Chemical Abstracts, Springer,AGRIS , GeoRef).
Инофрмационный портал eLIBRARY.ru, а также перечень научных изданий
ВАК являются основными источниками данных для информационной системы.
Но чаще всего из них практически невозможно получить информацию об импактфакторе конкретного журнала. Переходя на сайт самого издания, можно заметить,
что не все журналы указывают информацию о индексе цитируемости по тем или
иным причинам, вследствие чего было принято решение использовать сайты
17
ведущих издательств для получения необходимых данных с целью последующей
их интеграции в базу данных проекта. Для этого были выбраны сайты издательств
МАИК “Наука/Интерпериодика” и SPRINGER, чьи базы данных содержат
сведения о индексе цитируемости научных изданий.
МАИК “Наука/Интерпериодика” является одной из ключевых компаний в
группе
российских
издательств
и
осуществляет
важную
миссию
по
распространению в международном научном сообществе трудов российских
ученых, выпуская более 200 наименований научных журналов по физике,
математике, информатике, химии, биологии, наукам о земле на английском языке.
Авторы статей – известные ученые России, стран ближнего и дальнего зарубежья.
Основной
профиль
литература
по
издательства
естественным,
–
научная,
техническим,
учебная,
научно-популярная
гуманитарным,
общественно-
политическим дисциплинам сельскому хозяйству, машиностроению, транспорту,
медицине
и
другим
отраслям
знаний.
Продукция
группы
издательств
представлена как на российском, так и на международном рынках, включая
страны ближнего зарубежья.
SPRINGER — международная издательская компания, специализирующаяся
на
издании
академических
журналов
и
книг
по
естественно-научным
направлениям (теоретическая наука, медицина, экономика, инженерное дело,
архитектура, строительство и транспорт). Список журналов издательства Springer
включает научные и научно-популярные журналы издательства Springer Science,
распределенные по тематике и алфавиту. С 2006 года электронные версии
журналов (в том числе и за предыдущие годы) публикуются на ресурсе, где для
некоторых журналов реализован свободный доступ. Несмотря на то, что многие
журналы доступны лишь по платной подписке, журналы из свободного доступа
данного
ресурса с лихвой покрывают поставленную задачу, т.е. получение
международного индекса цитируемости изданий.
Таким образом, ясно видно, что требуется не просто добавить список
журналов из информационно-аналитических систем, приведенных выше, в базу
данных. Стоит задача намного важнее – проверить их на авторитетность в
18
научном сообществе и узнать меру их значимости среди признанных
специалистов.
1.4 Способы оценки качества научных журналов
В настоящее время в России публикации в научных журналах не имеют под
собой научную составляющую и адекватное рецензирование для оценки качества
статей [6, 7, 15]. Из-за этого большое распространение получил формальный
подход, когда статьи публикуются за плату в малоизвестных журналах,
распространяемых только среди авторов и по списку обязательной рассылки, а
качество издаваемых статей не проверяется никем. При этом требование об
обязательной публикации результатов диссертационных исследований получает
распространение количества статей у автора, а не качества их.
В связи с этим приобретает необходимость в разработке метода оценки
качества научных журналов, который позволял бы с приемлемой степенью
достоверности
установить,
какие
журналы
гарантируют
широкое
распространение и высокое качество публикуемых в них материалов [27].
Качество научного журнала очень сложно измерить [14]. Оно может
представлять усредненную оценку экспертов в определенной области или сфере
наук, а также степень престижности публикации в том или ином журнале.
Измерить точно качество публикации в научном журнале не представляется
возможности, оно может быть оценено с определенной погрешностью [27].
Российский индекс научного цитирования создавался не только как
национальный реестр публикаций российских ученых, но и как инструмент
оценки научной деятельности. То есть у РИНЦ две основные задачи [15, 19]: а)
сбор из всех источников в единой базе данных информации о всех публикациях
российских ученых, и б) расчет статистических показателей для оценки
публикационной активности ученых и научных организаций на основе
цитируемости публикаций.
Для оценки публикационной активности на платформе elibrary.ru теперь есть
три различных уровня:
19
1) Ядро РИНЦ. Сюда входят все публикации в журналах, индексируемых в
настоящее время в базах данных Web of Science Core Collection, Scopus и RSCI
(Russian Science Citation Index на платформе Web of Science). Кроме того, в ядро
будут включаться лучшие монографии и труды самых авторитетных научных
конференций, отобранные на основании строгой экспертной оценки. Ядро РИНЦ
рекомендуется для оценки наиболее качественной составляющей массива
публикаций российских ученых.
2) РИНЦ. После очистки от недобросовестных изданий сюда будут
включаться только публикации в рецензируемых научных изданиях, а также
нежурнальные публикации, отвечающие требованиям издательской и научной
этики. Рекомендуется для анализа публикационной активности по всем научным
направлениям, в том числе по тем, где уровень отечественных исследований еще
не дотягивает до мирового уровня.
3) Научная электронная библиотека. Здесь могут дополнительно размещаться
различные издания, имеющие отношение к научной деятельности, но не
являющиеся в строгом понимании этого слова научными, в том числе
реферативные,
научно-популярные,
информационные
и
общественно-
политические журналы, а также журналы, которые не могут быть отнесены к
категории рецензируемых. Эти издания не участвуют в статистической оценке
научной деятельности в РИНЦ.
Соответственно,
основные
библиометрические
показатели
(число
публикаций, число цитирований и индекс Хирша) рассчитываются теперь
отдельно для каждой категории, что позволяет их сравнить и понять, за счет
публикаций в каких источниках они формируются. Все эти показатели
представлены на странице анализа публикационной активности ученого. В
списках публикаций и цитирований автора также теперь можно выводить
публикации или ссылки отдельно для каждой из категорий.
Если изучить методику оценки качества научных журналов, рекомендуемых
Высшей аттестационной комиссией Российской Федерации (ВАК РФ), то можно
отметить следующее. В соответствии с решениями ВАК РФ, соискатели ученой
20
степени кандидата или доктора наук должны опубликовать определенное
количество
статей
в
журналах,
удовлетворяющих
следующему
набору
достаточных и необходимых требований [27].
Достаточное условие: включение текущих номеров научного периодического
издания или его переводной версии на иностранном языке хотя бы в одну из
систем цитирования – Web of Science, Scopus, Web of Knowledge, Astrophysics,
PubMed, Mathematics, Chemical Abstracts, Springer, Agris [20, 21].
Необходимое условие: выполнение научным периодическим изданием (как
традиционным, так и существующим только в электронной форме) всех
перечисленных ниже критериев [18].
1. Наличие института рецензирования (для экспертной оценки рукописей).
Обязательное предоставление редакцией рецензий по запросам авторам рукописей
и экспертным советам в ВАК.
2. Информационная открытость издания. Наличие сетевой версии в
Интернете. Аннотации статей, ключевые слова, информация об авторах должны
находиться в свободном доступе в Интернете на русском и английском языках,
полнотекстовые версии статей – в свободном доступе или быть доступными
только для подписчиков не позднее чем через год после выхода журнала.
3. Регулярное предоставление информации об опубликованных статьях по
установленной форме в систему Российского индекса научного цитирования.
4. Обязательное указание состава редакционной коллегии или совета с
указанием ученой степени и ученого звания на сайте научного периодического
издания.
5. Обязательное указание мест работы всех авторов, и контактной
информации для переписки.
6. Строгая периодичность. Претендент должен представить не менее двух
последних выпусков своего издания.
7. Наличие пристатейных библиографических списков у всех статей в
формате, установленном журналом из числа предусмотренных действующим
ГОСТом.
21
8. Наличие ключевых слов для каждой публикации.
9. Наличие и строгое соблюдение опубликованных правил представления
рукописей авторами.
10. Отсутствие платы за опубликование рукописей аспирантами.
11. В случае отказа в публикации статьи редакция обязана направить автору
мотивированный отказ.
12. Наличие ISSN.
13. Наличие подписного индекса ОАО «Роспечать», и / или Объединенного
каталога «Пресса России», и / или Каталога российской прессы «Почта России»
(не применяется для
электронных изданий). Для
электронных изданий
обязательным является регистрация издания в Научно-технологическом центре
«Информрегистр».
Журналы,
удовлетворяющие
этим
требованиями,
включаются
в
так
называемый список ВАК, размещенный на сайте ВАК РФ и периодически
пересматриваемый. Такие требования правомерны, так как можно отследить
псевдо-журналы, которые готовы опубликовать любой материал на платной
основе [27].
Но нужно также отметить, что в списке требований, предъявляемых к
научному журналу, присутствуют определенные недостатки:
1. Эти требования имеют текстовую форму (т. е. количественная оценка
степени соответствия им журнала не предполагается – проверяется лишь факт
выполнения того или иного требования).
2. Состав требований ВАК РФ говорит о том, что в первую очередь они
направлены на обеспечение высокого уровня научных публикаций. Хотя
отдельные требования и связаны с распространением журнала (например,
необходимость включения в подписные каталоги), они носят подчиненный
характер. Выше уже говорилось о том, что, по мнению автора, большое значение
имеют как качество публикаций, так и распространение журнала.
3. Спорной является фетишизация регистрации журнала в международных
научных базах данных.
22
Если оценивать доступность и привлекательность журнала для научной
общественности, то нужно также оценивать и его научный уровень. При этом
оценка должна иметь количественное выражение – это, с одной стороны, позволит
сделать процедуру более прозрачной и объективной, а с другой – создаст
возможность для построения рейтинга научных журналов. И, как уже было
сказано выше, не стоит полагать, что принятые в мире методики оценки качества
журналов абсолютно объективны: безусловно, получаемые при помощи этих
методик оценки могут служить в качестве ориентира, но не следует считать их
идеальными [14, 27].
Важный шаг в направлении разработки национального индекса качества
научных изданий сделала Украина, где Национальная библиотека им. Вернадского
рассчитывает для каждого журнала, включенного в список ВАК Украины, так
называемый индекс интегрированности в систему научных коммуникаций [8]. Как
явствует из самого названия этого показателя, он предназначен для измерения
степени доступности журнала для научной общественности.
Чем выше значение этого индекса, тем больше вероятность того, что с
опубликованными в нем материалами познакомится научное сообщество. Однако,
насколько нам известно, этот индекс не используется для принятия решения о
включении журнала в список ВАК Украины.
Структура индекса отображена в табл. 1.
23
Таблица 1
Процедура расчета индекса интегрированности в систему научных
коммуникаций
№
п/п
1
1
Показатель для расчета рейтинга
2
2
Продолжительность
существования издания
Периодичность
3
Наличие ISSN
4
Статус учредителя
5
6
7
8
Научный статус главного
редактора
Наличие переводной версии
Представленность в
украинской системе
реферирования научной
литературы
Представленность в
международных
реферативных базах данных
9
Оперативность
предоставления
электронной версии в
свободный доступ
10
Соответствие требованиям
распоряжения ВАК
Украины и НАН Украины
Значения
3
10 и больше лет
менее 10 лет
4 и более раз в год
менее 4 раз в год
У издания есть Международный
стандартный номер серийных изданий
ISSN
Центральный орган власти (министерство,
государственный комитет и т. д.),
Национальная академия наук Украины,
Академия медицинских наук Украины,
Украинская академия аграрных наук,
Академия педагогических наук Украины,
Академия правовых наук Украины
Научное или образовательное учреждение
и т. д.
Академик (член-корреспондент)
национальной или государственной
отраслевой академии наук
доктор (кандидат) наук
У издания есть переводная версия
Издание представлено постатейно в
реферативной базе данных «Україніка
наукова»
4
1
0
1
0
1
Издание представлено в базах данных
Scopus, ISI Web of Knowledge, Inspec,
Medline и т. д.
1
Электронная версия издания
предоставляется в свободный доступ на
сайте Национальной библиотеки Украины
имени В. И. Вернадского без
установленного издателем периода
задержки
Электронная копия издания соответствует
требованиям распоряжения ВАК Украины
и НАН Украины
1
24
1
0
1
0
1
1
1
Индекс интегрированности в систему научных коммуникаций рассчитывается
как сумма баллов по всем критериям. Максимально возможное значение этого
показателя – 10 (насколько можно судить, ни один журнал его не набрал [8].
Минимальное
значение
индекса
интегрированности
в
систему
научных
коммуникаций для научного журнала – 4 балла. Интересно отметить, что в списке
ВАК Украины много журналов со значением индекса интегрированности в
систему научных коммуникаций, меньшим 4 [8].
Однако эта методика, представляя собой весьма важную перспективную
попытку количественной оценки качества научного журнала, обладает рядом
недостатков [27]:
1. Спорный выбор критериев оценки:
– логическая неоднородность индекса – в него включены как факторы,
несомненно, определяющие интегрированность журнала в систему научных
коммуникаций (например, пп. 7 и 8), так и факторы, которые, скорее, призваны
определять уровень публикаций (пп. 4–5);
– неоправданный (хотя и типичный для постсоветского пространства)
приоритет административных критериев (пп. 4–5). Очевидно, что научная степень
редактора не имеет никакого отношения к качеству журнала. Кроме того, в случае
смены редактора и прихода на эту должность человека с более низкой ученой
степенью придется понижать индекс журнала, хотя на самом деле качество
издания, скорее всего, останется неизменным;
– некоторые важные критерии, характеризующие интегрированность издания
в систему научных коммуникаций (например, наличие сетевой версии журнала), в
перечень включены не были.
2. Возможность компенсации, т. е. ситуации, когда низкий балл по одному
критерию компенсируется в итоговом индексе высоким значением балла по
другому критерию.
3. Для каждого критерия предусмотрена только двухбалльная шкала оценки,
которая для разных критериев имеет различный смысл. Например, в случае
критерия 3 речь идет просто о выполнении или невыполнении соответствующего
25
требования, тогда как для критерия 5 предполагается ранжирование по наличию у
редактора журнала определенных научных регалий. Логичнее было ввести (по
крайней мере, для отдельных критериев) более подробные шкалы.
И. Д. Котляров предложил методику расчета индекса научного качества
журнала на основе методики расчета индекса интегрированности в систему
научных коммуникаций, рассмотренной выше, однако с учетом выявленных
недостатков и с включением в итоговый показатель отдельных критериев,
учитываемых в методике ВАК РФ [14].
Алгоритм разработки этой методики должен иметь следующий вид:
– составление списка критериев оценки научного журнала;
– разработка балльной шкалы оценки соответствия данному критерию;
–
определение
минимального
значения
оценки,
при
котором
соответствующий критерий считается соблюденным. Введение минимального
значения необходимо для предотвращения компенсации;
– итоговый индекс соответствия рассчитывается как сумма баллов,
набранных журналом по отдельным критериям. Для него также очевидным
образом задается минимальное значение (как сумма минимально допустимых
баллов по каждому критерию). Этот индекс позволяет составлять рейтинг
научных журналов.
Очевидно при этом, что разрабатываемая методика оценки должна быть
направлена не на то, чтобы давать высокие значения показателей для уже
существующих журналов, а на то, чтобы быть максимально объективной и
задавать для научных журналов целевые значения показателей, к которым следует
стремиться. Итоговая методика имеет следующий вид (см. табл. 2).
Таблица 2
Предлагаемая структура индекса научного качества журнала
№
1
1
Описание
критерия
2
Представленност
ь в базах
Градации
Баллы
3
4
Издание не представлено в базах научного 0
цитирования
26
Минимальны
й
балл
5
научного
цитирования
1
2
3
4
5
Издание представлено в национальной 1
базе «Российский индекс научного
цитирования»
Издание представлено в международных 2
базах научного цитирования
2
3
Наличие сетевой Сетевая версия отсутствует
Сетевая
версия
содержит
только
версии
контактную
информацию
журнала,
правила для авторов и данные о составе
редакционной коллегии
Сетевая версия содержит в свободном
доступе перечни опубликованных статей,
аннотации, данные об авторах и
пристатейные библиографические списки
Сетевая версия содержит архив журнала
за прошлые периоды (отстающие от
текущего выпуска не более, чем на
полгода) в свободном доступе
Все материалы журнала размещены в
свободном доступе на сайте самого
журнала
Наличие
Материалы публикуются на русском языке
переводной
без аннотаций на английском языке
версии журнала Материалы публикуются на русском языке
с аннотациями на английском языке
издается
Материалы публикуются на русском и
параллельная
версия журнала других языках с аннотациями на
на
английском английском языке (к этой же группе
относятся журналы, выходящие только на
языке4
английском языке)
Дополнительно к основной версии
журнала регулярно издается его краткая
версия на английском языке
Издается параллельная версия журнала на
английском языке
Регулярность
У издания отсутствует график публикации
У издания есть график публикации,
выпуска
однако он не соблюдается
У издания есть график публикации,
который жестко соблюдается
Распространение Журнал распространяется по списку
журнала
(для обязательной рассылки и среди авторов
Журнал включен в подписные каталоги
печатного
Журнал поступает в продажу в основные
журнала)
27
1
4
5
0
1
3
2
3
4
0
1
2
1
3
4
0
1
2
2
0
1
2
1
книготорговые
сети
и
к
распространителям прессы
Размещение
Журнал размещен на бесплатном хостинге 0
журнала
(для (не обладает собственным доменным
электронных
именем второго уровня)
Журнал размещен на сайте научного или 1
изданий)
образовательного учреждения высшего
образования
Журнал обладает собственным доменным 2
именем второго уровня
6
1
7
8
9
10
2
Наличие
института
рецензирования
Сведения об
авторах
Пристатейный
аппарат
Редакционная
коллегия
3
Рецензирование отсутствует
Автор статьи сам предоставляет рецензию
на свою работу
Журнал готовит внутреннюю рецензию в
свободной форме
Журнал запрашивает внешнюю рецензию
в свободной форме
Журнал запрашивает внешнюю рецензию
по определенной форме (т. е. она должна
быть составлена по требуемой журналом
форме и содержать количественную или
вербальную оценку соответствия статьи
критериям, предъявляемым журналом к
научной публикации)
Указываются только ФИО авторов
Указываются места работы авторов
Указываются контактные данные авторов
Пристатейный аппарат отсутствует
Есть библиографический список на
русском языке
Есть аннотация и библиографический
список на русском языке
Есть аннотация, ключевые слова и
библиографический список на русском
языке
Есть аннотация, ключевые слова и
библиографический список на русском и
английском языке
У журнала отсутствует редколлегия, или
она состоит из лиц без ученой степени
В редколлегии журнала число докторов
наук по профилю журнала составляет не
более 40 % (у всех остальных есть степень
кандидата наук)
В редколлегии журнала число докторов
28
1
4
5
0
1
2
3
3
4
0
1
2
0
1
2
3
2
3
4
0
1
2
2
наук по профилю журнала составляет
более 40 %
В
редколлегии
журнала
есть
действительные члены или членыкорреспонденты
РАН
или
государственных отраслевых академий
11
1
12
13
14
Главный редактор
журнала
Лицо без ученой степени
Кандидат наук
Доктор наук
Действительный член или членкорреспондент РАН или государственных
отраслевых академий
2
Взимание платы с
авторов
3
Плата с автора взимается, статья в
свободный доступ не помещается
Плата с автора взимается, статья с
момента публикации соответствующего
номера журнала помещается в свободный
доступ
Статья публикуется бесплатно или с
выплатой автору гонорара, помещается в
свободный доступ по истечении
определенного периода
Подтверждение
Автор не получает оттисков и авторских
факта публикации экземпляров журнала
Автор получает оттиски и / или авторские
экземпляры за отдельную плату
Автор получает оттиски и / или авторские
экземпляры бесплатно
Организация
Обмен
информацией
с
автором
взаимодействия с отсутствует (т. е. статья может быть
автором
опубликована без уведомления автора или
же
отклонена
без
предоставления
мотивированного отказа; редакция не
подтверждает получения статьи)
Редакция информирует автора о принятом
решении, но не вступает с ним в
переписку
Редакция высылает автору
мотивированное решение вместе с
отзывами рецензентов
Редакция подтверждает получение статьи
и высылает автору мотивированное
решение вместе с отзывами рецензентов
29
3
0
1
2
3
4
0
2
5
1
1
2
0
1
1
2
0
3
1
2
3
15
1
16
Открытость
журнала для
автора
2
Механизм
получения статей
Редакция
осуществляет
полное
сопровождение статьи (подтверждение
получения, присвоение регистрационного
номера, отправка решения и отзывов
рецензентов по установленной форме,
информирование о дате выхода журнала,
уведомление о высылке оттисков статей
или отправка ссылки на статью на сайте
журнала)
Журнал принимает материалы от авторов
только при наличии рекомендации в виде
выписки из протокола заседания кафедры
и экспертного заключения о возможности
опубликования статьи в открытой печати
Журнал принимает материалы от авторов
только при наличии рекомендации в виде
выписки из протокола заседания кафедры
Журнал не требует от автора никаких
сопроводительных документов
4
0
2
1
2
3
Журнал принимает материалы только в
«бумажном» виде
Журнал предусматривает возможность
получения статей по электронной почте
4
0
5
1
1
Максимально возможный балл для печатного журнала – 44, минимально
допустимый для того, чтобы журнал включался в список рекомендованных для
публикации основных результатов диссертационных исследований – 29. Таким
образом, величина «проходного балла» составляет порядка 66 % от максимально
возможного
балла,
что
представляется
приемлемым
уровнем
строгости
требований.
Можно также представить пояснения к таблице 2 [27].
1. Входящие в исходную версию индекса интегрированности в систему
научных
коммуникаций
критерии
наличия
ISSN,
ранга
учредителя
и
продолжительности существования журнала никак не влияют на качество
журнала
и
были
исключены.
Отсутствие
значимости
этих
критериев
подтверждается, в частности, тем, что они не учитываются при принятии решения
о включении журнала в базу данных Web of Science.
30
2. Из расчета индекса научного качества журнала были исключены
требования к правилам для авторов. Это подкрепляется существующей практикой
– ряд ведущих научных журналов, входящих в издательские концерны Elsevier,
Springer и Wiley-Blackwell, предъявляют минимальные требования к оформлению
работ (статья оформляется в стиле журнала сотрудниками журнала после ее
принятия к печати). Наличие строгих и неукоснительно соблюдаемых правил для
авторов, по сути дела, дает возможность журналу минимизировать собственные
затраты на оформление и верстку статей, но ничего не говорит о качестве
журнала.
3. Заявленная периодичность выпуска журнала, а также частота выхода
номеров имеют меньшее значение по сравнение с фактической периодичностью, и
по этой причине в новую версию структуры индекса интегрированности в систему
научных коммуникаций включена не заявленная периодичность, а степень ее
соблюдения (так как именно от нее зависит скорость поступления опубликованной
информации к читателям).
4. Приоритет, уделяемый английскому языку, объясняется тем, что он
фактически
стал
необходимости
международным
можно
языком
скорректировать
научной
требование
коммуникации.
об
При
обязательном
сопровождении статьи информацией на английском языке (например, допустив
использование других мировых языков).
5. Под краткой переводной версией понимается специальный выпуск
журнала на английском языке, издаваемый с меньшей периодичностью, чем
основная версия, и включающий в себя не все материалы из основного журнала.
6. Для печатного журнала параллельная иноязычная версия может
существовать только в электронном виде.
7. Статус главного редактора имеет особое значение с учетом российской
специфики: ученый высокого ранга не позволит использовать себя в качестве
номинального редактора некачественного журнала.
8. Ряд российских научных журналов требует от авторов при отправке статьи
обязательно приложить рекомендацию к публикации в виде соответствующей
31
выписки из протокола заседания кафедры, а также экспертное заключение о
возможности опубликования статьи в открытой печати. Не секрет, что во многих
российских
вузах
существует
традиция
вписывать
в
качестве
соавтора
заведующего кафедрой – без этого положительная рекомендация кафедры не
может быть получена. Требуя ее, редакции журналов вольно или невольно
содействуют отчуждению научных результатов от их подлинного автора. Кроме
того, данная практика отсекает от возможности публикации людей, не
работающих в вузах и НИИ (например, специалистов-практиков, занятых на
производстве). Наконец, настаивая на получении такой рекомендации, журнал
признается в своей не способности самостоятельно провести экспертизу
присланной статьи и, следовательно, не должен быть признан соответствующим
статусу научного журнала. Именно этот тезис отражен в п. 15 табл. 2.
9. Разумеется, механизм получения статей журналом непосредственного
отношения к его качеству не имеет. Однако в наше время требования ряда
журналов отправлять статьи традиционной почтой выглядят анахронизмом –
исследователю гораздо проще выслать отформатированный в соответствии с
правилами журнала файл со своего компьютера. Но главное не это – по
признанию редакторов, «бумажные» варианты статей (и желательно – заверенные
подписью автора) необходимы, чтобы избежать повторения нашумевшей истории
с «корчевателем» ииииииииииии [14]. Иными словами, редакторы неявно
признаются, что обеспечить полноценную экспертизу рукописи они не в
состоянии. Именно по этой причине особую важность имеет готовность журнала
получать материалы по электронной почте.
Предлагаемый индекс научного качества журнала может быть использован
для следующих целей [27]:
1. Формирование списка журналов, рекомендованных для публикации
основных результатов диссертационных исследований. Как уже отмечалось выше,
в этот список могут быть включены журналы, индекс качества научного журнала
которых равен или превышает требуемое минимальное значение. Отметим, что
поскольку официальные требования к уровню журналов, в которых публикуются
32
результаты диссертационных исследований, существуют не только в России, но
также на Украине, в Белоруссии, Казахстане и Узбекистане (в этот список можно
включить
и
Таджикистан,
присуждение
научных
степеней
в
котором
подконтрольно ВАК РФ), то предложенная методика могла бы быть внедрена во
всех этих государствах. Это позволило бы унифицировать процедуру оценки
качества научных журналов и дало бы возможность диссертантам публиковать
свои работы не только в стране, в которой планируется защита, но и во всех
государствах, которые бы приняли эту методику. Это, в свою очередь, стало бы
важным шагом к построению единого научного и образовательного пространства
на территории СНГ.
2. Установление уровня требований к публикациям аспирантов, докторантов
и соискателей ученой степени кандидата (доктора) наук. В настоящее время от
них требуется не менее одной (соответственно, семи) публикаций в журналах,
входящих в список ВАК. На наш взгляд, было бы разумно потребовать от
диссертантов набрать определенное количество баллов посредством публикации
статей в журналах, вошедших в список ВАК. Балл, присуждаемый каждой статье,
может быть рассчитан как частное от деления индекса качества научного журнала,
в котором была опубликована статья, на число соавторов. Минимально
допустимый уровень индекса научного качества журнала – 26, максимально
возможный – 40, поэтому в качестве ориентиров можно предложить суммарный
балл научных статей, равный 33 (среднее арифметическое от минимально и
максимально возможных значений баллов), для соискателей ученой степени
кандидата наук, и 231 – для докторантов. С одной стороны, эти требования ниже
максимально возможного уровня индекса качества научного журнала (40), а с
другой – мотивируют соискателей ученой степени на публикацию своих статей в
журналах более высокого уровня и без соавторов, т. е. стимулируют их к
самостоятельной и качественной научной работе и не позволят им ограничиться
одной публикацией в журнале низшего эшелона из списка ВАК. Дополнительно
уточним, что при расчете баллов учитываются только статьи, опубликованные в
журналах, входящих в список ВАК.
33
3. Регламентация требований к научным публикациям претендентов на
получение ученого звания доцента или профессора по кафедре. В настоящее
время
для
получения
звания
профессора
необходимо
опубликовать
(самостоятельно или в соавторстве) не менее трех научных работ за последние три
года (или монографию, или главу в монографии, но этот вариант рассматриваться
не будет – в частности потому, что отсутствует четкое определение того, какая
именно научная публикация является монографией). Для кандидатов на звание
доцента требуется не менее двух научных работ за последние три года. Однако
требования к уровню научных публикаций в этом случае отсутствуют. Эта
ситуация парадоксальна – жесткие требования ВАК к уровню публикаций
соискателей ученых степеней сочетаются с полным отсутствием требований к
качеству публикаций претендентов на ученые звания, хотя для высшей школы
ученые звания имеют большее значение, чем ученые степени. В итоге публикации
будущих доцентов превращаются в профанацию: сотрудник вуза перед подачей
документов на получение звания публикует свои наспех написанные доклады в
сборниках заочных конференций. Такая ситуация, разумеется, неприемлема.
Поэтому для претендентов на получение звания предлагается установить
следующие пороговые суммарные значения баллов за статьи в журналах из списка
ВАК за последние три года: 66 – для доцентов, 99 – для профессоров.
4.
Методику, аналогичную описанной в пп. 3– 4, рекомендуется
применять для оценки результативности научной деятельности профессорскопреподавательского состава.
5.
Индекс научного качества журнала может учитываться при выделении
государственного финансирования для поддержки издания журнала.
Итак, на что следует обратить внимание в первую очередь при выборе
журнала? Для публикации результатов диссертаций ВАК требует, чтобы научное
издание было рецензируемым. И это не пустые слова. Предполагается, что
рецензируемые журналы в данном случае выступают в качестве внешних центров
экспертизы результатов исследования, не допуская к публикации заведомо слабые
34
работы. Но все ли журналы действительно выполняют эту функцию, и как это
проверить?
По оценкам, среди шести тысяч индексируемых в РИНЦ журналов не менее
1000 вообще не проводят никакого рецензирования входных рукописей, хотя и
декларируют это. Публикация в таких изданиях может привести к тому, что статья
не будет включена в РИНЦ и не будет учитываться при расчете наукометрических
показателей автора. Поэтому и необходимо учитывать методы оценки качества
журналов.
35
ГЛАВА 2. СОЗДАНИЕ БАЗЫ ДАННЫХ СПРАВОЧНИКА
2.1 Структуры таблиц баз данных
Информационная
система,
созданная
в
рамках
выпускной
квалификационной работы представляет собой отражение необходимой структуры
хранения данных, получаемых из каждого ресурса (elibrary, springer, maik,
перечень ВАК) и представляемой на языке базы данных SQLite [8]. Все таблицы
спроектированы таким образом, чтобы хранить только самые необходимые
данные. Для каждого из упомянутых выше источников, объём необходимых для
сохранения данных будет отличаться, в зависимости от преследуемой цели.
Рассмотрим структуры каждой из таблиц.
Структура данных для анализа таблицы, принадлежащей информационной
системе elibrary.ru, выглядит следующим образом:
CREATE TABLE elibrary (
id INTEGER UNIQUE,
'Полное название' TEXT,
'Издательство' TEXT,
'Год основания' INTEGER,
'Рецензируемый' BOOLEAN,
'Выпусков в год' INTEGER,
'Импакт-фактор JCR' TEXT,
'Статей в выпуске' INTEGER,
'Импакт-фактор РИНЦ 2013' REAL,
'Сокращение' TEXT,
'Страна' TEXT,
'Город' TEXT,
'Регион' TEXT,
'Подписной индекс' TEXT,
'Тираж' INTEGER,
'ISSN печатной версии' TEXT,
'ISSN онлайновой версии' TEXT,
'Вариант представления' TEXT,
36
'WWW-адрес' TEXT,
'ISI' BOOLEAN,
'SCOPUS' BOOLEAN,
'РИНЦ' BOOLEAN,
'Перечень ВАК' BOOLEAN,
'Всего статей' INTEGER,
'Всего выпусков' INTEGER,
'Полных текстов' INTEGER,
'Цитирований' INTEGER,
'В настоящее время' TEXT,
'Доступный архив' TEXT,
'Реферативный' TEXT,
'Мультидисциплинарный' TEXT,
'Описание журнала' TEXT,
'Редакционная коллегия' TEXT,
'Aims & Scope' TEXT,
created_at TEXT);
При обработке журнала из elibrary , сохраняются все доступные поля. Тип
данных каждого из полей выбирался по аналогии с теми типами, что
предоставляет elibrary. Большая часть полей имеет русскоязычные названия. Такой
выбор был сделан исходя из необходимости сохранять все данные о журнале со
страницы elibrary и с целью уменьшение количества повторяющегося кода.
Каждое поле в таблице соответствует полю с аналогичным названием на странице
журнала - эти поля используются при извлечении данных.
В свою очередь, структура таблицы для извлечения необходимых данных с
сайта maik.ru имеет вид:
CREATE TABLE maik (
id TEXT UNIQUE,
title TEXT,
impact_factor_jcr REAL,
issn_print TEXT,
37
issn_online TEXT);
База maik.ru используется для уточнения импакт-фактора JCR журнала.
Поэтому в соответствующую таблицу сохраняются только самые необходимые
данные: id журнала в базе maik, название, импакт фактор JCR и ISSN онлайновой
и печатной версии журнала.
Структура таблицы для работы с базой Springer имеет вид, идентичный
предыдущей таблице:
CREATE TABLE springer (
id INTEGER UNIQUE,
title TEXT,
impact_factor_jcr REAL,
issn_print TEXT,
issn_online TEXT);
Так как сайт maik.ru в некоторых случаях не имеет данных об импактфакторе, то базу Springer удобно использовать для уточнения импакт-фактора JCR
журнала. Поэтому в соответствующую таблицу сохраняются только самые
необходимые данные: id журнала в базе springer, название, импакт фактор JCR и
ISSN онлайновой и печатной версии журнала.
Структура данных таблицы для работы с перечнем рецензируемых научных
изданий ВАК выглядит следующим образом:
CREATE TABLE perechen_vak (
id INTEGER UNIQUE,
title TEXT,
issn TEXT,
branches TEXT,
specialties TEXT,
foreign_db TEXT,
38
inclusion_date TEXT);
Эти данные используются для уточнения отраслей науки, специальностей и
вхождения в международные базы данных журнала, а также самого факта
присутствия журнала в перечне ВАК.
После получения и сохранения данных из всех доступных ресурсов,
происходит их обработка и сохранение в таблицу journals. Подробнее процесс
обработки описан в третьей главе.
В эту таблицу попадают только самые необходимые данные о журнале:
название, описание, издательство, ISSN печатной и онлайновой версии,
импакт фактор JCR, импакт фактор РИНЦ, отрасли наук, специальности,
информация о вхождении в различные базы данных, ссылки на сайт журнала и т.д.
CREATE TABLE journals (
id INTEGER UNIQUE,
title TEXT,
description TEXT,
publisher TEXT,
issn_print TEXT,
issn_online TEXT,
impact_factor_jcr REAL,
impact_factor_rinc REAL,
branches TEXT,
specialties TEXT,
foreign_db TEXT,
journal_url TEXT,
elibrary_url TEXT,
maik_url TEXT,
springer_url TEXT,
reviewed BOOLEAN,
in_vak BOOLEAN,
in_rinc BOOLEAN,
in_isi BOOLEAN,
in_scopus BOOLEAN,
39
in_humanities BOOLEAN);
В начале работы над проектом для создания информационной системы
использовалась компактная встраиваемая реляционная база данных SQLite. Но
продолжать её использовать для текущих задач не рекомендуется, так как для
корректного встраивания базы в веб-интерфейс данная библиотека не подходит.
По
этой
причине
был
осуществлен
переход
на
свободную
и
самую
распространенную реляционную систему управления базами данных MySQL. При
этом с учетом возможных неполадок в работе информационной системы было
решено оставить базу данных на SQLite в качестве временного хранилища
данных.
Рис. 1. ER-диаграмма базы данных
На рисунке 1 представлена графическая интерпретация информационной
системы. Наибольший интерес представляют четыре таблицы: библиотека
40
журналов journals_library, в которой содержатся данные непосредственно о
научных изданиях, а также таблицы специальностей, международных баз данных
и отраслей наук, названные journals_specialty, journals_foreigndb, journals_branch
соответственно. Структура таблицы journals_library имеет следующий вид:
CREATE TABLE IF NOT EXISTS `scidb`.`journals_library` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`outer_id` INT(10) UNSIGNED NULL DEFAULT NULL,
`title` VARCHAR(255) CHARACTER SET 'utf8' NULL DEFAULT NULL,
`description` LONGTEXT CHARACTER SET 'utf8' NULL DEFAULT NULL,
`publisher` VARCHAR(255) CHARACTER SET 'utf8' NULL DEFAULT NULL,
`issn_print` VARCHAR(16) CHARACTER SET 'utf8' NULL DEFAULT NULL,
`issn_online` VARCHAR(16) CHARACTER SET 'utf8' NULL DEFAULT NULL,
`impact_factor_jcr` DOUBLE NULL DEFAULT NULL,
`impact_factor_rinc` DOUBLE NULL DEFAULT NULL,
`journal_url` VARCHAR(255) CHARACTER SET 'utf8' NULL DEFAULT NULL,
`elibrary_url` VARCHAR(255) CHARACTER SET 'utf8' NULL DEFAULT
NULL,
`maik_url` VARCHAR(255) CHARACTER SET 'utf8' NULL DEFAULT NULL,
`springer_url` VARCHAR(255) CHARACTER SET 'utf8' NULL DEFAULT
NULL,
`reviewed` TINYINT(1) NOT NULL,
`in_vak` TINYINT(1) NOT NULL,
`in_rinc` TINYINT(1) NOT NULL,
`in_isi` TINYINT(1) NOT NULL,
`in_scopus` TINYINT(1) NOT NULL,
`in_humanities` TINYINT(1) NOT NULL,
`created_at` DATETIME NOT NULL,
`updated_at` DATETIME NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `title` (`title` ASC, `issn_print` ASC, `issn_online`
ASC))
Расшифруем поля, попадающие в таблицу. Так как в нее попадают все
необходимые сведения о журнале, она содержит номер журнала в созданной
41
системе, его название, описание, название издательства, серийный номер ISSN
печатной и онлайновой версии, импакт-факторы JCR и РИНЦ, ссылки на сайт
издания, его страницы на портале eLIBRARY.ru и сайтах maik.ru, Springer,
информацию о рецензируемости и наличии в системах Scopus,Web of Science,
перечне ВАК, а также дату добавления и изменения журнала в базе.
Структуры таблиц journals_specialty, journals_foreigndb, journals_branch
однотипны и состоят только из уникального идентификатора для каждого
элемента и самого наименования специальности, международной базы или же
отрасли наук. Они имеют следующий вид:
CREATE TABLE IF NOT EXISTS `scidb`.`journals_branch` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) CHARACTER SET 'utf8' NOT NULL,
PRIMARY KEY (`id`))
CREATE TABLE IF NOT EXISTS `scidb`.`journals_specialty` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) CHARACTER SET 'utf8' NOT NULL,
PRIMARY KEY (`id`))
CREATE TABLE IF NOT EXISTS `scidb`.`journals_foreigndb` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) CHARACTER SET 'utf8' NOT NULL,
PRIMARY KEY (`id`))
Между основными таблицами информационной системы проходит связь
М:М (многие-ко-многим) по причине того, что каждый журнал может
принадлежать к нескольким группам специальностей, отраслям наук и входить в
несколько международных баз данных, и естественно это же работает и в другую
сторону. По правилам этой связи [10], как видно из диаграммы системы,
создаются 3 промежуточные таблицы с названиями journals_library_branches,
journals_library_foreign_dbs и journals_library_specialties.
42
2.2 Импорт данных о журналах в базу веб-приложения
После создания разветвленной структуры для хранения необходимой
информации необходимо наполнить её
корректными данными исходя их
поставленных задач, а именно сведениями о научных периодических изданиях.
Импорт данных позволяет загружать данные из журналах из внешних источников,
коими являются внешние индексы цитирования и базы данных об изданиях.
В
данном
случае
стоит
пошагово
рассмотреть
работу
скрипта
import_journals, отвечающего за импорт информации непосредственно из
ресурсов, указанных в первой главе, а также то, как он будет взаимодействовать с
созданной в ходе работы над проектом информационной системой.
Вначале скрипт фиксирует время начала импорта с целью выяснения
затраты времени на сам процесс импортирования данных. После этого происходит
получение данных с сайтов elibrary, springer, maik и перечня ВАК и сохранение их
в SQLite:
start_time = time.time()
try:
save.to_sqlite()
Для того, чтобы перенаправить сохраненные данные из SQLite в MySQL
(т.к. SQLite является временным хранилищем), происходит извлечение списка
журналов из созданной базы:
data = database.select_all('journals')
new_journals = 0
current = 1
total = len(data)
После этого
действия требуется пройти в цикле по данным каждого
журнала и непосредственно встроить их в MySQL. Если же издание не попадет в
43
базу, то оно создается в ней отдельно, и в этом случае обновляются все
оставшиеся поля нового журнала:
for d in data:
journal, created = Library.objects.get_or_create(
outer_id=d['id'], title=d['title'], )
if created:
new_journals += 1
journal.description = ['description']
journal.publisher = d['publisher']
journal.issn_print = d['issn_print']
journal.issn_online = ['issn_online']
journal.impact_factor_jcr = d['impact_factor_jcr']
journal.impact_factor_rinc = d['impact_factor_rinc']
journal.journal_url = d['journal_url']
journal.elibrary_url = d['elibrary_url']
journal.maik_url = d['maik_url']
journal.springer_url = d['springer_url']
journal.reviewed = d['reviewed'] or False
journal.in_vak = d['in_vak'] or False
journal.in_rinc = d['in_rinc'] or False
journal.in_isi = d['in_isi'] or False
journal.in_scopus = d['in_scopus'] or False
journal.in_humanities = d['in_humanities'] or False
Нужно учитывать что отрасли наук, специальности и иностранные базы
данных хранятся в sqllite в виде строк, внутри которых элементы разделены с
помощью ';' . Эти строки обрабатываются, и полученные сущности сохраняются в
MySQL, при этом добавляясь к каждому из журналов, уже попавших в эту базу:
if d['branches']:
for name in d['branches'].split(';'):
44
branch, created =
Branch.objects.get_or_create(name=name)
journal.branches.add(branch)
if d['specialties']:
for name in d['specialties'].split(';'):
specialty, created =
Specialty.objects.get_or_create(name=name)
journal.specialties.add(specialty)
if d['foreign_db']:
for db_name in d['foreign_db'].split(';'):
foreign_db, created =
ForeignDb.objects.get_or_create(name=db_name)
journal.foreign_dbs.add(foreign_db)
Теперь, после того, как все данные о журналах получены (или обновлены,
если они уже проходили процедуру получения ранее), каждое из изданий и их
список в совокупности сохраняются в базу данных, пригодную для дальнейшей с
ней работы. При этом учитываются возможные ошибки при их получении, а также
отображается время, ушедшее на весь процесс импортирования:
journal.save()
print(u'[%d/%d] Сохранение: "%s"' % (current,
total, d['title']))
else:
print(u'[%d/%d] Уже есть в базе: "%s"' %
(current, total, d['title']))
current += 1
print(u'Добавлено %d новых журналов' % new_journals)
print(u'Успех!')
except Exception:
print(u'Ошибка при получении журналов:')
traceback.print_exc()
print(u"--- время импорта данных: %s минут ---" %
((time.time() - start_time) / 60))
45
ГЛАВА 3. РАЗРАБОТКА ВЕБ-ПРИЛОЖЕНИЯ
3.1 Архитектура проекта
Прежде чем перейти к подробному анализу работы над приложением, стоит
описать
весь
проект
в
целом.
Полученные
из
основных
ресурсов
(информационной системы eLibrary, сайтов издательств МАИК и Springer,
перечня рецензируемых научных изданий ВАК) данные о научных журналах
проходят процедуру парсинга и попадают сначала во временное хранилище, а
потом, вкупе с проверкой, корректировкой и обновлением сведений, в базу
данных, после чего на её основе строится каркас веб-приложения, в дальнейшем
работающий на основе созданной базы данных. При этом имеется возможность
обновления базы до актуального состояния без участия пользователя c помощью
планировщика задач CRON, который, в зависимости от выбранного времени,
каждый день будет актуализировать сведения об изданиях.
Сам
проект
представляет
из
себя
веб-приложение,
созданное
с
использованием фреймворка Django [12] и скрипт для получения, обработки и
сохранения данных о журналах, написанный на высокоуровневом языке Python
[13]. Эти вещи были объединены с помощью технологии ORM (объектнореляционное отображение), которая, связав базу данных с концепцией объектноориентированного языка программирования, помогла создать полноценную
информационную систему.
46
Рис. 2. Общая схема проекта
Скрипт импорта интегрирован в свободный программный каркас Django в
качестве отдельной команды и вызывается следующим образом:
python manage.py import_journals
Веб-приложение построено с использованием архитектуры MTV (Модельшаблон-представление). В этой концепции термин «Модель» относится к логике
доступа к данным; термин «Представление» относится к той части системы,
которая определяет, что показать и как, а термин «Управление» относится к той
части системы, которая определяет, какое представление надо использовать, в
зависимости от пользовательского ввода, по необходимости получая доступ к
модели [13].
47
3.2 Разработка дизайна проекта
Немаловажной является проблема, связанная с надлежащим оформлением
созданного интерфейса. Но, прежде чем приступить непосредственно к самому
дизайну, требуется определиться с основной стилистикой работы.
Выбор стиля оформления в первую очередь обусловлен тем, что данное вебприложение
впоследствии
будет
интегрировано
в
систему
электронной
отчётности о научной работе университета. Эта система использует фреймворк
для создания переносимых интерфейсов Semantic UI [14]. В данном случае он
используется в качестве основы для стилевого оформления элементов интерфейса.
Чтобы не нарушать единообразия, Semantic UI используется в данной работе с той
же целью.
Для данного типа веб-интерфейса за основу был выбран минимализм,
поскольку для справочных систем этот стиль наиболее приемлем [15]. Он не
отвлекает пользователя от представленной перед ним информации сложными
дизайнерскими решениями, при этом несмотря на то, что неискушенному
обывателю стиль может показаться простым и примитивным, на самом деле при
создании интерфейса нужно делать акцент на удобстве использования и
продуманности, что более приоритетно в текущей работе. Тем не менее он не
выглядит скучным благодаря использованному фреймворку, который органично
вписывается в общую канву проекта.
48
3.3 Проектирование веб-интерфейса
3.3.1 Главная страница
Заглавная страница приложения является “лицом” веб-интерфейса, так как
именно на неё прежде всего попадает пользователь. По этой причине начиная
именно с неё следует рассматривать весь интерфейс приложения. При открытии
главной страницы осуществляется
переход в корневой раздел приложения
(/journals/) и в это время на стороне django выполняется метод views.journals:
def journals(request):
journals_list = Library.objects.filter(search_query(request))
paginator = Paginator(journals_list, 50)
page = request.GET.get('page')
try:
journals = paginator.page(page)
except PageNotAnInteger:
journals = paginator.page(1)
except EmptyPage:
journals = paginator.page(paginator.num_pages)
url_params = request.GET.copy()
url_params.pop('page', None)
return render(request, 'journals/index.html', {
'url_params': url_params.urlencode(),
'search_form': SearchForm(request.GET),
'journals': journals,
'plural': choose_plural(journals.paginator.count, u'журнал',
u'журнала', u'журналов')
})
Внутри этого метода возможны два варианта развития событий:
1. Получение списка журналов без использования фильтров поиска
2. Получение списка журналов с использованием фильтров поиска
Первый вариант происходит при обычной загрузке страницы /journals/. В этом
случае для пользователя отображаются все журналы, имеющиеся в базе, при этом
проходя пагинацию – т.е. издания, вместо того чтобы одним огромным массивом
отображаться на странице, разбиваются на отдельные страницы с 50 элементами
на каждой из них.
49
Второй вариант происходит при отправке данных через форму поиска. В данном
случае список журналов будет автоматически отфильтрован по ним.
Метод спроектирован таким образом, чтобы обработка обоих вариантов ничем не
отличалась друг от друга. Это возможно, благодаря вспомогательному методу
views.search_query.
def search_query(request):
query = Q()
for k, v in request.GET.items():
if k == 'page':
continue
if v:
query.add(Q(**{k: v}), Q.AND)
return query
В качестве аргумента он принимает содержимое текущего запроса к
серверу. Далее он извлекает все параметры, которые были переданы в запросе
через форму поиска. Если параметр содержит в себе какое-либо значение, то его
основе динамически конструируется SQL-запрос. Для этого используется объект
Q (django.db.models.Q), который инкапсулирует множество аргументов, которые
можно
использовать
для
конструирования
SQL-запроса.
Эти
аргументы
подобраны оптимальным образом для каждого из полей таблицы журналов и
оформлены в виде формы поиска, представленной в объектно-ориентированном
стиле:
class SearchForm(forms.Form):
title__icontains = forms.CharField(label=u'Название',
required=False)
description__icontains = forms.CharField(label=u'Описание',
required=False)
publisher__icontains = forms.CharField(label=u'Издатель',
required=False)
issn_print__exact = forms.CharField(label=u'ISSN print',
required=False)
issn_online__exact = forms.CharField(label=u'ISSN online',
required=False)
50
reviewed__exact = forms.TypedChoiceField(label=u'Рецензируемый',
choices=CHOICES, coerce=int, required=False)
in_vak__exact = forms.TypedChoiceField(label=u'Входит в перечень
ВАК', choices=CHOICES, coerce=int, required=False)
in_rinc__exact = forms.TypedChoiceField(label=u'Входит в РИНЦ',
choices=CHOICES, coerce=int, required=False)
in_isi__exact = forms.TypedChoiceField(label=u'Входит в ISI',
choices=CHOICES, coerce=int, required=False)
in_scopus__exact = forms.TypedChoiceField(label=u'Входит в
SCOPUS', choices=CHOICES, coerce=int, required=False)
in_humanities__exact = forms.TypedChoiceField(label=u'Входит в
humanities', choices=CHOICES, coerce=int, required=False)
impact_factor_jcr__gt = forms.DecimalField(label=u'Импакт фактор
JCR больше', required=False)
impact_factor_jcr__lt = forms.DecimalField(label=u'Импакт фактор
JCR меньше', required=False)
impact_factor_rinc__gt = forms.DecimalField(label=u'Импакт
фактор РИНЦ больше', required=False)
impact_factor_rinc__lt = forms.DecimalField(label=u'Импакт
фактор РИНЦ меньше', required=False)
branches__id = forms.ModelChoiceField(label='Отрасль науки',
queryset=Branch.objects.all().order_by('name'), required=False)
specialties__id = forms.ModelChoiceField(label='Группы
специальностей', queryset=Specialty.objects.all().order_by('name'),
required=False)
foreign_dbs__id = forms.ModelChoiceField(label='Международная
база данных', queryset=ForeignDb.objects.all().order_by('name'),
required=False)
3.3.2 Форма поиска
Веб-интерфейс создавался с целью упрощения взаимодействия с базой
данных. Форма поиска является его основной частью, ведь именно на основе
данных, полученных из этой формы, конструируются поисковые SQL-запросы
таблице с журналами.
Форма спроектирована таким образом, чтобы можно было осуществлять поиск по
всем полям, принадлежащим таблице журналов.
51
Рис. 3. Форма поиска
Представленная в виде объекта форма поиска транслируется в следующий
html-код (с использованием синтаксиса шаблонов, который предоставляет
Django):
<form action="{% url 'journals' %}" class="ui form">
<div class="fields">
<div class="three wide field">
<label>Название</label>
{{ search_form.title__icontains }}
</div>
<div class="three wide field">
<label>Описание</label>
{{ search_form.description__icontains }}
</div>
<div class="three wide field">
<label>Издатель</label>
{{ search_form.publisher__icontains }}
</div>
<div class="two wide field">
<label>ISSN print</label>
{{ search_form.issn_print__exact }}
52
</div>
<div class="two wide field">
<label>ISSN online</label>
{{ search_form.issn_online__exact }}
</div>
</div>
<div class="fields">
<div class="three wide field">
<label>Рецензируемый</label>
{{ search_form.reviewed__exact }}
</div>
<div class="three wide field">
<label>Входит в перечень ВАК</label>
{{ search_form.in_vak__exact }}
</div>
<div class="three wide field">
<label>Входит в РИНЦ</label>
{{ search_form.in_rinc__exact }}
</div>
<div class="three wide field">
<label>Входит в ISI</label>
{{ search_form.in_isi__exact }}
</div>
<div class="three wide field">
<label>Входит в SCOPUS</label>
{{ search_form.in_scopus__exact }}
</div>
<div class="three wide field">
<label>Входит в humanities</label>
{{ search_form.in_humanities__exact }}
</div>
</div>
<div class="inline fields">
<div class="field">
{{ search_form.impact_factor_jcr__lt }}
<label>&lt; импакт фактор JCR &lt;</label>
{{ search_form.impact_factor_jcr__gt }}
</div>
<div class="field">
{{ search_form.impact_factor_rinc__lt }}
<label>&lt; импакт фактор РИНЦ &lt;</label>
53
{{ search_form.impact_factor_rinc__gt }}
</div>
</div>
<div class="fields">
<div class="five wide field">
<label>Отрасль науки</label>
{{ search_form.branches__id }}
</div>
<div class="five wide field">
<label>Специальность</label>
{{ search_form.specialties__id }}
</div>
<div class="five wide field">
<label>Международная база данных</label>
{{ search_form.foreign_dbs__id }}
</div>
</div>
<input class="ui primary button" type="submit" value="Найти">
{% if url_params %}
<a class="ui button" href="{% url 'journals' %}">Сброс</a>
{% endif %}
<a class="ui right floated black button" href="{% url
'new_journal' %}">Добавить журнал</a>
</form>
Любое из полей этой формы уникально, и поэтому автоматизировать
процесс формирования формы не представлялось возможным. Вместо этого
параметры каждого поля были настроены вручную.
Каждое поле этой формы представляет из себя аргумент для объекта Q,
например
title__icontains
превратится
в
регистро-независимую
проверку
содержимого поля title.
Таким образом, из множества переданных параметров будет сформированы
условия для SQL-запроса, которые объединяются конъюнкцией (логическим И)
для корректной работы запросов.
54
3.3.3 Список научных изданий
На главной странице, помимо формы поиска, располагается и имеющий
первостепенное значение список научных периодических изданий. Благодаря
верхней и нижней пагинации отображение списка является максимально удобным
для конечного пользователя.
Рис. 4. Список научных журналов
По сути, список изданий является таблицей с журналами в созданной базе
данных, и это можно увидеть из рис. 4. Как и форма поиска, таблица является
объектом и транслируется в следующий html-код (с использованием синтаксиса
шаблонов, который предоставляет Django):
<table class="ui selectable celled table">
<thead>
<tr>
<th>Название</th>
<th>Описание</th>
<th>Издательство</th>
<th>ISSN</th>
<th>Импакт фактор</th>
<th>Добавлен</th>
<th>Действие</th>
</tr>
55
</thead>
<tbody>
{% for journal in journals %}
{# static/js/journals/popup.js #}
<tr
{% for field, value in journal.as_dict.items %}
data-{{ field }}="{{ value }}"
{% endfor %}
>
<td class="journal_popup">{{ journal.title }}</td>
<td
class="journal_popup"
title="{{ journal.description }}">
{{ journal.description | default_if_none:'' |
truncatechars:30 }}
</td>
<td
class="journal_popup"
title="{{
journal.publisher
}}">{{
journal.publisher
|
truncatechars:30 }}</td>
<td class="journal_popup">
{{ journal.issn_print | default_if_none:''}}
{{ journal.issn_online | default_if_none:'' }}
</td>
<td class="journal_popup">
{{ journal.impact_factor_jcr | default_if_none:''}}
{{ journal.impact_factor_rinc | default_if_none:''}}
</td>
<td class="journal_popup">{{ journal.created_at | date:'d.m.Y'
}}</td>
<td>
В данном случае информация о журнале сохраняется в data-атрибутах
строки таблицы. Эти атрибуты будут использоваться при открытии всплывающего
окна с информацией о журнале, но конечному пользователю атрибуты строки
будут не видны. Так как в поля “Описание” и “Издательство” попадает слишком
много информации, которая впоследствии может отразиться на внешнем виде
таблицы не в лучшую сторону, то данные из этих полей обрезаются до 30
символов, и таким образом место в таблице распределяется более удачно. Но при
желании пользователь может посмотреть полную версию поля при наведении
курсора на ячейку.
56
3.3.4 Форма редактирования научного журнала
При нажатии на главной странице приложения на кнопку “Добавить
журнал”
пользователь
попадает
на
страницу
редактирования
журнала
(/journals/new), и перед ним предстает форма редактирования научного журнала.
Создание нового журнала внутри метода new_journal происходит по следующей
схеме: если пришли данные из формы и введенная информация валидна, то
происходит
создание
нового
журнала
информационную систему. В случае, когда
и
добавление
его
в
текущую
просто нужно отобразить страницу,
создается пустая форма для журнала и рендерится шаблон с её html-кодом.
def new_journal(request):
if request.method == 'POST':
form = LibraryForm(request.POST)
if form.is_valid():
form.save(commit=True)
return HttpResponseRedirect('/journals/')
else:
form = LibraryForm()
return render(request, 'journals/new.html', {'form': form})
57
Рис. 5. Форма редактирования
58
3.3.5 Поля редактирования отраслей, групп специальностей
и международных баз данных
Несмотря на то, что по большей части отрасли, группы специальностей и
международные базы данных добавляются автоматически одновременно с
научными журналами в ходе работы скрипта импорта журналов, существуют и
поля для их редактирования. Они были сделаны для возможного ручного
редактирования данных в случае изменений названий любой из этих групп.
Группы специальностей, международные базы данных и отрасли науки
отличаются друг от друга только названием таблицы, в которой хранятся данные.
В остальном они идентичны, поэтому, чтобы избежать дублирования кода, было
принято решение сделать универсальные шаблоны и методы для взаимодействия с
каждой из этих трёх сущностей.
Каждый из этих методов принимает набор
параметров, позволяющих использовать один и тот же шаблон для разных
моделей.
Рассмотрим подробнее эти методы и примеры шаблонов, которые они
генерируют.
Метод
journals.views.collection_index
генерирует
шаблон
journals/collection_index.html.
def collection_index(request, context):
return render(request,journals/collection_index.html',
context)
Внутри шаблона в зависимости от значения переменной active_item
происходит подсвечивание (добавление класса active) на элемент меню [16]. К
примеру, при значении 'foreign_dbs' в названии шаблона будет отображаться
надпись “Международные базы данных” (рис. 6). Аналогичным образом
подставляются и другие названия.
Таким
образом
будет
выглядеть
международных базах данных:
59
метод
получения
информации
о
def foreign_dbs(request):
return collection_index(request, {
'collection': ForeignDb.objects.all().order_by('name'),
'active_item': 'foreign_dbs',
'title': 'Международные базы данных',
'new_url': 'new_journal_foreign_db',
'edit_url': 'edit_journal_foreign_db',
'delete_url': 'delete_journal_foreign_db'
})
Рис. 6. Список международных баз
Метод journals.views.collection_new отвечает за генерирование шаблона
journals/collection_new.html.
def collection_new(request, form_class, redirect, context):
if request.method == 'POST':
form = form_class(request.POST)
if form.is_valid():
60
form.save(commit=True)
return HttpResponseRedirect(redirect)
else:
form = form_class()
context.update({'form': form})
return render(request, 'journals/collection_new.html', context)
Логика работы данного метода заключается в следующем: если пришли
данные из поля редактирования, то они сохраняются в список похожих данных,
после чего происходит возврат на
страницу с готовым списком на основе
шаблона, на которой уже будет добавленная пользователем информация. На рис 7.
представлен
пример
html-страницы
добавления
группы
специальностей,
работающей по этому принципу.
Рис.7. Поле добавления группы специальностей
Метод journals.views.collection_edit рендерит шаблон journals/ collection_edit.html.
Его логика работы практически такая же, как у предыдущего метода,
рассмотренного выше – после получения данных из формы редактирования и их
сохранения вновь отображается html-страница на основе шаблона, с которым
работает метод:
def collection_edit(request, element, form_class, redirect,
context):
if request.method == 'POST':
form = form_class(request.POST, instance=element)
if form.is_valid():
form.save(commit=True)
return HttpResponseRedirect(redirect)
else:
form = form_class(instance=element)
61
context.update({'form': form, 'element': element})
return render(request, 'journals/collection_edit.html', context)
Естественно, что в отличие от формы добавления, форма редактирования
работает только с уже существующими записями, например, с данными о
конкретной отрасли наук (рис. 8)
Рис. 8. Редактирование отрасли наук
62
ЗАКЛЮЧЕНИЕ
В данной работе получены следующие результаты:
1. Произведен обзор понятия «научный журнал», и критериев, по которым
издание является научным журналом.
2. Среди авторитетных баз данных и систем цитирования для импортирования
данных о научных периодических изданиях были выбраны следующие открытые
источники:
- российский информационный портал в области науки, медицины,
технологии и образования eLIBRARY.ru;
- перечень рецензируемых научных изданий, в которых должны быть
опубликованы основные научные результаты диссертаций на соискание
ученой степени кандидата наук, на соискание ученой степени доктора наук
Высшей
Аттестационной
Комиссии
Российской
Федерации
perechen.vak2.ed.gov.ru;
- сайт ведущего российского издательства научных журналов “МАИК
Наука/Интерпериодика” maik.ru;
- интерактивная база данных журналов, книжных серий, книг,
справочных
материалов
и
архивов
для
исследователей
и
ученых
международной издательской компании SPRINGER link.springer.com.
3. Получена база данных, содержащая научные журналы, отобранные на
основе
проанализированной
информации
с
возможностью
обновления и актуализации имеющейся информации.
4. Разработано веб-приложение для взаимодействия
с
ежедневного
базой
данных,
содержащее в себе весь необходимый функционал для поиска, создания,
изменения и удаления записей, содержащих информацию о научных изданиях.
Таким образом, можно сделать вывод о том, что в настоящей работе были
решены все поставленные задачи. Основным результатом работы является вебприложение с обширным информационным каталогом научных периодических
изданий,
отвечающее
содержащее
требованиям
необходимую
научно-педагогических
информацию
для
занимающихся научно-исследовательской работой.
63
сотрудников
работников
и
университета,
Данное приложение впоследствии будет интегрировано в информационную
систему научного отдела Орловского государственного университета имени И.С.
Тургенева с целью использования в качестве справочника по научным
периодическим изданиям.
64
СПИСОК ЛИТЕРАТУРЫ
1. Алексеева, Т.В. Информационно - аналитические системы. / Т.В.
Алексеева, Ю.В. Америди, М.Г Лужецкий, под общей ред. Т.В. Алексеевой. –
Москва: Московская финансово - промышленная академия, 2005. – 1 ч. – С. 54-67.
2. Документация Django на русском [Электронный ресурс]. – Режим доступа:
http://djbook.ru/. – Дата доступа: 18.04.2018
3. Документация по MySQL [Электронный ресурс]. – Режим доступа:
http://www.mysql.ru/docs. – Дата доступа: 29.04.2018.
4. Документация по Python [Электронный ресурс]. – Режим доступа:
https://www.python.org/doc/ . – Дата доступа: 01.04.2018.
5. Еременко, Г. О. Как проводились оценка и отбор российских научных
журналов в базу данных Russian Science Citation Index (RSCI) на Web of Science
[Электронный ресурс] / Г. О. Еременко, А. Я. Назаренко. - Режим доступа:
https://www.hse.ru/science/news/198490943.html. - Дата доступа: 28.04.2018
6. Еременко Г. О. Особенности национальной оценки научных журна-лов
[Электронный ресурс] / Г. О. Еременко // SCIENCE INDEX 2014: аналитические
инструменты и сервисы для оценки научной деятельности : науч.-практ. конф.,
Москва,
15-16
дек.
2014
г.
-
Режим
доступа:
http://elibrary.ru/projects/science_index/conf/2014/presentations.asp. - Дата доступа:
28.04.2018
7. Интерактивная база данных журналов, книжных серий, книг, справочных
материалов и архивов для исследователей и ученых международной издательской
компании
SPRINGER
[Электронный
ресурс].
–
Режим
доступа:
http://link.springer.com/ . – Дата доступа: 28.04.2018
8. Індекс інтегрованості періодичного видання в систему наукових
комунікацій
(бета-версія
2009
р.).
–
Режим
доступа:http://www.nbuv.gov.ua/portal/ink.html - Дата доступа: 28.04.2018
9. Категории и критерии оценки российских журналов и программы их
развития / О. В. Кириллова, А. Ю. Кузнецов, А. В. Диментов, В. В. Лебедев, М. Е.
65
Шварцман // Научная периодика: проблемы и решения. - 2014. - № 5 (23). - С. 2034.
10. Кириллова, О. В. Анализ результатов выполнения проекта по
господдержке
программ
развития
журналов:
показатели,
достоинства
и
недостатки, пожелания на будущее [Электронный ресурс] / О. В. Кириллова //
Заключительный семинар по Проекту государственной поддержки программ
развития журналов, Москва, 10 нояб. 2016 г. - Режим доступа: http://konkursjurnalov.neicon.ru/images/files/Кириллова.pdf. - Дата доступа: 28.04.2018
11. Кириллова, О. В. Конкурс программ развития журналов как зеркало
состояния редакционно-издательской системы российской научной периодики / О.
В. Кириллова // Научная периодика: проблемы и решения. - 2015. - Т. 5, № 2. - С.
56-74.
12. Кириллова О. В. Редакционная подготовка научных журналов по
международным стандартам. Рекомендации эксперта БД Scopus / О. В. Кириллова.
- М. : Elsevier, 2013. - Ч. 1. - 90 с.
13. Кириллова О. В. Создание программ комплексного развития журналов и
опыт их сравнительной оценки [Электронный ресурс] / О. В. Кириллова //
Консолидация ведущих российских научных журналов: проект Russian Science
Citation Index на платформе Web of Science : науч. семинар, Москва, 14 окт. 2014 г.
- Режим доступа: http://konkurs-jurnalov.neicon.ru/images/kirillova.pdf.
-
Дата
доступа: 28.04.2018
14. Котляров, И. Д. Принципы оценки качества научных журналов / И. Д.
Котляров // Образование и наука. - 2010. - № 8 (76). - С. 4-19.
15. Лоскутова, Т. А. Современные подходы к оценке качества российских
научных журналов / Т. А. Лоскутова // Baikal Research Journal. — 2017. — Т. 8, №
1. — DOI: 10.17150/2411-6262.2017.8(1).16.
16. Марк Лутц. Программирование на Python. /М.Лутц. – М: Символ-Плюс,
2011. – 992 с.
66
17.
Маршакова-Шайкевич,
И.
В.
Роль
библиометрии
в
оценке
исследовательской активности науки / И. В. Маршакова-Шайкевич // Управление
большими системами. - 2013. - № 44. - С. 210-247.
18. Методические рекомендации по подготовке и оформлению научных
статей в журналах, индексируемых в международных наукометрических базах
данных [Электронный ресурс] / под общ. ред. О. В. Кирилловой. - М., 2017. - 144
c.
-
Режим
доступа:
http://rasep.ru/images/materials/Методрекомендации
%20полные-на%20сайт%20АНРИ.pdf.
-
Дата доступа: 28.04.2018
19. Научная электронная библиотека [Электронный ресурс]. – Режим
доступа: http://elibrary.ru/ . – Дата доступа: 10.05.2018.
20. Научное издание международного уровня - 2015: современные тенденции
в мировой практике редактирования, издания и оценки научных публикаций :
материалы 4-й Междунар. науч.-практ. конф., Санкт-Петербург, 26-29 мая 2015 г. /
отв. ред. О. В. Кириллова. - СПб. : Сев.-Зап. ин-т упр. - фил. РАНХиГС, 2015. - 188
с.
21. Научное издание международного уровня - 2016: решение проблем
издательской этики, рецензирования и подготовки публикаций : материалы 5-й
Междунар. науч.-практ. конф., Москва, 17-20 мая 2016 г. / отв. ред. О. В.
Кириллова. - Екатеринбург : Изд-во Урал. ун-та, 2016. - 324 с.
22. Ожегов, Д.В. Введение в SQLite. / Д.В. Ожегов. – М.: Символ-плюс,
2004.– 98с.
23. Официальный сайт фреймворка для создания переносимых интерфейсов
Semantic UI [Электронный ресурс]. –
Режим доступа:http://semantic-ui.com/. –
Дата доступа: 15.05.2016
24. Пахомов, С. И. О перечне рецензируемых научных изданий [Электронный
ресурс] / С. И. Пахомов // Научное издание международного уровня - 2016:
решение проблем издательской этики, рецензирования и подготовки публикаций :
материалы 5-й Междунар. науч.-практ. конф., Москва, 17-20 мая 2016 г. - Режим
доступа:
http://conf.neicon.ru/index.php/science/domestic0516/schedConf/program.
Дата доступа: 28.04.2018.
67
25. Перечень рецензируемых научных изданий ВАК, в которых должны быть
опубликованы основные научные результаты диссертаций на соискание ученой
степени кандидата наук, на соискание ученой степени доктора наук [Электронный
ресурс]. – Режим доступа: http://perechen.vak2.ed.gov.ru/ . – Дата доступа:
10.05.2018.
26. Петров, В.Н. Информационные системы. / В.Н. Петров – СПб.: Питер,
2002. – 724 с.
27. Писляков В. В. Методы оценки научного знания по показателям
цитирования / В. В. Писляков // Социологический журнал. - 2007. - № 1. - C. 128140.
28. Пономарева Н. И. Библиометрия: краткие методологические комментарии
[Электронный ресурс] / Н. И. Пономарева, Г. А. Козбогарова, Т. Ш. Кубиева //
Новости
науки
Казахстана.
-
2013.
-
Вып.
1.
-
Режим
доступа:
http://www.vestnik.nauka.kz/informatika/bibliometriya-kratkie-metodologicheskiekommentarii.php. - Дата доступа: 28.04.2018.
29. Руководство по наукометрии: индикаторы развития науки и технологии :
монография / М. А. Акоев, В. А. Маркусова, О. В. Москалева [и др.] ; под ред. М.
А. Акоева. - Екатеринбург : Изд-во Урал. ун-та, 2014. - 250 с.
30. Сайт ведущего российского издательства научных журналов “МАИК
Наука/Интерпериодика» [Электронный ресурс]. – Режим доступа: http://maik.ru/ .
– Дата доступа: 29.04.2018.
31. Санина, Л. В. Известия Иркутской государственной экономической
академии: четверть века на службе науки (по материалам Российского индекса
научного цитирования) / Л. В. Санина, Т. А. Лоскутова // Известия Иркутской
государственной экономической академии. - 2015. - Т. 25, № 2. - С. 221-231. - DOI:
10.17150/1993-3541.2015.25(2).221-231.
32. Сервис расчета российского импакт-фактора (РИФ)
[Электронный
ресурс]. – Режим доступа: http://impact-factor.ru/. – Дата доступа: 1.04.2018.
33. Сырых Ю.А. Современный веб-дизайн. Эпоха Веб 3.0. 2-е изд. / Ю. А.
Сырых. - М.: 000 “И.Д. Вильямс”, 2013. - 368 с.: ил.
68
34. Ульман Л. MySQL - Руководство по изучению языка./ Л. Ульман. - М:
ДМК Пресс, Питер, 2004. - 352 с.
35.
Школа
Python
[Электронный
ресурс].
–
Режим
доступа:
http://www.russianlutheran.org/python/python.html . – Дата доступа: 18.04.2018.
69
ПРИЛОЖЕНИЕ
Исходный код проекта
Серверная часть
Модели
journals/models.py
# encoding: utf-8
from django.db import models
# Отрасль науки
class Branch(models.Model):
name = models.CharField(u'Название', max_length=255,
null=False, unique=True)
def __unicode__(self):
return self.name
# Специальность
class Specialty(models.Model):
name = models.CharField(u'Название', max_length=255,
null=False, unique=True)
def __unicode__(self):
return self.name
# Международная база данных
class ForeignDb(models.Model):
name = models.CharField(u'Название', max_length=255,
null=False, unique=True)
def __unicode__(self):
return self.name
# Журнал
class Library(models.Model):
outer_id = models.PositiveIntegerField(u'Внешний id',
null=True)
title = models.CharField(u'Название', max_length=255,
70
null=True)
description = models.TextField(u'Описание', null=True)
publisher = models.CharField(u'Издательство',
max_length=255, null=True, blank=True)
issn_print = models.CharField(u'ISSN печатной версии',
max_length=16, null=True, blank=True)
issn_online = models.CharField(u'ISSN онлайновой версии',
max_length=16, null=True, blank=True)
impact_factor_jcr = models.FloatField(u'Импакт-фактор
JCR', null=True, blank=True)
impact_factor_rinc = models.FloatField(u'Импакт-фактор
РИНЦ', null=True, blank=True)
journal_url = models.CharField(u'Ссылка на сайт журнала',
max_length=255, null=True, blank=True)
elibrary_url = models.CharField(u'Ссылка на журнал в
elibrary', max_length=255, null=True, blank=True)
maik_url = models.CharField(u'Ссылка на журнал в maik',
max_length=255, null=True, blank=True)
springer_url = models.CharField(u'Ссылка на сайт в
springer', max_length=255, null=True, blank=True)
reviewed = models.BooleanField(u'Рецензируемый',
default=False)
in_vak = models.BooleanField(u'Входит в перечень ВАК',
default=False)
in_rinc = models.BooleanField(u'Входит в РИНЦ',
default=False)
in_isi = models.BooleanField(u'Входит в ISI',
default=False)
in_scopus = models.BooleanField(u'Входит в SCOPUS',
default=False)
in_humanities = models.BooleanField(u'Входит в
humanities', default=False)
branches = models.ManyToManyField(Branch, blank=True,
71
verbose_name=u'Отрасли наук', help_text=u'Выберите одну или
несколько отраслей наук')
specialties = models.ManyToManyField(Specialty,
blank=True, verbose_name=u'Специальности',
help_text=u'Выберите одну или несколько специальностей')
foreign_dbs = models.ManyToManyField(ForeignDb,
blank=True, verbose_name=u'Международные базы',
help_text=u'Выберите одну или несколько международных баз')
# время создания и время последнего изменения (обновляются
автоматически)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
# представление журнала в виде python-словаря
# используется при отображении информации о журнале во
всплывающем окне
# templates/journals/index.html
def as_dict(self):
result = self.__dict__.copy()
result['created_at'] =
result['created_at'].strftime('%d.%m.%Y')
result['branches'] = ',
'.join(self.branches.values_list('name', flat=True))
result['specialties'] = ',
'.join(self.specialties.values_list('name', flat=True))
result['foreign_dbs'] = ',
'.join(self.foreign_dbs.values_list('name', flat=True))
return result
class Meta:
unique_together = ('outer_id', 'title')
Представления
journals/views.py
# encoding: utf-8
from django.core.paginator import Paginator, EmptyPage,
PageNotAnInteger
72
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect
from django.db.models import Q
from journals.forms import LibraryForm, BranchForm,
SpecialtyForm, ForeignDbForm
from journals.forms import SearchForm
from journals.models import Library, Branch, Specialty,
ForeignDb
# правильное склонение слова во множественном числе
# пример данных: choose_plural(5, 'журнал', 'журнала',
'журналов')
def choose_plural(n, form1, form2, form5):
n1 = abs(n) % 100
n2 = n % 10
if n1 > 10 and n1 < 20:
return form5
elif n2 > 1 and n2 < 5:
return form2
elif n2 == 1:
return form1
else:
return form5
# динамически конструируем запрос для поиска данных
def search_query(request):
query = Q()
# извлекаем все параметры, кроме page из GET-запроса
for k, v in request.GET.items():
if k == 'page':
continue
# если параметр содержит в себе что-нибудь
if v:
# добавляем его к итоговому запросу, используя
логическои И
query.add(Q(**{k: v}), Q.AND)
return query
# главная страница: список журналов
73
# шаблон: templates/journals/index.html
def journals(request):
# получаем список журналов
# если через форму поиска были введены какие-то значения,
# то список журналов будет автоматически отфильтрован по
ним
journals_list =
Library.objects.filter(search_query(request))
# включаем пагинацию (50 элементов на страницу
paginator = Paginator(journals_list, 50)
# текущая страница
page = request.GET.get('page')
# извлекаем журналы для текущей страницы
try:
journals = paginator.page(page)
except PageNotAnInteger:
journals = paginator.page(1)
except EmptyPage:
journals = paginator.page(paginator.num_pages)
# получаем список параметров, переданных в запросе
url_params = request.GET.copy()
# удаляем из этого списка параметр page
# (все остальные параметры будут из формы поиска)
url_params.pop('page', None)
return render(request, 'journals/index.html', {
# пробрасываем параметр url_params в шаблон
# чтобы сохранять выбранные фильтры в форме поиска
# при переключении между страницами
'url_params': url_params.urlencode(),
'search_form': SearchForm(request.GET),
'journals': journals,
# правильное склонения слова "журналы"
# чтобы внизу таблицы с журналами вывести красивое
сообщение
'plural': choose_plural(journals.paginator.count,
u'журнал', u'журнала', u'журналов')
})
74
# создание нового журнала
# шаблон: templates/journals/new.html
def new_journal(request):
# если пришли данные из формы
if request.method == 'POST':
form = LibraryForm(request.POST)
# и они валидны
if form.is_valid():
# то создаём новый журнал
form.save(commit=True)
return HttpResponseRedirect('/journals/')
# если просто нужно отобразить страницу
else:
# создаём пустую форму для журнала
# и рендерим шаблон
form = LibraryForm()
return render(request, 'journals/new.html', {'form':
form})
# редактирование журнала
# шаблон: templates/journals/edit.html
def edit_journal(request, journal_id):
# получение объекта
journal = get_object_or_404(Library, pk=journal_id)
# пришли данные из формы
if request.method == 'POST':
form = LibraryForm(request.POST, instance=journal)
# пробуем обновить журнал
if form.is_valid():
form.save(commit=True)
return HttpResponseRedirect('/journals/')
# нужно просто отобразить страницу
else:
# инициализируем форму с текущим журналам
form = LibraryForm(instance=journal)
return render(request, 'journals/edit.html', {
'form': form,
'journal': journal
})
75
# удаление журнала
def delete_journal(request, journal_id):
journal = get_object_or_404(Library, pk=journal_id)
journal.delete()
return HttpResponseRedirect('/journals')
# отрасли наук
# шаблон: templates/journals/collection_index.html
def branches(request):
return collection_index(request, {
'collection': Branch.objects.all().order_by('name'),
'active_item': 'branches',
'title': 'Отрасли науки',
'new_url': 'new_journal_branch',
'edit_url': 'edit_journal_branch',
'delete_url': 'delete_journal_branch'
})
# создание новой отрасли наук
# шаблон: templates/journals/collection_new.html
def new_branch(request):
return collection_new(request, BranchForm,
'/journals/branches', {
'title': 'Создание новой отрасли наук',
'new_url': 'new_journal_branch'
})
# редактирование отрасли наук
# шаблон: templates/journals/collection_edit.html
def edit_branch(request, branch_id):
element = get_object_or_404(Branch, pk=branch_id)
return collection_edit(request, element, BranchForm,
'/journals/branches', {
'edit_url': 'edit_journal_branch'
})
76
# удаление отрасли наук
def delete_branch(request, branch_id):
branch = get_object_or_404(Branch, pk=branch_id)
branch.delete()
return HttpResponseRedirect('/journals/branches')
# специальности
# шаблон: templates/journals/collection_index.html
def specialties(request):
return collection_index(request, {
'collection':
Specialty.objects.all().order_by('name'),
'active_item': 'specialties',
'title': 'Специальности',
'new_url': 'new_journal_specialty',
'edit_url': 'edit_journal_specialty',
'delete_url': 'delete_journal_specialty'
})
# создание новой специальности
# шаблон: templates/journals/collection_new.html
def new_specialty(request):
return collection_new(request, SpecialtyForm,
'/journals/specialties', {
'title': 'Создание специальности',
'new_url': 'new_journal_specialty'
})
# редактирование специальности
# шаблон: templates/journals/collection_edit.html
def edit_specialty(request, specialty_id):
element = get_object_or_404(Specialty, pk=specialty_id)
return collection_edit(request, element, SpecialtyForm,
'/journals/specialtyes', {
'edit_url': 'edit_journal_specialty'
77
})
# удаление специальности
def delete_specialty(request, specialty_id):
specialty = get_object_or_404(Specialty, pk=specialty_id)
specialty.delete()
return HttpResponseRedirect('/journals/specialties')
# международные базы данных
# шаблон: templates/journals/collection_index.html
def foreign_dbs(request):
return collection_index(request, {
'collection':
ForeignDb.objects.all().order_by('name'),
'active_item': 'foreign_dbs',
'title': 'Международные базы данных',
'new_url': 'new_journal_foreign_db',
'edit_url': 'edit_journal_foreign_db',
'delete_url': 'delete_journal_foreign_db'
})
# международные базы данных
# шаблон: templates/journals/collection_new.html
def new_foreign_db(request):
return collection_new(request, ForeignDbForm,
'/journals/foreign_dbs', {
'title': 'Создание новой международной базы',
'new_url': 'new_journal_foreign_db'
})
# редактирование международной базы данных
# шаблон: templates/journals/collection_edit.html
def edit_foreign_db(request, foreign_db_id):
element = get_object_or_404(ForeignDb, pk=foreign_db_id)
return collection_edit(request, element, ForeignDbForm,
78
'/journals/foreign_dbs', {
'edit_url': 'edit_journal_foreign_db'
})
def delete_foreign_db(request, foreign_db_id):
foreign_db = get_object_or_404(ForeignDb,
pk=foreign_db_id)
foreign_db.delete()
return HttpResponseRedirect('/journals/foreign_dbs')
# Три сущности: Branch, Specialty и ForeignDb имеют всего одно
поле - name.
# Чтобы избежать дублирования кода - используются
универсальные методы:
# collection_index, collection_edit, collection_new
# Каждый из методов получает необходимый набор параметров и
рендерит соответствующий шаблон.
# шаблон: templates/journals/collection_edit.html
def collection_index(request, context):
return render(request, 'journals/collection_index.html',
context)
# шаблон: templates/journals/collection_new.html
def collection_new(request, form_class, redirect, context):
# пришли данные из формы
if request.method == 'POST':
form = form_class(request.POST)
if form.is_valid():
form.save(commit=True)
return HttpResponseRedirect(redirect)
# просто отображаем страницу
else:
form = form_class()
context.update({'form': form})
return render(request, 'journals/collection_new.html',
79
context)
# шаблон: templates/journals/collection_edit.html
def collection_edit(request, element, form_class, redirect,
context):
# пришли данные из формы
if request.method == 'POST':
form = form_class(request.POST, instance=element)
if form.is_valid():
form.save(commit=True)
return HttpResponseRedirect(redirect)
# просто отображаем страницу
else:
form = form_class(instance=element)
context.update({'form': form, 'element': element})
return render(request, 'journals/collection_edit.html',
context)
Формы
journals/forms.py
# encoding: utf-8
from django import forms
from journals.models import Library, Branch, Specialty,
ForeignDb
class LibraryForm(forms.ModelForm):
class Meta:
model = Library
fields = '__all__'
class BranchForm(forms.ModelForm):
class Meta:
model = Branch
fields = '__all__'
80
class SpecialtyForm(forms.ModelForm):
class Meta:
model = Specialty
fields = '__all__'
class ForeignDbForm(forms.ModelForm):
class Meta:
model = ForeignDb
fields = ['name']
CHOICES = (('', u'Не выбрано'), (1, u'Да'), (0, u'Нет'))
class SearchForm(forms.Form):
title__icontains = forms.CharField(label=u'Название',
required=False)
description__icontains =
forms.CharField(label=u'Описание', required=False)
publisher__icontains = forms.CharField(label=u'Издатель',
required=False)
issn_print__exact = forms.CharField(label=u'ISSN print',
required=False)
issn_online__exact = forms.CharField(label=u'ISSN online',
required=False)
reviewed__exact =
forms.TypedChoiceField(label=u'Рецензируемый',
choices=CHOICES, coerce=int, required=False)
in_vak__exact = forms.TypedChoiceField(label=u'Входит в
перечень ВАК', choices=CHOICES, coerce=int, required=False)
in_rinc__exact = forms.TypedChoiceField(label=u'Входит в
РИНЦ', choices=CHOICES, coerce=int, required=False)
in_isi__exact = forms.TypedChoiceField(label=u'Входит в
ISI', choices=CHOICES, coerce=int, required=False)
in_scopus__exact = forms.TypedChoiceField(label=u'Входит в
SCOPUS', choices=CHOICES, coerce=int, required=False)
in_humanities__exact =
81
forms.TypedChoiceField(label=u'Входит в humanities',
choices=CHOICES, coerce=int, required=False)
impact_factor_jcr__gt = forms.DecimalField(label=u'Импакт
фактор JCR больше', required=False)
impact_factor_jcr__lt = forms.DecimalField(label=u'Импакт
фактор JCR меньше', required=False)
impact_factor_rinc__gt = forms.DecimalField(label=u'Импакт
фактор РИНЦ больше', required=False)
impact_factor_rinc__lt = forms.DecimalField(label=u'Импакт
фактор РИНЦ меньше', required=False)
branches__id = forms.ModelChoiceField(label='Отрасль
науки', queryset=Branch.objects.all().order_by('name'),
required=False)
specialties__id =
forms.ModelChoiceField(label='Специальность',
queryset=Specialty.objects.all().order_by('name'),
required=False)
foreign_dbs__id =
forms.ModelChoiceField(label='Международная база данных',
queryset=ForeignDb.objects.all().order_by('name'),
required=False)
Маршруты
journals/urls.py
from django.conf.urls import patterns, url
from journals import views
urlpatterns = patterns('',
url(r'^$', views.journals, name='journals'),
url(r'^new$', views.new_journal, name='new_journal'),
url(r'^(?P<journal_id>\d+)/edit$', views.edit_journal,
name='edit_journal'),
url(r'^(?P<journal_id>\d+)/delete$', views.delete_journal,
name='delete_journal'),
url(r'^branches$', views.branches, name='branches'),
url(r'^branches/new$', views.new_branch,
name='new_journal_branch'),
82
url(r'^branches/(?P<branch_id>\d+)/edit$',
views.edit_branch, name='edit_journal_branch'),
url(r'^branches/(?P<branch_id>\d+)/delete$',
views.delete_branch, name='delete_journal_branch'),
url(r'^specialties$', views.specialties,
name='specialties'),
url(r'^specialties/new$', views.new_specialty,
name='new_journal_specialty'),
url(r'^specialties/(?P<specialty_id>\d+)/edit$',
views.edit_specialty, name='edit_journal_specialty'),
url(r'^specialties/(?P<specialty_id>\d+)/delete$',
views.delete_specialty, name='delete_journal_specialty'),
url(r'^foreign_dbs$', views.foreign_dbs,
name='foreign_dbs'),
url(r'^foreign_dbs/new$', views.new_foreign_db,
name='new_journal_foreign_db'),
url(r'^foreign_dbs/(?P<foreign_db_id>\d+)/edit$',
views.edit_foreign_db, name='edit_journal_foreign_db'),
url(r'^foreign_dbs/(?P<foreign_db_id>\d+)/delete$',
views.delete_foreign_db, name='delete_journal_foreign_db'),
)
Импорт данных
journals/management/commands/import_journals.py
# encoding: utf-8
from django.core.management.base import BaseCommand
from journals.models import Library, Branch, Specialty,
ForeignDb
from journals.parser import save
from journals.parser import database
import traceback
import time
class Command(BaseCommand):
83
help = u'Импорт журналов'
def handle(self, *args, **options):
# фиксируем время начала импорта
start_time = time.time()
try:
# получаем данные с сайтов и сохраняем их в sqlite
save.to_sqlite()
print(u'Сохраняем полученные данные в MySQL...')
# извлекаем список журналов из sqlite
data = database.select_all('journals')
new_journals = 0
# счётчик новых журналов
current = 1
# порядковый номер текущего
total = len(data)
# всего журналов
журнала
# проходим по данным каждого журнала
for d in data:
# получаем журнал из MySQL
# если его там, нет то создаём новый
journal, created =
Library.objects.get_or_create(
outer_id=d['id'],
title=d['title'],
)
# если был создан новый журнал
if created:
new_journals += 1
# обновляем все оставшиеся поля нового
журнала
journal.description = d['description']
journal.publisher = d['publisher']
journal.issn_print = d['issn_print']
journal.issn_online = d['issn_online']
journal.impact_factor_jcr =
d['impact_factor_jcr']
journal.impact_factor_rinc =
d['impact_factor_rinc']
journal.journal_url = d['journal_url']
84
journal.elibrary_url = d['elibrary_url']
journal.maik_url = d['maik_url']
journal.springer_url = d['springer_url']
journal.reviewed = d['reviewed'] or False
journal.in_vak = d['in_vak'] or False
journal.in_rinc = d['in_rinc'] or False
journal.in_isi = d['in_isi'] or False
journal.in_scopus = d['in_scopus'] or
False
journal.in_humanities = d['in_humanities']
or False
# отрасли наук, специальности и
иностранные базы данных
# хранятся в sqllite в виде строк, внутри
которых элементы
# разделены с помощью ';'
# мы обрабатываем эти строки и сохраняем
полученные сущности в MySQL
# добавляя их к журналу
if d['branches']:
for name in d['branches'].split(';'):
branch, created =
Branch.objects.get_or_create(
name=name
)
journal.branches.add(branch)
if d['specialties']:
for name in
d['specialties'].split(';'):
specialty, created =
Specialty.objects.get_or_create(
name=name
)
journal.specialties.add(specialty)
if d['foreign_db']:
for db_name in
85
d['foreign_db'].split(';'):
foreign_db, created =
ForeignDb.objects.get_or_create(
name=db_name
)
journal.foreign_dbs.add(foreign_db)
# все данные обновлены, сохраняем журнал
journal.save()
print(u'[%d/%d] Сохранение: "%s"' %
(current, total, d['title']))
else:
print(u'[%d/%d] Уже есть в базе: "%s"' %
(current, total, d['title']))
current += 1
print(u'Добавлено %d новых журналов' %
new_journals)
print(u'Успех!')
except Exception:
print(u'Ошибка при получении журналов:')
traceback.print_exc()
print(u"--- время импорта данных: %s минут ---" %
((time.time() - start_time) / 60))
journals/parser/database.py
#!/usr/bin/env python2
# encoding: utf-8
import sqlite3
import os
__location__ = os.path.dirname(os.path.realpath(__file__))
database_path = os.path.join(__location__, '../journals.db')
connection = sqlite3.connect(database_path)
def create_table(name, columns):
''' Создание таблицы (если её ещё не существует) '''
c = connection.cursor()
86
query = 'CREATE TABLE IF NOT EXISTS %s (\n' % name
query += ',\n'.join(columns)
query += ')'
c.execute(query)
connection.commit()
c.close()
def id_exists(table, id):
''' Проверяем, есть ли указанный id в таблице '''
c = connection.cursor()
c.execute('SELECT * FROM %s WHERE id = ?' % table, (id,))
result = bool(c.fetchone())
c.close()
return result
def find_in_table(table, column, value):
'''
Проверяем, входит ли указанное значение в заданный столбец
таблицы.
Если входит - возвращаем id.
Используется для поиска журналов по ISSN.
'''
if not value:
return
c = connection.cursor()
# поиск любого вхождения value в строку column
c.execute("SELECT id FROM %s WHERE instr(%s, '%s') > 0" %
(table, column, value))
row = c.fetchone()
c.close()
return (row[0] if row else None)
def select(table, id):
''' Получение всех данных по указанному id '''
c = connection.cursor()
row = c.execute('SELECT * FROM %s WHERE id = ?' % table,
87
(id,))
row = c.fetchone()
c.close
# преобразовываем список в словарь
result = _convert_row_to_dict(row, c.description) if row
else {}
c.close
return result
def select_all(table):
''' Получение всех данных из указанной таблицы в виде
списка словарей '''
c = connection.cursor()
rows = c.execute('SELECT * FROM %s' % table)
# преобразовываем список в словарь
result = [_convert_row_to_dict(row, c.description) for row
in rows]
c.close
return result
def insert(table, data):
''' Универсальный метод вставки любых данных в указанную
таблицу '''
c = connection.cursor()
try:
fields = ['"%s"' % k for k in data.keys()]
question_marks = ','.join('?' * len(data.values()))
query = 'INSERT INTO %s (%s) VALUES (%s)' % (table,
','.join(fields), question_marks)
c.executemany(query, (data.values(),))
connection.commit()
return True
except sqlite3.IntegrityError:
return False
finally:
c.close()
88
def delete(table, id):
''' Удаление из таблицы по id '''
c = connection.cursor()
c.execute('DELETE FROM %s WHERE id = %d' % (table, id))
c.close()
def _convert_row_to_dict(values, description):
''' Преобразование списка в словарь для результатов
запроса '''
result = {}
for i, columns in enumerate(description):
column_name = columns[0]
result[column_name] = values[i]
return result
journals/parser/elibrary.py
#!/usr/bin/env python2
# encoding: utf-8
import re
import database
import datetime
from util import *
from bs4 import BeautifulSoup
def save_all_journals():
''' Получение и сохранение всех журналов в бд '''
print(('*' * 20) + ' elibrary.ru ' + ('*' * 20))
journals_list = _get_journals_list()
total = len(journals_list)
print(u'Найдено %d журналов' % total)
for i, journal in enumerate(journals_list):
prefix = '[%d/%d] (elibrary)' % (i + 1, total)
if database.id_exists('elibrary', journal['id']):
already_exists_notify(prefix, journal['title'])
else:
89
data = _get_journal(journal['id'],
journal['title'])
if data:
save_notify(prefix, journal['title'])
database.insert('elibrary', data)
else:
get_error_notify(prefix, journal['title'])
def _get_journals_list():
''' Получение списка журналов для последующей обработки
'''
print('Получаем список журналов elibrary...')
html = make_request(
'http://elibrary.ru/org_items_titles.asp'
'?id=1584&order=0&selids=&show_authors=0&show_refs=1'
'&orgdepid=0&rand=0.9622463253326714'
)
if html:
result = []
soup = BeautifulSoup(html, 'html.parser')
trs = soup.find_all('tr')
for tr in trs:
journal_id = int(tr['id'].split('_')[1])
title_with_occurrences = tr.td.next_sibling.text
m = re.match(r'(.*)\((\d+)\)',
title_with_occurrences)
journal_title = m.group(1).strip()
journal_occurrences = int(m.group(2))
result.append({
'id': journal_id,
'title': journal_title,
'occurrences': journal_occurrences
})
return result
else:
print('Не удалось получить список журналов...')
return []
90
def _get_journal(id, title):
''' Получение и обработка данных журнала по заданному id
'''
html = make_request('http://elibrary.ru/title_about.asp?
id=%s' % id)
if html:
soup = BeautifulSoup(html, 'html.parser')
simple_values = [
u'Издательство',
u'Год основания',
u'Рецензируемый',
u'Выпусков в год',
u'Импакт-фактор JCR',
u'Статей в выпуске',
u'Импакт-фактор РИНЦ',
u'Сокращение',
u'Страна',
u'Город',
u'Регион',
u'Подписной индекс',
u'Тираж',
u'ISSN печатной версии',
u'ISSN онлайновой версии',
u'Вариант представления',
u'WWW-адрес',
u'ISI',
u'SCOPUS',
u'РИНЦ',
u'Перечень ВАК',
u'Всего статей',
u'Всего выпусков',
u'Полных текстов',
u'Цитирований',
u'В настоящее время',
u'Доступный архив',
u'Реферативный',
u'Мультидисциплинарный',
]
91
complex_values = [
u'Описание журнала',
u'Редакционная коллегия',
u'Aims & Scope',
]
result = {}
result['id'] = id
# на elibrary полное название будет "В ТАКОМ ВИДЕ",
поэтому сохраняем
# его в нормальном формате
result[u'Полное название'] = title
for value in simple_values:
try:
result[value] = _find_simple_value(soup,
value)
except Exception:
print(u'Ошибка обработки поля "%s" у журнала
"%s" (#%s)' % (value, title, id))
result[value] = ''
for value in complex_values:
try:
result[value] = _find_complex_value(soup,
value)
except Exception:
print(u'Ошибка обработки поля "%s" у журнала
"%s" (#%s)' % (value, title, id))
result[value] = ''
result['created_at'] = str(datetime.datetime.now())
return result
def _find_simple_value(soup, key):
''' Поиск простого значения по html журнала '''
td_with_name = soup.find(text=re.compile('^%s' %
key)).find_parent('td')
td_with_value = td_with_name.next_sibling
value = td_with_value.next_element.text.strip()
return _check_value(value)
92
def _find_complex_value(soup, key):
''' Поиск непростого значения по html журнала '''
if key in [u'Описание журнала', u'Редакционная коллегия']:
key = ''.join(key.split(' '))
fonts = soup.find_all('font')
value = None
for font in fonts:
string = font.text
if string and string == key:
main_table =
font.find_parent('table').find_parent('table')
value = main_table.find_all('font')[-1].text
break
return _check_value(value)
def _check_value(value):
''' Пытаемся привести значение к нужному типу данных '''
if value in (u'да', u'включен'):
return 1
elif value in ('', u'нет', None):
return None
elif _isfloat(value):
# числа типа float на elibrary выглядят так '3,14'
return float(value.replace(',', '.'))
elif value.isdigit():
return int(value)
else:
return value
def _isfloat(value):
''' Пробуем выяснить, можно ли привести строку к типу
float '''
try:
float(value.replace(',', '.'))
return True
93
except ValueError:
return False
database.create_table('elibrary', [
"id INTEGER UNIQUE",
"'Полное название' TEXT",
"'Издательство' TEXT",
"'Год основания' INTEGER",
"'Рецензируемый' BOOLEAN",
"'Выпусков в год' INTEGER",
"'Импакт-фактор JCR' TEXT",
"'Статей в выпуске' INTEGER",
"'Импакт-фактор РИНЦ' REAL",
"'Сокращение' TEXT",
"'Страна' TEXT",
"'Город' TEXT",
"'Регион' TEXT",
"'Подписной индекс' TEXT",
"'Тираж' INTEGER",
"'ISSN печатной версии' TEXT",
"'ISSN онлайновой версии' TEXT",
"'Вариант представления' TEXT",
"'WWW-адрес' TEXT",
"'ISI' BOOLEAN",
"'SCOPUS' BOOLEAN",
"'РИНЦ' BOOLEAN",
"'Перечень ВАК' BOOLEAN",
"'Всего статей' INTEGER",
"'Всего выпусков' INTEGER",
"'Полных текстов' INTEGER",
"'Цитирований' INTEGER",
"'В настоящее время' TEXT",
"'Доступный архив' TEXT",
"'Реферативный' TEXT",
"'Мультидисциплинарный' TEXT",
"'Описание журнала' TEXT",
"'Редакционная коллегия' TEXT",
"'Aims & Scope' TEXT",
94
"created_at TEXT"
])
journals/parser/erihplus.py
#!/usr/bin/env python2
# encoding: utf-8
import re
from journals.parser.util import make_request
def include(issn_print, issn_online):
return issn_check(issn_print) or issn_check(issn_online)
or None
def issn_check(issn):
''' Проверка наличия issn журнала в базе erihplus '''
if not issn:
return 0
url =
'https://dbh.nsd.uib.no/publiseringskanaler/erihplus/search.ac
tion?sok.discipline=1&treffliste.tidsskriftTreffside=1&treffliste.vis=true&enkeltS
ok=%s' % issn
html = make_request(url)
m = re.search('The search returned (\d+) hits', html)
return (m.group(1) if m else 0)
journals/parser/maik.py
#!/usr/bin/env python2
# encoding: utf-8
import re
from bs4 import BeautifulSoup
from journals.parser import database
from journals.parser.util import make_request,
already_exists_notify, save_notify
foreign =
'A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z'
95
russian = 'a,b,v,g,d,zh,z,i,k,l,m,n,o,p,r,s,t,u,f,kh,ch,e,ya'
def save_all_journals():
''' Получение и сохранение всех журналов в бд '''
print(('*' * 20) + ' maik.ru ' + ('*' * 20))
result = []
# проходим по всем буквам из обоих алфавитов
for char in foreign.split(',') + russian.split(','):
result += _get_journals(char)
total = len(result)
print(u'Найдено %d журналов' % total)
for i, data in enumerate(result):
prefix = '[%d/%d] (maik)' % (i + 1, total)
if database.id_exists('maik', data['id']):
already_exists_notify(prefix, data['title'])
else:
save_notify(prefix, data['title'])
database.insert('maik', data)
def find(issn_print, issn_online):
id = database.find_in_table('maik', 'issn_print',
issn_print)
if not id:
id = database.find_in_table('maik', 'issn_online',
issn_online)
if id:
return database.select('maik', id)
def _get_journals(char):
''' Получение данных по всем журналам, начинающимся на
заданную букву '''
print(u'Получение журналов из базы maik на букву "%s"...'
% char)
url = 'http://maik.ru/ru/journals/catalog/alphabet/%s' %
char
96
html = make_request(url)
if html:
soup = BeautifulSoup(html, 'html.parser')
result = []
divs = soup.find_all('div', class_="book_item")
for div in divs:
id = div.find('a', class_='btn-standart')
['href'].split('/')[-2]
title = div.find('div',
class_='book_item_text').b.text
m = re.search('ISSN PRINT:\s+(\w+-\w+)', div.text)
issn_print = m.group(1) if m else None
m = re.search('ISSN ONLINE:\s+(\w+-\w+)',
div.text)
issn_online = m.group(1) if m else None
impact_div = div.find('div', class_="impact")
impact_factor = None
if impact_div:
impact_factor = float(impact_div.span.text)
result.append({
'id': id,
'title': title,
'impact_factor_jcr': impact_factor,
'issn_print': issn_print,
'issn_online': issn_online,
})
print('
%s' % title)
return result
else:
return []
database.create_table('maik', [
'id TEXT UNIQUE',
'title TEXT',
'impact_factor_jcr REAL',
97
'issn_print TEXT',
'issn_online TEXT',
])
journals/parser/perechen_vak.py
#!/usr/bin/env python2
# encoding: utf-8
import re
from bs4 import BeautifulSoup
from journals.parser import database
from journals.parser.util import *
def save_all_journals():
''' Получение и сохранение всех журналов в бд '''
print(('*' * 20) + ' perechen.vak2.ed.gov.ru ' + ('*' *
20))
with_specialties = _get_vak_journals_with_specialities()
with_foreign_db = _get_vak_journals_with_foreign_db()
journals = with_specialties + with_foreign_db
total = len(journals)
print(u'Найдено %d журналов' % total)
for i, journal in enumerate(journals):
prefix = '[%d/%d] (vak)' % (i + 1, total)
if database.id_exists('perechen_vak', journal['id']):
already_exists_notify(prefix, journal['title'])
else:
save_notify(prefix, journal['title'])
database.insert('perechen_vak', journal)
def find(issn_print, issn_online):
id = database.find_in_table('perechen_vak', 'issn',
issn_print)
if not id:
id = database.find_in_table('perechen_vak', 'issn',
issn_online)
98
if id:
return database.select('perechen_vak', id)
def _get_vak_journals_with_specialities():
''' Получение и обработка всех журналов со специальностями
'''
print(u'Получаем содержимое перечня ВАК...')
html = make_request('http://perechen.vak2.ed.gov.ru/')
if html:
soup = BeautifulSoup(html, 'html.parser')
table = soup.find(id='datatable').find('tbody')
rows = table.find_all('tr')
result = []
for row in rows:
data = {}
columns = row.find_all('td')
data['id'] = int(columns[5].text)
data['title'] = columns[0].text.strip()
data['issn'] = _extract_issn(columns[1].text)
branches = [s.text.strip() for s in
columns[2].find_all('p')]
specialties = [s.text.strip() for s in
columns[3].find_all('p')]
data['branches'] = ';'.join(branches) or None
data['specialties'] = ';'.join(specialties) or
None
data['inclusion_date'] = columns[4].text.strip()
result.append(data)
return result
def _get_vak_journals_with_foreign_db():
''' Получение и обработка всех журналов с информацией о
вхождении в международные бд '''
print(u'Получаем информацию по вхождению в международные
базы данных...')
html =
make_request('http://perechen.vak2.ed.gov.ru/dblist')
99
if html:
soup = BeautifulSoup(html, 'html.parser')
table = soup.find(id='datatable').find('tbody')
rows = table.find_all('tr')
result = []
for row in rows:
columns = row.find_all('td')
data = {}
data['id'] = int(columns[4].text)
data['title'] = columns[0].text.strip()
data['issn'] = _extract_issn(columns[1].text)
branches = [s.text.strip() for s in
columns[2].find_all('p')]
foreign_db = [s.text.strip() for s in
columns[3].find_all('p')]
data['branches'] = ';'.join(branches) or None
if data['branches']:
print(u'Получение информации о специальностях
для журнала "%s"' % data['title'])
data['specialties'] =
_get_specialties(data['id'])
data['foreign_db'] = ';'.join(foreign_db) or None
result.append(data)
return result
def _get_specialties(journal_id):
html =
make_request('http://perechen.vak2.ed.gov.ru/edition_view/%d'
% journal_id)
if html:
soup = BeautifulSoup(html, 'html.parser')
tr = soup.find(class_='table').find_all('tr')[-1]
text = tr.find_all('td')[-1].text
values = [s.strip() for s in text.split('\n')]
specialties = ';'.join(filter(None, values))
return specialties
100
def _extract_issn(string):
''' Извлечение ISSN из строки '''
# пример: '1234-123X (online), print: 4567-456' => '1234123X, 4567-456'
issn = [m.group(1) for m in re.finditer('([\dX]+-[\dX]+)',
string)]
return ', '.join(issn) or None
database.create_table('perechen_vak', [
'id INTEGER UNIQUE',
'title TEXT',
'issn TEXT',
'branches TEXT',
'specialties TEXT',
'foreign_db TEXT',
'inclusion_date TEXT',
])
journals/parser/springer.py
#!/usr/bin/env python2
# encoding: utf-8
import re
from journals.parser import database
from journals.parser.util import *
def save_all_journals():
''' Получение и сохранение всех журналов в бд '''
print(('*' * 20) + ' springer.com ' + ('*' * 20))
ids = _get_all_journals_ids()
total = len(ids)
print(u'Найдено %d журналов' % total)
for i, id in enumerate(ids):
prefix = '[%d/%d] (springer)' % (i + 1, total)
if database.id_exists('springer', id):
already_exists_notify(prefix, 'id %d' % id)
else:
101
data = _get_journal(id)
if data:
save_notify(prefix, data['title'])
database.insert('springer', data)
else:
get_error_notify(prefix, id)
def find(issn_print, issn_online):
id = database.find_in_table('springer', 'issn_print',
issn_print)
if not id:
id = database.find_in_table('springer', 'issn_online',
issn_online)
if id:
return database.select('springer', id)
def _get_all_journals_ids():
''' Последовательно запрашиваем все страницы и сохраняем
id журналов '''
csv = make_request('http://link.springer.com/search/csv?
facet-content-type=%22Journal%22')
rows = map(lambda x: x.split(','), csv.split('\n'))[1:]
ids = []
for row in rows:
url = row[8].replace('"', '')
if url:
id = int(url.split('/')[-1])
ids.append(id)
return sorted(ids)
def _get_journal(id):
''' Получение данных журнала по заданному id '''
if not id:
return
url = 'http://link.springer.com/journal/%d' % id
html = make_request(url)
102
if html:
title = re.search('<h1 id="title">(.+)</h1>',
html).group(1)
m = re.search('Impact Factor</span>\n.*<span>(.
+)</span>', html, re.MULTILINE)
impact_factor = float(m.group(1)) if m else None
m = re.search('<span class="pissn">([\dX]+-[\dX]+)',
html)
issn_print = m.group(1) if m else None
m = re.search('<span class="eissn">([\dX]+-[\dX]+)',
html)
issn_online = m.group(1) if m else None
return {
'id': id,
'title': title.decode('utf-8'),
'impact_factor_jcr': impact_factor,
'issn_print': issn_print,
'issn_online': issn_online
}
database.create_table('springer', [
'id INTEGER UNIQUE',
'title TEXT',
'impact_factor_jcr REAL',
'issn_print TEXT',
'issn_online TEXT',
])
journals/parser/save.py
#!/usr/bin/env python2
# encoding: utf-8
from journals.parser import util
from journals.parser import database
from journals.parser import elibrary
from journals.parser import maik
from journals.parser import springer
from journals.parser import perechen_vak
103
from journals.parser import erihplus
def to_sqlite():
elibrary.save_all_journals()
maik.save_all_journals()
perechen_vak.save_all_journals()
springer.save_all_journals()
database.create_table('journals', [
'id INTEGER UNIQUE',
'title TEXT',
'description TEXT',
'publisher TEXT',
'issn_print TEXT',
'issn_online TEXT',
'impact_factor_jcr REAL',
'impact_factor_rinc REAL',
'branches TEXT',
'specialties TEXT',
'foreign_db TEXT',
'journal_url TEXT',
'elibrary_url TEXT',
'maik_url TEXT',
'springer_url TEXT',
'reviewed BOOLEAN',
'in_vak BOOLEAN',
'in_rinc BOOLEAN',
'in_isi BOOLEAN',
'in_scopus BOOLEAN',
'in_humanities BOOLEAN',
])
print(u'Обработка полученных данных...')
journals = database.select_all('elibrary')
# сохранение данных, полученных из всех баз в одну таблицу
total = len(journals)
for i, j in enumerate(journals):
prefix = '[%d/%d] (journals)' % (i + 1, total)
104
if database.id_exists('journals', j['id']):
util.already_exists_notify(prefix, j.get('Полное
название'))
else:
issn_print = j.get('ISSN печатной версии')
issn_online = j.get('ISSN онлайновой версии')
impact_factor_jcr = None
data = {
'id': j['id'],
'title': j.get('Полное название'),
'description': j.get('Описание журнала'),
'publisher': j.get('Издательство'),
'issn_print': issn_print,
'issn_online': issn_online,
'reviewed': j.get('Рецензируемый'),
'in_vak': j.get('Перечень ВАК'),
'in_rinc': j.get('РИНЦ'),
'in_isi': j.get('ISI'),
'in_scopus': j.get('SCOPUS'),
'impact_factor_rinc': j.get('Импакт-фактор
РИНЦ 2013'),
'journal_url': j.get('WWW-адрес'),
}
data['elibrary_url'] =
'http://elibrary.ru/title_about.asp?id=%s' % j['id']
data['in_humanities'] =
erihplus.include(issn_print, issn_online)
# проверяем, входит ли журнал в базу springer
springer_journal = springer.find(issn_print,
issn_online)
if springer_journal:
data['springer_url'] =
'http://link.springer.com/journal/%d' % springer_journal['id']
impact_factor_jcr =
springer_journal['impact_factor_jcr']
# проверяем, входит ли журнал в базу maik
maik_journal = maik.find(issn_print, issn_online)
105
if maik_journal:
data['maik_url'] =
'http://maik.ru/ru/journal/acoust/%s' % maik_journal['id']
impact_factor_jcr =
maik_journal['impact_factor_jcr']
# проверяем, входит ли журнал в перечень ВАК
vak_journal = perechen_vak.find(issn_print,
issn_online)
if vak_journal:
data['branches'] = vak_journal['branches']
data['specialties'] =
vak_journal['specialties']
data['foreign_db'] = vak_journal['foreign_db']
data['in_vak'] = 1
data['impact_factor_jcr'] = impact_factor_jcr
util.save_notify(prefix, data['title'])
database.insert('journals', data)
print(u'Успех!')
journals/parser/util.py
# encoding: utf-8
import time
import requests
def make_request(url, timeout=1):
''' Универсальный метод для запросов, возвращает тело
ответа '''
time.sleep(timeout)
try:
r = requests.get(url)
except Exception as e:
print('Не удалось получить данные по адресу "%s"\n%s'
%
(url.encode('utf-8'), e))
return
106
if r.status_code >= 400:
print('Запрос по адресу "%s" завершился с кодом ошибки
%s' %
(url.encode('utf-8'), r.status_code))
return
else:
return r.text.encode('utf-8')
def already_exists_notify(prefix, title):
print(u'%s Уже есть в базе: %s' % (prefix, title))
def save_notify(prefix, title):
print(u'%s Сохранение: %s' % (prefix, title))
def get_error_notify(prefix, title):
print(u'%s Ошибка при получении данных: %s' % (prefix,
title))
Клиентская часть
Шаблоны
templates/journals/base.html
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
{# блок с заголовком страницы #}
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet"
href="/static/css/journals/semantic.min.css">
<script src="/static/js/jquery.min.js"></script>
<script src="/static/js/journals/semantic.min.js"
type="text/javascript"></script>
<script src="/static/js/journals/popup.js"
type="text/javascript"></script>
<style type="text/css" media="all">
{# меняем курсор при наведении на ячейку с классом
journal_popup #}
107
.journal_popup {
cursor: pointer;
}
</style>
{# блок для подключения дополнительных стилей и скриптов
#}
{% block head_includes %}{% endblock %}
</head>
<body>
{# блок с основным содержимым #}
{% block content %}{% endblock %}
</body>
</html>
templates/journals/collection_edit.html
{% extends "journals/base.html" %}
{% block title %}
Редактирование "{{ element.name }}"
{% endblock %}
{% block content %}
<div class="ui container">
<div class="ui text menu">
<a class="item" href="{% url 'journals' %}">Список
журналов</a>
<a class="item" href="{% url 'branches' %}">Отрасли
наук</a>
<a class="item" href="{% url 'specialties'
%}">Специальности</a>
<a class="item" href="{% url 'foreign_dbs'
%}">Международные базы</a>
</div>
<h2 class="ui header">Редактирование
"{{ element.name }}"</h2>
108
<form action="{% url edit_url element.id %}" method="post"
class="ui form">
{% csrf_token %}
{% for field in form %}
<div class="fields">
<div class="five wide field">
<label>{{ field.label_tag }}</label>
{{ field }}
</div>
</div>
{% endfor %}
<input class="ui positive button" type="submit"
value="Сохранить" />
</form>
{% endblock content %}
templates/journals/collection_index.html
{% extends "journals/base.html" %}
{% block title %}
{{ title }}
{% endblock %}
{% block content %}
<div class="ui container">
{# меню #}
<div class="ui text menu">
<a class="item" href="{% url 'journals' %}">Список
журналов</a>
{# в зависимости от значения переменной active_item #}
{# мы подсвечиваем (добавляем класс active) на элемент
меню #}
{% if active_item == 'branches' %}
<span class="active item">Отрасли науки</span>
{% else %}
<a class="item" href="{% url 'branches' %}">Отрасли
науки</a>
{% endif %}
109
{% if active_item == 'specialties' %}
<span class="active item">Специальности</span>
{% else %}
<a class="item" href="{% url 'specialties'
%}">Специальности</a>
{% endif %}
{% if active_item == 'foreign_dbs' %}
<span class="active item">Международные базы
данных</span>
{% else %}
<a class="item" href="{% url 'foreign_dbs'
%}">Международные базы данных</a>
{% endif %}
</div>
<h2 class="ui header">{{ title }}</h2>
<a class="ui black button" href="{% url new_url
%}">Добавить</a>
<table class="ui celled collapsing table">
<thead>
<tr>
<th>Название</th>
<th>Действие</th>
</tr>
</thead>
<tbody>
{% for element in collection %}
<tr>
<td>{{ element.name }}</td>
<td>
{# кнопка редактирования #}
<a href="{% url edit_url element.id %}"><i
class="pencil icon"></i></a>
{# кнопка удаления с подтверждением #}
<a href="{% url delete_url element.id %}"
onclick="return confirm('Вы уверены?') ? true : false;"><i
class="trash icon"></i></a>
110
</td>
</tr>
{% endfor %}
</tbody>
</table>
<br>
</div>
{% endblock %}
templates/journals/collection_new.html
{% extends "journals/base.html" %}
{% block title %}
{{ title }}
{% endblock %}
{% block content %}
<div class="ui container">
<div class="ui text menu">
<a class="item" href="{% url 'journals' %}">Список
журналов</a>
<a class="item" href="{% url 'branches' %}">Отрасли
наук</a>
<a class="item" href="{% url 'specialties'
%}">Специальности</a>
<a class="item" href="{% url 'foreign_dbs'
%}">Международные базы</a>
</div>
<h2 class="ui header">{{ title }}</h2>
<form action="{% url new_url %}" method="post" class="ui
form">
{% csrf_token %}
{% for field in form %}
<div class="fields">
<div class="five wide field">
<label>{{ field.label_tag }}</label>
{{ field }}
111
</div>
</div>
{% endfor %}
<input class="ui positive button" type="submit"
value="Создать" />
</form>
{% endblock content %}
templates/journals/ edit.html
{% extends "journals/base.html" %}
{% block title %}
Редактирование журнала "{{ journal.title }}"
{% endblock %}
{% block content %}
<div class="ui container">
<div class="ui text menu">
<a class="item" href="{% url 'journals' %}">Список
журналов</a>
<a class="item" href="{% url 'branches' %}">Отрасли
наук</a>
<a class="item" href="{% url 'specialties'
%}">Специальности</a>
<a class="item" href="{% url 'foreign_dbs'
%}">Международные базы</a>
</div>
<div class="ui secondary segment">
<h2 class="ui header">Редактирование журнала</h2>
{% if form.errors %}
<div class="ui error message">
<div class="header">
Обнаружены следующие ошибки:
</div>
<ul class="list">
{% for field in form %}
{% if field.errors %}
<div class="item">{{ field.label_tag }}
{{ field.errors }}</div>
112
{% endif %}
{% endfor %}
</ul>
</div>
{% endif %}
<form action="{% url 'edit_journal' journal.id %}"
method="post" class="ui form">
{% csrf_token %}
<div class="fields">
<div class="sixteen wide field">
<label>Название</label>
{{ form.title }}
</div>
</div>
<div class="fields">
<div class="sixteen wide field">
<label>Издательство</label>
{{ form.publisher }}
</div>
</div>
<div class="fields">
<div class="sixteen wide field">
<label>Описание</label>
{{ form.description }}
</div>
</div>
<div class="fields">
<div class="two wide field">
<label>ISSN print</label>
{{ form.issn_print }}
</div>
<div class="two wide field">
<label>ISSN online</label>
{{ form.issn_online }}
113
</div>
<div class="three wide field">
<label>Импакт фактор JCR</label>
{{ form.impact_factor_jcr }}
</div>
<div class="three wide field">
<label>Импакт фактор РИНЦ</label>
{{ form.impact_factor_rinc }}
</div>
<div class="two wide field">
<label>Внешний ID</label>
{{ form.outer_id }}
</div>
</div>
<div class="fields">
<div class="three wide field">
<div class="ui checkbox">
{{ form.reviewed }}
<label for="id_reviewed">Реценезируемый</label>
</div>
</div>
<div class="four wide field">
<div class="ui checkbox">
{{ form.in_vak }}
<label for="id_in_vak">Входит в перечень
ВАК</label>
</div>
</div>
<div class="three wide field">
<div class="ui checkbox">
{{ form.in_rinc }}
<label for="id_in_rinc">Входит в РИНЦ</label>
</div>
114
</div>
<div class="three wide field">
<div class="ui checkbox">
{{ form.in_isi }}
<label for="id_in_isi">Входит в ISI</label>
</div>
</div>
<div class="three wide field">
<div class="ui checkbox">
{{ form.in_scopus }}
<label for="id_in_scopus">Входит в SCOPUS</label>
</div>
</div>
<div class="three wide field">
<div class="ui checkbox">
{{ form.in_humanities }}
<label for="id_in_humanities">Входит в
humanities</label>
</div>
</div>
</div>
<div class="fields">
<div class="sixteen wide field">
<label>Ссылка на сайт журнала</label>
{{ form.journal_url }}
</div>
</div>
<div class="fields">
<div class="sixteen wide field">
<label>Ссылка на журнал в elibrary</label>
{{ form.elibrary_url }}
</div>
</div>
115
<div class="fields">
<div class="sixteen wide field">
<label>Ссылка на журнал в maik</label>
{{ form.maik_url }}
</div>
</div>
<div class="fields">
<div class="sixteen wide field">
<label>Ссылка на журнал в springer</label>
{{ form.springer_url }}
</div>
</div>
<div class="fields">
<div class="seven wide field">
<label>Отрасли наук</label>
{{ form.branches }}
</div>
</div>
<div class="fields">
<div class="seven wide field">
<label>Специальности</label>
{{ form.specialties }}
</div>
</div>
<div class="fields">
<div class="seven wide field">
<label>Международные базы данных</label>
{{ form.foreign_dbs }}
</div>
</div>
<input class="ui positive button" type="submit"
value="Сохранить">
</form>
</div>
<br>
116
</div>
{% endblock %}
templates/journals/ index.html
{% extends "journals/base.html" %}
{% block title %}
Список журналов
{% endblock %}
{% block head_includes %}
{# фиксируем ширину всех полей типа number (Импакт фактор
РИНЦ, Импакт фактор JCR) #}
<style type="text/css" media="screen">
input[type=number] {
width: 70px !important;
}
</style>
{% endblock
%}
{% block content %}
<div class="ui container">
<div class="ui text menu">
<span class="active item">Список журналов</span>
<a class="item" href="{% url 'branches' %}">Отрасли
наук</a>
<a class="item" href="{% url 'specialties'
%}">Специальности</a>
<a class="item" href="{% url 'foreign_dbs'
%}">Международные базы данных</a>
</div>
<div class="ui secondary segment">
<h2 class="ui header">Поиск</h2>
{# форма поиска #}
{# каждое поле у формы поиска мы размещаем вручную #}
{# чтобы можно было настроить его ширину и положение #}
<form action="{% url 'journals' %}" class="ui form">
117
<div class="fields">
<div class="three wide field">
<label>Название</label>
{{ search_form.title__icontains }}
</div>
<div class="three wide field">
<label>Описание</label>
{{ search_form.description__icontains }}
</div>
<div class="three wide field">
<label>Издатель</label>
{{ search_form.publisher__icontains }}
</div>
<div class="two wide field">
<label>ISSN print</label>
{{ search_form.issn_print__exact }}
</div>
<div class="two wide field">
<label>ISSN online</label>
{{ search_form.issn_online__exact }}
</div>
</div>
<div class="fields">
<div class="three wide field">
<label>Рецензируемый</label>
{{ search_form.reviewed__exact }}
</div>
<div class="three wide field">
<label>Входит в перечень ВАК</label>
{{ search_form.in_vak__exact }}
</div>
<div class="three wide field">
118
<label>Входит в РИНЦ</label>
{{ search_form.in_rinc__exact }}
</div>
<div class="three wide field">
<label>Входит в ISI</label>
{{ search_form.in_isi__exact }}
</div>
<div class="three wide field">
<label>Входит в SCOPUS</label>
{{ search_form.in_scopus__exact }}
</div>
<div class="three wide field">
<label>Входит в humanities</label>
{{ search_form.in_humanities__exact }}
</div>
</div>
<div class="inline fields">
<div class="field">
{{ search_form.impact_factor_jcr__lt }}
<label>&lt; импакт фактор JCR &lt;</label>
{{ search_form.impact_factor_jcr__gt }}
</div>
<div class="field">
{{ search_form.impact_factor_rinc__lt }}
<label>&lt; импакт фактор РИНЦ &lt;</label>
{{ search_form.impact_factor_rinc__gt }}
</div>
</div>
<div class="fields">
<div class="five wide field">
<label>Отрасль науки</label>
{{ search_form.branches__id }}
</div>
<div class="five wide field">
119
<label>Специальность</label>
{{ search_form.specialties__id }}
</div>
<div class="five wide field">
<label>Международная база данных</label>
{{ search_form.foreign_dbs__id }}
</div>
</div>
<input class="ui primary button" type="submit"
value="Найти">
{# если были переданы какие-то параметры через форму
поиска, #}
{# то отображаем кнопку сброса этих параметров #}
{% if url_params %}
<a class="ui button" href="{% url 'journals'
%}">Сброс</a>
{% endif %}
<a class="ui right floated black button" href="{% url
'new_journal' %}">Добавить журнал</a>
</form>
</div>
</div>
<br>
{# верхняя пагинация #}
<div class="ui grid">
<div class="column centered row">
<div class="ui pagination menu">
{% if journals.has_previous %}
<a class="icon item" href="?
page={{ journals.previous_page_number }}&{{ url_params }}">
<i class="left chevron icon"></i>
</a>
{% endif %}
{% for n in journals.paginator.page_range %}
{% if n == journals.number %}
120
<span class="active item">{{ n }}</span>
{% else %}
<a class="item" href="?page={{ n }}
{{ url_params }}">{{ n }}</a>
{% endif %}
{% endfor %}
{% if journals.has_next %}
<a class="icon item" href="?
page={{ journals.next_page_number }}&{{ url_params }}">
<i class="right chevron icon"></i>
</a>
{% endif %}
</div>
</div>
</div>
{# таблица с журналами #}
<table class="ui selectable celled table">
<thead>
<tr>
<th>Название</th>
<th>Описание</th>
<th>Издательство</th>
<th>ISSN</th>
<th>Импакт фактор</th>
<th>Добавлен</th>
<th>Действие</th>
</tr>
</thead>
<tbody>
{% for journal in journals %}
{# сохраняем информацию о журнале в data-атрибутах строки
таблицы #}
{# эти атрибуты будут использоваться при открытии
всплывающего окна с информацией о журнале #}
{# static/js/journals/popup.js #}
{# (пользователю эти атрибуты будут не видны) #}
<tr
121
{% for field, value in journal.as_dict.items %}
data-{{ field }}="{{ value }}"
{% endfor %}
>
<td class="journal_popup">{{ journal.title }}</td>
{# обрезаем поля "описание" и "издательство" до 30
символов, чтобы сэкономить место в таблице #}
{# добавляем полную версию поля в title (отображается
при наведении на ячейку) #}
<td class="journal_popup"
title="{{ journal.description }}">
{{ journal.description | default_if_none:'' |
truncatechars:30 }}
</td>
<td class="journal_popup"
title="{{ journal.publisher }}">{{ journal.publisher |
truncatechars:30 }}</td>
<td class="journal_popup">
{{ journal.issn_print | default_if_none:''}}
{{ journal.issn_online | default_if_none:''
}}
</td>
<td class="journal_popup">
{{ journal.impact_factor_jcr | default_if_none:''}}
{{ journal.impact_factor_rinc | default_if_none:''}}
</td>
<td class="journal_popup">{{ journal.created_at |
date:'d.m.Y' }}</td>
<td>
{# кнопка редактирования #}
<a href="{% url 'edit_journal' journal.id %}"><i
class="pencil icon"></i></a>
{# кнопка удаления с подтверждением #}
<a href="{% url 'delete_journal' journal.id %}"
onclick="return confirm('Вы уверены?') ? true : false;"><i
class="trash icon"></i></a>
</td>
</tr>
{% endfor %}
122
</tbody>
{# в футере таблицы отображаем информаци о количестве
найденных журналов #}
<tfoot>
<tr>
<th colspan="7">
<div class="center aligned">
Всего найдено {{ journals.paginator.count }}
{{ plural }}
</div>
</th>
</tr>
</tfoot>
</table>
{# нижняя пагинация #}
<div class="ui grid">
<div class="column centered row">
<div class="ui pagination menu">
{% if journals.has_previous %}
<a class="icon item" href="?
page={{ journals.previous_page_number }}&{{ url_params }}">
<i class="left chevron icon"></i>
</a>
{% endif %}
{% for n in journals.paginator.page_range %}
{% if n == journals.number %}
<span class="active item">{{ n }}</span>
{% else %}
<a class="item" href="?page={{ n }}&{{ url_params }}">{{
n }}</a>
{% endif %}
{% endfor %}
{% if journals.has_next %}
<a class="icon item" href="?
page={{ journals.next_page_number }}&{{ url_params }}">
<i class="right chevron icon"></i>
</a>
{% endif %}
123
</div>
</div>
</div>
{# шаблон для всплывающего окна #}
{# используется в static/js/journals/popup.js #}
<div class="ui modal" id="journal_popup">
<div class="content">
<p>
<strong>Название:</strong>
<span id="journal_title"></span>
</p>
<p>
<strong>Описание:</strong>
<span id="journal_description"></span>
</p>
<p>
<strong>Издательство:</strong>
<span id="journal_publisher"></span>
</p>
<p>
<strong>ISSN печатной версии:</strong>
<span id="journal_issn_print"></span>
</p>
<p>
<strong>ISSN онлайновой версии:</strong>
<span id="journal_issn_online"></span>
</p>
<p>
<strong>Рецензируемый:</strong>
<span id="journal_reviewed"></span>
</p>
<p>
<strong>Сайт журнала:</strong>
124
<span id="journal_journal_url"></span>
</p>
<p>
<strong>Elibrary:</strong>
<span id="journal_elibrary_url"></span>
</p>
<p>
<strong>Maik:</strong>
<span id="journal_maik_url"></span>
</p>
<p>
<strong>Springer:</strong>
<span id="journal_springer_url"></span>
</p>
<p>
<strong>Входит в перечень ВАК:</strong>
<span id="journal_in_vak"></span>
</p>
<p>
<strong>Входит в РИНЦ:</strong>
<span id="journal_in_rinc"></span>
</p>
<p>
<strong>Входит в ISI:</strong>
<span id="journal_in_isi"></span>
</p>
<p>
<strong>Входит в SCOPUS:</strong>
<span id="journal_in_scopus"></span>
</p>
<p>
125
<strong>Входит в humanities:</strong>
<span id="journal_in_humanities"></span>
</p>
<p>
<strong>Отрасли наук:</strong>
<span id="journal_branches"></span>
</p>
<p>
<strong>Специальности:</strong>
<span id="journal_specialties"></span>
</p>
<p>
<strong>Международные базы данных:</strong>
<span id="journal_foreign_dbs"></span>
</p>
<p>
<strong>Дата добавления:</strong>
<span id="journal_created_at"></span>
</p>
</div>
</div>
{% endblock %}
templates/journals/ new.html
{% extends "journals/base.html" %}
{% block title %}
Создание нового журнала
{% endblock %}
{% block content %}
<div class="ui container">
<div class="ui text menu">
<a class="item" href="{% url 'journals' %}">Список
126
журналов</a>
<a class="item" href="{% url 'branches' %}">Отрасли
наук</a>
<a class="item" href="{% url 'specialties'
%}">Специальности</a>
<a class="item" href="{% url 'foreign_dbs'
%}">Международные базы</a>
</div>
<div class="ui secondary segment">
<h2 class="ui header">Создание нового журнала</h2>
{% if form.errors %}
<div class="ui error message">
<div class="header">
Обнаружены следующие ошибки:
</div>
<ul class="list">
{% for field in form %}
{% if field.errors %}
<div class="item">{{ field.label_tag }}
{{ field.errors }}</div>
{% endif %}
{% endfor %}
</ul>
</div>
{% endif %}
<form action="{% url 'new_journal' %}" method="post"
class="ui form">
{% csrf_token %}
<div class="fields">
<div class="sixteen wide field">
<label>Название</label>
{{ form.title }}
</div>
</div>
<div class="fields">
<div class="sixteen wide field">
<label>Издательство</label>
127
{{ form.publisher }}
</div>
</div>
<div class="fields">
<div class="sixteen wide field">
<label>Описание</label>
{{ form.description }}
</div>
</div>
<div class="fields">
<div class="two wide field">
<label>ISSN print</label>
{{ form.issn_print }}
</div>
<div class="two wide field">
<label>ISSN online</label>
{{ form.issn_online }}
</div>
<div class="three wide field">
<label>Импакт фактор JCR</label>
{{ form.impact_factor_jcr }}
</div>
<div class="three wide field">
<label>Импакт фактор РИНЦ</label>
{{ form.impact_factor_rinc }}
</div>
<div class="two wide field">
<label>Внешний ID</label>
{{ form.outer_id }}
</div>
</div>
<div class="fields">
128
<div class="three wide field">
<div class="ui checkbox">
{{ form.reviewed }}
<label for="id_reviewed">Реценезируемый</label>
</div>
</div>
<div class="four wide field">
<div class="ui checkbox">
{{ form.in_vak }}
<label for="id_in_vak">Входит в перечень
ВАК</label>
</div>
</div>
<div class="three wide field">
<div class="ui checkbox">
{{ form.in_rinc }}
<label for="id_in_rinc">Входит в РИНЦ</label>
</div>
</div>
<div class="three wide field">
<div class="ui checkbox">
{{ form.in_isi }}
<label for="id_in_isi">Входит в ISI</label>
</div>
</div>
<div class="three wide field">
<div class="ui checkbox">
{{ form.in_scopus }}
<label for="id_in_scopus">Входит в SCOPUS</label>
</div>
</div>
<div class="three wide field">
<div class="ui checkbox">
{{ form.in_humanities }}
129
<label for="id_in_humanities">Входит в
humanities</label>
</div>
</div>
</div>
<div class="fields">
<div class="sixteen wide field">
<label>Ссылка на сайт журнала</label>
{{ form.journal_url }}
</div>
</div>
<div class="fields">
<div class="sixteen wide field">
<label>Ссылка на журнал в elibrary</label>
{{ form.elibrary_url }}
</div>
</div>
<div class="fields">
<div class="sixteen wide field">
<label>Ссылка на журнал в maik</label>
{{ form.maik_url }}
</div>
</div>
<div class="fields">
<div class="sixteen wide field">
<label>Ссылка на журнал в springer</label>
{{ form.springer_url }}
</div>
</div>
<div class="fields">
<div class="seven wide field">
<label>Отрасли наук</label>
{{ form.branches }}
</div>
130
</div>
<div class="fields">
<div class="seven wide field">
<label>Специальности</label>
{{ form.specialties }}
</div>
</div>
<div class="fields">
<div class="seven wide field">
<label>Международные базы данных</label>
{{ form.foreign_dbs }}
</div>
</div>
<input class="ui positive button" type="submit"
value="Создать">
</form>
</div>
<br>
</div>
{% endblock %}
Cкрипты
static/js/journals/popup.js
$(function() {
// при клике на элемент с классом journal_popup
// конструируем и отображаем всплывающее окно
// шаблон, который используется при генерации этого окна,
// находится тут: templates/journals/index.html
// (элемент с id="journal_popup", по умолчанию он скрыт)
$('.journal_popup').on('click', function() {
// получаем элмент <tr>, в котором хранятся
// все данные о журнале в виде data-атрибутов
var $tr = $(this).closest('tr');
// список параметров, которые нужно отобразить как текст
var fields = [
'title',
'description',
131
'publisher',
'issn_print',
'issn_online',
'reviewed',
'in_vak',
'in_rinc',
'in_isi',
'in_scopus',
'in_humanities',
'branches',
'specialties',
'foreign_dbs',
'created_at'
];
// список параметров, которые нужно отобразить как ссылки
var fields_with_url = [
'journal_url',
'elibrary_url',
'maik_url',
'springer_url'
];
// функция для перевода питоновских значений в
человеческий формат
function humanValue(value) {
switch (value) {
case '':
return 'Отсутствуют';
case 'None':
return 'Отсутствует';
case 'True':
return 'Да';
case 'False':
return 'Нет';
default:
return value;
}
}
132
// заполняем текстовые параметры внутри шаблона
fields.forEach(function(field) {
$('#journal_' +
field).text(humanValue($tr.data(field)));
});
// заполняем параметры-ссылки
fields_with_url.forEach(function(field) {
// очищаем элемент, если там что-то есть
$('#journal_' + field).empty();
var value = humanValue($tr.data(field));
// если ссылки нет, то добавляем текст "Отсутствует"
if (value == 'Отсутствует') {
$('#journal_' + field).text('Отсутствует');
// ссылка есть
} else {
// создаём новый элемент <a></a> для её отображения
var $a = $('<a></a>');
$a.attr('href', value);
$a.attr('_target', 'blank');
$a.text(value);
// добавляем ссылку
$('#journal_' + field).append($a);
}
});
// шаблон готов, все данные на месте
// отображаем всплывающее окно
$('#journal_popup').modal('show');
});
});
133
134
1/--страниц
Пожаловаться на содержимое документа