Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

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


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

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

Легко, начальный \b не позволяет нам "сопоставить" "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 суффикс должен состоять из строки символов любой длины, выбранной регистранте. Каждый суффикс должен быть уникальным для префиксного элемента, который предшествует этому. Уникальный суффикс может быть порядковым номером, или он может включить идентификатор, сгенерированный из или на другой системе.

Теперь, когда он становится более сложным, из всех обработанных документов DOI я видел следующие символы (помимо [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:]], который включает символы, легко доступные в свободном тексте или любом языке разметки: "'&<> среди других.

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

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

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

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

Это длинный 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';

И voilá, вот демонстрация.

Ответ 2

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

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

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

Ответ 3

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

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

Это соответствует: "10-точечный номер слэш-символ-не-пробел"

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

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

Я все еще проверяю их, но до сих пор я надеюсь.

Ответ 4

Вот мой ход:

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

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

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

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

Ответ 5

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

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

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

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

Ответ 6

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

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

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

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

и

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

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

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