2008-08-26 23 views
40

El sistema DOI básicamente no tiene limitaciones útiles sobre lo que constituye a reasonable identifier. Sin embargo, ser capaz de extraer DOI de archivos PDF, páginas web, etc. es bastante útil para obtener información de citas, etc.Encontrar un DOI en un documento o página

¿Existe una manera confiable de identificar un DOI en un bloque de texto sin asumir el 'doi:' ¿prefijo? (Cualquier lenguaje aceptable, expresiones regulares prefiere, y evitar falsos positivos imprescindible)

Respuesta

47

Ok, actualmente estoy extrayendo miles de DOI de texto de forma libre (XML) y me di cuenta de que my previous approach tenía algunos problemas, a saber, con respecto a las entidades codificadas y la puntuación final, así que seguí leyendo the specification y esto es lo mejor que pude encontrar.


El prefijo DOI estarán compuestos de un indicador de directorio seguido por un código de registro. Estos dos componentes deben estar separados por una parada completa (punto).

El indicador de directorio debe ser "10". El indicador de directorio distingue el conjunto completo de cadenas de caracteres (prefijo y sufijo) como identificadores de objetos digitales dentro del sistema de resolución.

bastante fácil, la inicial \b nos impide "juego" a "DOI" que no se inicia con 10.:

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

El segundo elemento del prefijo DOI deben ser el código de registro. El código de registrador es una cadena única asignada a un registrante.

También, todo el código de registro asignado son numéricas, y al menos 4 dígitos de longitud, así que:

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

El código de registro se puede dividir en sub-elementos para administrativa conveniencia si lo desea Cada subelemento del código de registrador irá precedido por un punto.

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

La sintaxis DOI se compone de un prefijo y un sufijo DOI DOI separados por una barra inclinada.

Sin embargo, esto no es absolutamente necesario, la sección 2.2.3 establece que los sistemas de sufijos comunes pueden utilizar otras convenciones (como 10.1000.123456 en lugar de 10.1000/123456), pero deja cortar un poco de holgura.

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

El nombre DOI es sensible a las mayúsculas y puede incorporar cualquier caracteres imprimibles de los caracteres gráficos legales de Unicode. El sufijo DOI consistirá en una cadena de caracteres de cualquier longitud elegida por el registrante . Cada sufijo debe ser exclusivo del elemento de prefijo que lo precede . El sufijo único puede ser un número secuencial, o podría incorporar un identificador generado a partir de o basado en otro sistema.

Ahora bien, esto es donde se pone más complicado, de todo el DOI he procesado, vi los siguientes caracteres (además [0-9a-zA-Z] por supuesto) en sus sufijos: .-()/:- - por lo que, si bien no existe , el DOI 10.1016.12.31/nature.S0735-1097(98)2000/12/31/34:7-7 es completamente plausible.

La elección lógica sería utilizar \S o la clase [[:graph:]] PCRE POSIX, por lo que permite hacer eso:

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

Ahora tenemos un problema difícil, la clase [[:graph:]] es un super-conjunto de la clase [[:punct:]], que incluye caracteres que se encuentran fácilmente en texto libre o en cualquier lenguaje de marcado: "'&<> entre otros.

Permite sólo filtrar las marcado por ahora usando una búsqueda negativa hacia delante:

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

las entidades anteriores deben cubrir codificados (&), atribuir las citas (["']) y las etiquetas de apertura/cierre ([<>]) .

A diferencia de los lenguajes de marcas, texto libre por lo general no emplea caracteres de puntuación a menos que sean delimitado por al menos un espacio o colocado al final de una frase, por ejemplo:

Este es un largo DOI: 10.1016.12.31/nature.S0735-1097(98)2000/12/31/34:7-7!!!

Aquí la solución es cerrar nuestro grupo de captura y hacer valer otro límite de palabra:

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

Y voilá , here is a demo.

+3

No es el caso (o ya no es el caso) que todos los códigos de registrante asignados tengan al menos cuatro dígitos de longitud. Por ejemplo, 10.231 es el Journal of Investigative Medicine. Por ejemplo, 10.231/JIM.0b013e31820bab4c –

+1

@DavidConrad: ¡Gracias por la actualización hombre! –

+3

Wiley usa "<" and ">" en sus DOI. Por ejemplo, 10.1002/(SICI) 1522-2594 (199911) 42: 5 <952 :: AID-MRM16> 3.0.CO; 2-S es un DOI válido. Este DOI no es capturado por la expresión regular anterior. Una solución rápida es eliminar las etiquetas de abrir/cerrar del conjunto de caracteres que no son DOI. (Consulte https://sourceforge.net/p/jabref/patches/203/) – koppor

0

La siguiente expresión regular debe hacer el trabajo (la sintaxis de expresiones regulares de Perl):

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

que podría hacer un poco de cordura adicionales relativos al control mediante la apertura de las direcciones URL

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

y

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

dónde está el doi candidato,

y prueba de que a) obtienes un estado de 200 OK http, yb) la página devuelta no es la página "DOI no encontrado" para el servicio.

+3

Esta expresión regular no coincide con todo DOIs (particularmente los que contienen letras o puntos después de la barra), tales como http: // dx .doi.org/10.1038/ejcn.2010.73) –

+0

¡Pero el consejo de "control de cordura" es bueno! Por ahora, sin embargo, ['https: // doi.org /' debería usarse] (https://www.doi.org/doi_handbook/3_Resolution.html#3.8) para resolver DOIs :-) –

13

@Silas La comprobación de cordura es una buena idea. Sin embargo, la expresión regular no cubre todos los DOI. El primer elemento tiene que (actualmente) sea 10, y el segundo elemento tiene que (actualmente) ser numérico, pero el tercer elemento apenas se restringe en absoluto:.

"caracteres válidos son los caracteres gráficos legales de Unicode Esta específicamente excluye los rangos de caracteres de control 0x00-0x1F y 0x80-0x9F ... "

y ahí es donde radica el problema real. En la práctica, nunca he visto espacio en blanco utilizado, pero la especificación lo permite específicamente. Básicamente, no parece haber una manera sensata de detectar el extremo de un DOI.

5

estoy seguro que no es súper útil para la OP en este punto, pero pensé que había puesto lo que estoy tratando en caso de cualquier otra persona como yo se topa con esto:

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

Esto coincide : "Número de 10 puntos barra algo-no-espacio en blanco"

Pero para mi uso (raspado de HTML), esto era encontrar falsos positivos, así que tenía que coincidir con el anterior, además de deshacerme de las comillas y mayor que/menor que:

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

Todavía estoy probando esto, pero me siento esperanzado hasta el momento.

+0

Si bien esta expresión regular probablemente funcione para todos los nombres existentes de DOI, la especificación dice: _ "Todos los prefijos emitidos hasta ahora han sido cadenas numéricas simples, pero no hay nada que impida que se usen caracteres alfabéticos. El prefijo se puede dividir en prefijos secundarios, por ejemplo: 10.1000.10/123456 "_ –

+0

El texto citado de Ju9OR se puede encontrar en [el manual de DOI: La estructura de un nombre de DOI] (http://www.doi.org/handbook_2000/enumeration.html#2.2) – koppor

+2

Basado en los comentarios, la expresión regular '(10 \. [^ /] +/([^ (\ S \> \" \ <})]) +) 'funciona para mí (especialmente en archivos BibTeX) – koppor

2

Esta es una pregunta muy antigua y respondida, pero aquí hay otro posible sustituto.

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

Esto supone que el espacio en blanco no es parte del DOI.

No he probado esto en busca de falsos positivos, pero parece ser capaz de encontrar todos los casos extremos mencionados en esta página.

Cuestiones relacionadas