Aufschnur Logo

PowerShell: URLs aus Textdateien auslesen

Es gibt Situationen in denen man sämtliche URLs aus einer Datei auslesen möchte. Zum Beispiel um festzustellen, welche Webadressen in einer HTML-Datei untergebracht sind, oder um alle URLs aus einem XML-Export auszulesen. Im Folgenden beschreibe ich einen einfachen Weg, dies mit PowerShell durchzuführen. Wer eine fertige Lösung sucht, dem empfehle ich mein interaktives PowerShell-Skript URL Extractor.

Das Suchmuster

Für eine solche Aufgabe nutzt man am besten einen Regulären Ausdruck (RegEx). Im Internet findet man viele fertige RegEx-Pattern, wobei folgender für unsere Aufgabe gute Dienste leistet:

$regex = '([a-zA-Z]{3,})://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?'

Dieses Suchmuster findet in einem Text alle URLs, die mit http://, https://, ftp:// usw. anfangen. Es ist also wichtig, dass die URLs im zu durchsuchenden Text korrekt bzw. vollständig sind, inklusive dem Protokoll (z.B. http://). Ansonsten fallen sie durch das Raster.

Dateiinhalt durchsuchen

Wir verwenden das RegEx-Suchmuster in PowerShell in Verbindung mit dem Cmdlet Select-String. Über den Parameter -Path geben wir die einzulesende Datei an. Im Beispiel unten ist es eine Textdatei input.txt die im selben Verzeichnis wie das Skript liegt. Wichtig ist auch der Parameter -AllMatches, durch den auch mehrere Treffer in einer Zeile gefunden werden und nicht nur der erste.
Nun muss das Suchmuster lediglich auf einen Textinhalt losgelassen werden. Sämtliche Treffer werden dabei abschließend als Liste in eine Ergebnisdatei geschrieben. Damit es keine Duplikate gibt, lassen wir die Ergenisse zuvor noch durch das Cmdlet Get-Unique laufen. Dieses setzt aber eine bereits sortierte Liste voraus, deshalb wenden wir zuvor noch Sort an. In PowerShell können wir alle Schritte durch die Pipe reichen und damit in einem Einzeiler abbilden:

Select-String -Path "input.txt" -Pattern $regex -AllMatches | % { $_.Matches } | % { $_.Value } | Sort | Get-Unique > "output.txt"

Suchergebnisse trimmen

Standardmäßig extrahiert das Suchmuster die komplette URL, also inklusive eventuell vorhandenem Pfad und Query, wie hier bei Format 1:

Format 1: http://www.example.com/subdir/index.html?p1=A#ressource
Format 2: http://www.example.com
Format 3: example.com

Möchtet ihr die Ergebnisse kürzen, damit sie im Format 2 oder 3 gespeichert werden, dann müsst ihr die Ergebnisliste aus dem vorherigen Abschnitt z.B. in ein Array oder besser in eine Arrayliste (System.Collections.ArrayList) laden und per Foreach-Object in einer Schleife durcharbeiten.

# Arraylisten initialisieren
[System.Collections.ArrayList]$arrlist_alt = @()
[System.Collections.ArrayList]$arrlist_neu = @()
# Die Ergebnisse aus dem ersten Durchlauf in die Arrayliste laden
$arrlist_alt = Get-Content -Path "output.txt"
# Die Arrayliste durchlaufen und die Einträge dabei bearbeiten
$arrlist_alt | Foreach-Object  {
    # <<< Hier die gewünschte Aktion >>>
    [void]$arrlist_neu.Add($domain)
}

Wenn ihr z.B. lediglich Protokoll + Host/(Sub)Domains (siehe oben Format 2) der URL behalten möchtet, lasst ihr als Aktion -Replace mit folgendem RegEx-Pattern über jeden Eintrag laufen:

$domain = $_ -Replace '^([a-zA-Z]{3,}://[^/]+).*', '$1';

Wenn ausschließlich nur der Host mit (Sub)Domains (siehe oben Format 3) gespeichert werden soll, könnt ihr euch der URI-Klasse bedienen und den Host auslesen. Das angehängte -Replace '^www\.' könnt ihr weg lassen, wenn ihr die Domain inklusive www. speichern möchtet:

$domain = ([System.Uri]$_).Host -Replace '^www\.'

Fertiges Skript: URL Extractor

Ich habe auch ein PowerShell-Skript zu dieser Thematik erstellt, welches alle hier geschilderten Möglichkeiten abdeckt und euch interaktiv durch den Vorgang leitet.

Zum URL Extractor

Diese Beiträge könnten dich auch interessieren:

1 Kommentar

Raspberry.l33t
6. Mai 2019 um 22:12 Uhr

Lieben Dank für das Script. Ich würde die Ausgabe gerne weiterverarbeiten. Hierzu wird Vor und Hinter der URL jeweils ein “ benötigt und der Absatz soll entfallen (Fließtext). Könnten sie mir hierfür ein Codeschnipsel zukommen lassen? Beste grüße



Deine Meinung zählt