In mijn dagelijkse werk houd ik mij veel bezig met Information Extraction. Met Information Extraction (Informatie Extractie) wordt bedoeld ‘het vinden van Informatie uit ongestructureerde data, bijvoorbeeld vrije tekst of HTML’. Information Extraction kan worden gebruikt om bijvoorbeeld geautomatiseerd elementen uit CVs te herkennen of documenten geautomatiseerd te categoriseren. Zoekmachines maken vaak gebruik van Information Extraction om relevantie van een website op basis van een zoekterm te bepalen.

Soms is het interessant om de URLs / Hyperlinks uit een stuk ongeordende tekst te halen, bijvoorbeeld:

  • om te bepalen wat op dit moment een heel erg HOT onderwerp is op het internet
  • om een spider of crawler (Gebruikt door onder andere zoekmachines) te maken
  • om het onderwerp van een artikel te achterhalen.
  • om een sitemap te kunnen maken

Er zijn een aantal methoden mogelijk om deze URLs te vinden. Eén daarvan is het gebruiken van regular expressions (Reguliere expressies). Om dit te kunnen doen is er naast een reguliere expressie een stukje programmeerwerk nodig. Ik zal een voorbeeld geven hoe dit te doen met C# (.NET).

Reguliere Expressie
Allereerst de regulier expressie. Met een reguliere expressie wordt een patroon op een dusdanige wijze beschreven  dat een computer in staat is dit partoon in vrije tekst te herkennen. Alvorens we een reguliere expressie voor het herkennen van Hyperlinks kunnen schrijven kijken we eerst naar de structuur van een URL/Hyperlink in HTML. Deze is (bijna altijd) als volgt:

<a {mogelijke andere attributes} href="{url}" {mogelijke andere attributes}>{anchor}</a>

Zeker is dat het patroon altijd begint met ‘<a’ en dat er ergens tussen de ‘<a’ en de eerst daaropvolgende ‘>’ een patroon is dat er uitziet als ‘href=’. Na ‘href=’ staat altijd de URL waar het om gaat.  Soms worden er dubbele quotes rondom de URL gebruikt. Soms enkele quotes en soms helemaal geen quotes. Na de ‘>’ begint de anchor-tekst (de tekst die de lezer ziet als hyperlink) en deze eindigt na ‘</a>’. Overal in dit patroon zouden enters kunnen voorkomen. Om dit patroon te kunnen herkennen is de volgende reguliere expressie nodig:

<a[^>]*href\s*=\s*[\"\']?(?<URI>[^"'>\s]*)[\"\']?[^>]*>(?<Anchor>[^<]+|.*?)?</a\s*>

Het gaat nu te ver om deze reguliere expressie in detail te beschrijven, maar geinteresseerden kunnen een uitleg van alle symbolen in deze reguliere expressie hier vinden. Ik gebruik deze regex (afkorting) in vele van mijn websites en spiders en in de praktijk voldoet deze prima.

Voorbeeld in sofware (C#)
Reguliere expressies kunnen voor verschillende doeleinden worden gebruikt, bijvoorbeeld:

  • Het vervangen van tekst dat voldoet aan een patroon door andere tekst
  • Het vinden van tekst dat voldoet aan een patroon
  • Het vinden van tekst dat wordt gevonden tussen twee patronen
  • Het valideren van tekst (voldoet deze aan het patroon?) Bijvoorbeeld een telefoonnummer.

Ik geef hier een voorbeeld hoe je deze reguliere expressie kunt gebruiken om de patronen van een hyperlink te vinden en binnen de patroon de URL, de anchor tekst en de eerste letter van het patroon in de tekst  te vinden.  Dit voorbeeld is geschreven in C#.

//Geschreven in C-sharp

private DataTable ExtractAllURLs(string in_String)
{
    //Maak een tabel met de velden ‘URL’, ‘Anchor’ en ‘Position’
    DataTable lv_URLs = new DataTable();
    lv_URLs.Columns.Add(”URL”);
    lv_URLs.Columns.Add(”Anchor”);
    lv_URLs.Columns.Add(”Position”);

    //De reguliere expressie om URL en anchor te vinden
    Regex lv_FindAllURLs = new Regex(@”<a[^>]*href\s*=\s*[\""\']?(?<URI>[^""'>\s]*)[\""\']?[^>]*>(?<Anchor>[^<]+|.*?)?</a\s*>”);

    //Vind alle patronen en sla deze op in een MatchCollection object
    MatchCollection mMatchCollection = lv_FindAllURLs.Matches(in_String);

    //Voeg alle URLs, Anchors en gevonden posities in individuele records toe aan de tabel�
    foreach (Match mMatch in mMatchCollection)
    {
        string lv_URL = mMatch.Groups["URI"].Value;
        string lv_Anchor = mMatch.Groups["Anchor"].Value;

        DataRow lv_DataRow = lv_URLs.NewRow();
        lv_DataRow["URL"] = lv_URL;
        lv_DataRow["Anchor"] = lv_Anchor;
        lv_DataRow["Position"] = mMatch.Groups["URI"].Index.ToString();
        lv_URLs.Rows.Add(lv_DataRow);
    }

    return lv_URLs;
}

Dit is natuurlijk een voorbeeld met veel op en aanmerkingen, bijvoorbeeld:

  • De gevonden URLs kunnen nog een relatieve URLs zijn (dus verwijzen naar interne paginas).
  • Er kan sprake zijn van een niet geldige of juist geformatteerde URL
  • Er kan nog HTML in de anchor tekst staan

Desalnietemin is dit denk ik een leuk voorbeeld van Information Extraction.