Сведения о вопросе

Faridun

02:36, 20th August, 2020

Теги

regex   doi    

Поиск DOI в документе или странице

Просмотров: 555   Ответов: 7

Система DOI в принципе не накладывает никаких полезных ограничений на то, что представляет собой разумный идентификатор . Однако, будучи в состоянии вытащить DOIs из PDFs, веб-страниц и т. д. весьма полезна для цитирования информация и т.д.

Существует ли надежный способ определить DOI в блоке текста, не предполагая префикс ' doi:'? (любой приемлемый язык, предпочтительные регексы и предотвращение ложных срабатываний обязательно)



  Сведения об ответе

repe

12:29, 28th August, 2020

Хорошо, в настоящее время я извлекаю тысячи DOIs из текста свободной формы (XML), и я понял, что мой предыдущий подход имел несколько проблем, а именно в отношении кодированных сущностей и пунктуации trail, поэтому я продолжал читать спецификацию , и это лучшее, что я мог предложить.


Префикс DOI должен состоять из Указателя каталога, за которым следует код владельца регистрации. Эти два компонента должны быть разделены полным стоп (точка).

Показатель каталога должен быть равен "10". Индикатор каталога различает весь набор символьных строк (префикс и суффикс) как цифровые идентификаторы объектов в системе разрешения.

Достаточно просто, начальный \b предотвращает нас от "matching" a "DOI", который не начинается с 10. :

$pattern = '\b(10[.]';

Вторым элементом префикса DOI должен быть код владельца регистрации. То код владельца регистрации - это уникальная строка, назначенная владельцу регистрации.

Кроме того, все присвоенные регистранту коды являются цифровыми и имеют длину не менее 4 цифр, поэтому:

$pattern = '\b(10[.][0-9]{4,}';

Код владельца регистрации может быть дополнительно разделен на подэлементы для административное удобство при желании. Каждый подэлемент системы код владельца регистрации должен предшествовать полной остановке.

$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*';

Синтаксис DOI должен состоять из префикса DOI и суффикса DOI разделенные прямой косой чертой.

Однако это не является абсолютно необходимым, раздел 2.2.3 утверждает, что необычные суффиксальные системы могут использовать другие соглашения (например, 10.1000.123456 вместо 10.1000/123456), но позволяет сократить некоторые пробелы.

$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/';

Имя DOI не чувствительно к регистру и может включать любую печатную версию символы из юридических графических символов Юникода. В DOI суффикс должен состоять из символьной строки любой длины, выбранной пользователем. регистрант. Каждый суффикс должен быть уникальным для префиксного элемента, который предшествовать ему. Уникальным суффиксом может быть порядковый номер, а может и наоборот включить идентификатор, созданный из другой системы или основанный на ней.

Теперь это становится сложнее, из всех DOIs, которые я обработал, я увидел следующие символы (кроме [0-9a-zA-Z] , конечно) в их суффиксах : .-()/:- -так что, хотя он и не существует, DOI 10.1016.12.31/nature.S0735-1097(98)2000/12/31/34:7-7 вполне правдоподобен.

Логическим выбором было бы использовать класс \S или [[:graph:]] PCRE POSIX, поэтому давайте сделаем это:

$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/\S+'; // or
$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/[[:graph:]]+';

Теперь у нас есть сложная проблема, класс [[:graph:]] -это супер-набор класса [[:punct:]] , который включает символы, легко найденные в свободном тексте или любом языке markup: "'&<> среди других.

Давайте просто фильтровать markup сейчас, используя отрицательный просмотр вперед:

$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/(?:(?!["&\'<>])\S)+'; // or
$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/(?:(?!["&\'<>])[[:graph:]])+';

Вышесказанное должно охватывать закодированные сущности ( & ), кавычки атрибутов ( ["'] ) и теги открытия / закрытия ([<>] ).

В отличие от markup языков, в свободном тексте обычно не используются знаки препинания, если они не ограничены хотя бы одним пробелом или не помещены в конце предложения, например:

Это очень долго DOI: 10.1016.12.31/nature.S0735-1097(98)2000/12/31/34:7-7 !!!

Решение здесь состоит в том, чтобы закрыть нашу группу захвата и утвердить другую границу слова:

$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/(?:(?!["&\'<>])\S)+)\b'; // or
$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/(?:(?!["&\'<>])[[:graph:]])+)\b';

И вуаля, вот вам демо-версия .


  Сведения об ответе

lourence

17:10, 5th August, 2020

@Silas проверка вменяемости-хорошая идея. Однако regex не покрывает все DOIs. Первый элемент должен (в настоящее время) быть be 10, а второй элемент должен (в настоящее время) быть числовым, но третий элемент практически не ограничен:

"Юридические символы - это юридические графические символы Юникода. Это специально исключает диапазоны управляющих символов 0x00-0x1F и 0x80-0x9F..."

и вот тут-то и кроется настоящая проблема. На практике я никогда не видел, чтобы whitespace использовался, но спецификация специально допускает это. В принципе, похоже, что нет разумного способа обнаружить конец DOI.


  Сведения об ответе

lourence

14:37, 22nd August, 2020

CrossRef имеет рекомендацию, что они успешно протестированы на 99.3% из DOIs:

/^10.\d{4,9}/[-._;()/:A-Z0-9]+$/i


  Сведения об ответе

JUST___

22:51, 19th August, 2020

Я уверен, что это не очень полезно для OP в данный момент, но я решил опубликовать то, что я пытаюсь, если кто-то еще, как я, наткнется на это:

(10.(\d)+/(\S)+)

Это соответствует: "10 точечный номер Слэш anything-not-whitespace"

Но для моего использования (выскабливание HTML) это было обнаружение ложных срабатываний, поэтому мне пришлось сопоставить вышеописанное, а также избавиться от кавычек и greater-than/less-than:

(10.(\d)+/([^(\s\>\"\<)])+)

Я все еще проверяю их, но до сих пор чувствую надежду.


  Сведения об ответе

SILA

01:53, 19th August, 2020

Вот мой ход на это:

(10[.][0-9]{4,}[^\s"/<>]*/[^\s"<>]+)

И несколько допустимых крайних случаев, когда это не терпит неудачи, но другие, похоже, делают это:

Кроме того, правильно отбрасывает некоторые ложные (X|HT)ML вещи, такие как:

  • <geo coords="10.4515260,51.1656910"></geo>


  Сведения об ответе

+-*/

04:39, 21st August, 2020

Это действительно старый и ответный вопрос, но вот еще одна потенциальная замена.

\b10\.(\d+\.*)+[\/](([^\s\.])+\.*)+\b

Это предполагает, что пробел не является частью DOI.

Я не проверял это на ложные срабатывания, но, похоже, он сможет найти все крайние случаи, упомянутые на этой странице.


  Сведения об ответе

dumai

10:47, 27th August, 2020

Следующий regex должен выполнить эту работу (синтаксис Perl regex):

/(10\.\d+\/\d+)/

Вы можете сделать некоторые дополнительные проверки вменяемости, открыв URL-адреса

http://hdl.handle.net/<doi>

и

http://dx.doi.org/<doi>

где находится кандидат doi,

и проверка того, что вы а) получаете статус 200 OK http, и Б) возвращенная страница не является страницей "DOI not found" для службы.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться