Frage

Der DOI Das System setzt im Grunde keine sinnvollen Beschränkungen dessen, was es ausmacht eine sinnvolle Kennung.Allerdings ist es möglich, DOIs aus PDFs, Webseiten usw. zu extrahieren.ist sehr nützlich für Zitatinformationen usw.

Gibt es eine zuverlässige Möglichkeit, einen DOI in einem Textblock zu identifizieren, ohne das Präfix „doi:“ anzunehmen?(jede Sprache ist akzeptabel, reguläre Ausdrücke werden bevorzugt und die Vermeidung von Fehlalarmen ist ein Muss)

War es hilfreich?

Lösung

Ok, ich extrahiere derzeit Tausende von DOIs aus Freiformtext (XML) und das ist mir klar geworden mein bisheriger Ansatz hatte ein paar Probleme, nämlich mit kodierten Entitäten und nachgestellten Satzzeichen, also habe ich weitergelesen die Spezifikation und das ist das Beste, was ich mitbringen konnte.


Das DOI -Präfix besteht aus einem Verzeichnisindikator, gefolgt von einem Registrantencode.Diese beiden Komponenten müssen durch einen vollständigen Stopp (Periode) getrennt werden.

Der Verzeichnisindikator muss „10“ sein.Der Verzeichnisindikator unterscheidet den gesamten Satz von Zeichenketten (Präfix und Suffix) als digitale Objektkennung innerhalb des Auflösungssystems.

Ganz einfach, der Anfang \b verhindert, dass wir einen „DOI“ „abgleichen“, der nicht mit beginnt 10.:

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

Das zweite Element des DOI-Präfixes ist der Registrantencode.Der Registrant Code ist eine eindeutige Zeichenfolge, die einem Registranten zugeordnet ist.

Außerdem sind alle zugewiesenen Registrantencodes numerisch und mindestens 4 Ziffern lang, also:

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

Der Registrant-Kodex kann bei gewünschtem Verwaltungskomfort weiter in Unterelemente unterteilt werden.Jede Unterelement des Registrantenkodex dürfte einen vollständigen Stopp vorangestellt werden.

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

Die DOI -Syntax muss aus einem DOI -Präfix und einem DOI -Suffix bestehen, das durch einen Vorwärtsschräger getrennt ist.

Dies ist jedoch nicht unbedingt erforderlich. Abschnitt 2.2.3 besagt, dass ungewöhnliche Suffixsysteme möglicherweise andere Konventionen verwenden (z. B 10.1000.123456 anstatt 10.1000/123456), aber lassen wir es etwas lockerer angehen.

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

Der DOI-Name ist Fall-unempfindlich und kann alle druckbaren Zeichen aus den rechtlichen Grafikzeichen von Unicode einbeziehen.Das DOI -Suffix muss aus einer Zeichenfolge aus jeder vom Registranten ausgewählten Länge bestehen.Jedes Suffix muss für das Präfixelement eindeutig sein, das ihm vorausgeht.Das eindeutige Suffix kann eine sequentielle Zahl sein oder eine aus einem anderen System erzeugte Kennung oder basierend auf einem anderen System enthalten.

Jetzt wird es schwieriger, von allen DOIs, die ich verarbeitet habe, habe ich die folgenden Zeichen gesehen (außerdem [0-9a-zA-Z] natürlich) in ihrem Suffixe: .-()/:- – also, obwohl es nicht existiert, der DOI 10.1016.12.31/nature.S0735-1097(98)2000/12/31/34:7-7 ist völlig plausibel.

Die logische Wahl wäre die Verwendung \S oder der [[:graph:]] PCRE POSIX-Klasse, also machen wir das:

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

Jetzt haben wir ein schwieriges Problem, das [[:graph:]] Klasse ist eine Obermenge der [[:punct:]] Klasse, die Zeichen enthält, die leicht in Freitext oder einer beliebigen Auszeichnungssprache zu finden sind: "'&<> unter anderen.

Filtern wir zunächst einfach die Markup-Einträge mit einem negativen Lookahead:

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

Das Obige sollte codierte Entitäten abdecken (&), Attribut-Anführungszeichen (["']) und Tags zum Öffnen/Schließen ([<>]).

Im Gegensatz zu Auszeichnungssprachen werden in Freitext normalerweise keine Satzzeichen verwendet, es sei denn, sie sind durch mindestens ein Leerzeichen begrenzt oder am Ende eines Satzes stehen, zum Beispiel:

Dies ist ein langer DOI: 10.1016.12.31/nature.S0735-1097(98)2000/12/31/34:7-7!!!

Die Lösung hier besteht darin, unsere Erfassungsgruppe zu schließen und eine andere Wortgrenze festzulegen:

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

Und voilá, Hier ist eine Demo.

Andere Tipps

@Silas Die Überprüfung der geistigen Gesundheit ist eine gute Idee.Der reguläre Ausdruck deckt jedoch nicht alle DOIs ab.Das erste Element muss (derzeit) 10 sein und das zweite Element muss (derzeit) numerisch sein, aber das dritte Element unterliegt kaum Einschränkungen:

„Zulässige Zeichen sind die zulässigen Grafikzeichen von Unicode.Ausgenommen hiervon sind insbesondere die Steuerzeichenbereiche 0x00-0x1F und 0x80-0x9F..."

Und genau darin liegt das eigentliche Problem.In der Praxis habe ich noch nie die Verwendung von Leerzeichen gesehen, aber die Spezifikation erlaubt dies ausdrücklich.Grundsätzlich scheint es keine sinnvolle Möglichkeit zu geben, das zu erkennen Ende eines DOI.

CrossRef hat eine Empfehlung, dass sie bei 99,3 % der DOIs erfolgreich getestet wurden:

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

Ich bin mir sicher, dass es für den OP an dieser Stelle nicht besonders hilfreich ist, aber ich dachte, ich poste, was ich versuche, falls jemand anderes wie ich darüber stolpert:

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

Das passt:„10-Punkt-Schrägstrich für alles, was kein Leerzeichen ist“

Aber für meine Verwendung (Scraping von HTML) wurden falsch-positive Ergebnisse gefunden, also musste ich mit den oben genannten übereinstimmen und außerdem Anführungszeichen und Größer-als/Kleiner-als entfernen:

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

Ich teste sie immer noch, aber bisher bin ich hoffnungsvoll.

Hier ist mein Versuch:

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

Und ein paar gültige Randfälle, bei denen dies nicht fehlschlägt, andere jedoch zu funktionieren scheinen:

Außerdem werden einige falsche (X|HT)ML-Sachen korrekt verworfen, wie zum Beispiel:

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

Dies ist eine wirklich alte und beantwortete Frage, aber hier ist ein weiterer möglicher Ersatz.

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

Dies setzt voraus, dass Leerzeichen nicht Teil des DOI sind.

Ich habe dies nicht auf Fehlalarme getestet, aber es scheint in der Lage zu sein, alle auf dieser Seite erwähnten Randfälle zu finden.

Der folgende reguläre Ausdruck sollte die Aufgabe erfüllen (Perl-Regex-Syntax):

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

Sie könnten eine zusätzliche Plausibilitätsprüfung durchführen, indem Sie die URLs öffnen

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

Und

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

Wo ist der Kandidat doi,

und testen, ob Sie a) den HTTP-Status „200 OK“ erhalten und b) die zurückgegebene Seite nicht die Seite „DOI nicht gefunden“ für den Dienst ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top