ASP Classic

Woher kommen die Besucher meiner Web-Site?

Über die IP-Adresse oder den Host-Namen das Land des Besuchers ermitteln

Jeder Web-Server, der eine Anfrage erhält, protokolliert ein paar Informationen über den Besucher, wie den User-Agent, die IP-Adresse, et cetera. Was leider fehlt ist die Angabe aus welchem Land die Anfrage kommt, obwohl diese Information gerade bei international ausgelegten Web-Sites von Interesse ist, gerade in Bezug auf das Marketing, wenn man den ein solches betreibt. Mit dem Wissen aus welchem Land die überwiegende Anzahl der Besucher kommt, lassen sich z.B. Werbeaktionen wesentlich effektiver einsetzen.

Der einzige sichere Anhaltspunkt zu ermitteln aus welchem Land eine Seitenanfrage kommt, ist die übermittelte IP-Adresse. Nachfolgend drei Alternativen, wie man dies hinbekommt.

Alternative 1

Mit der IP-Adresse lässt sich im ersten Schritt über das Domain Name System (DNS) schon einmal der Host-Name der Anfrage ermitteln. Wie das funktioniert habe ich u.a. im Artikel Mit der IP-Adresse den Host-Namen auflösen beschrieben.

So wird z.B. aus der IP-Adresse 213.39.164.xxx der Hostname xxx.adsl.hansenet.de. Extrahiert man nun z.B. per ASP aus dem Host-Namen die Top-Level-Domain (TLD), also die letzten Zeichen nach dem letzten Punkt, so kann man für unser Beispiel sagen, das der Seitenaufruf von einem deutschen Server stammte. Genauer: von einem Kunden des deutschen Providers Hansenet. Gelegen kommt uns dabei die Tatsache, dass die Codes der Länder-TLD's mit den standardisierten ISO-3166-Länderkennungen übereinstimmen.

'IP auslesen
strIP = Request.ServerVariables("REMOTE_ADDR")

'Hostname ermitteln (siehe zerbit-Artikel Nr.40 und 41)
strHost = GetHostName(strIP)

'Hostname an den Punkten in Array zerlegen
arr = Split(strHostname, ".")

'Letztes Array-Element enthält TLD
strTLD = arr(UBound(arr))

Sammeln kann man diese Information nun z.B. in einer Datenbanktabelle mit folgender Struktur:

TLD Anzahl
de 1023
at 345
ch 123

Bei jedem Zugriff kann man nun die TLD ermitteln und die Anzahl in der Tabelle um 1 erhöhen.

Problem

Problematisch beim Einsatz dieser Variante sind all jene TLD's, die keine Länderkennung tragen: COM, NET, ORG, EDU, et cetera. Man könnte nun hingehen und automatisch davon ausgehen, dass diese Server in den USA stehen, aber das würde das Bild extrem verfälschen, denn z.B. die TLD's COM und NET sind auch außerhalb der USA sehr beliebt.

Weiterhin kann es sein, dass ein Server zwar eine Länderkennung trägt, aber dem Land gar nicht zuzuordnen werden kann. Beispiel hierfür ist die Top-Level-Domain TV, die zwar dem Inselstaat Tuvalu gehört, aber gerade bei Fernsehsendern sehr beliebt ist. Die Regierung von Tuvalu hat schlicht die eigene TLD verkauft.

Alternative 2

Dem Problem, die TLD's COM, NET, et cetera aufzulösen, kommen wir nur bei, wenn wir uns externer Daten bedienen. Man muss dazu wissen, dass der gesamte IP-Adressbereich nach gewissen Regeln weltweit aufgeteilt ist. Man kann also, wenn man über die aktuellen Aufteilungsdaten verfügt, aus einer IP-Adresse direkt das Land des Servers ableiten.

Es gibt inzwischen einige kommerzielle Dienste, die die Zuordnung einer IP zu einem Land über Web-Dienste ermöglichen. Meist erwirbt man sich dabei ein Zugriffskontingent, d.h. für die erfolgreiche Bestimmung von 10.000 IP-Adressen muss man dann Betrag X berappen.

Man kann heutzutage jedoch davon ausgehen, dass es für jede Art von Internet-Dienst auch ein kostenloses Pendant aus dem Open-Source-Bereich gibt. So auch hier. Bei der Recherche nach Diensten, die IP-Adressen in Länderkennungen auflösen, stieß ich auf hostip.info, einem Dienst unter der Common-Public-License (CPL). Die Datenbasis von hostip.info bilden eigene Robots, die unablässig  IP-Adressen per Traceroute auflösen. Benutzer des Service sind jedoch aufgefordert fehlende bzw. falsche Einträge zu korrigieren, was mit der Zeit zu einem recht umfangreichen Datenbestand führte und führt.

hostip.info bietet für die automatisierte Abfrage eine API. So kann man sich die Daten, neben einem Text-Feed, auch in einer XML-Datei liefern lassen. Grundlage ist wie so oft das XMLHTTP-Objekt.

Beispiel für eine ASP-Prozedur zur Abfrage:

Private Sub GetCountry_hostip(strIP, strCode, strName)

   strURL = "http://api.hostip.info/?ip=" & strIP

   Set objXmlHttp = CreateObject("MSXML2.ServerXMLHTTP")

   objXmlHttp.open "GET", strURL, False
   objXmlHttp.send

   strCode = objXmlHttp.ResponseXml.DocumentElement._
      GetElementsByTagName("countryAbbrev").Item(0).Text

   strName = objXmlHttp.ResponseXml.DocumentElement. _
      GetElementsByTagName("countryName").Item(0).Text

   Set objXmlHttp = nothing

End Sub

Wie im Beispiel dargestellt, bekommt man zwei Informationen zurück: die ISO-Länderkennung (z.b. DE) und den englischen Namen des Landes (z.B. GERMANY). Über den Text-Feed erhält man zusätzlich noch die Koordinaten des Servers, sofern sie vorliegen.

Problem

Um eine lückenlose Statistik zu erhalten, muss man jeden ersten Zugriff auf eine Web-Site auf diese Art und Weise protokollieren. Im Test reagierte hostip.info jedoch zum Teil etwas bockig. Mehr als einmal lief ich in einen Timeout, was natürlich dazu führt, dass der Seitenaufbau der eigenen Seite sich extrem verzögert. Und das nur wegen einer Länderstatistik?

Alternative 3

Die indische Firma Directi bot über das Portal webhosting.info bis vor Kurzem ebenfalls einen Länderabfragedienst an. Er wurde jedoch eingestellt, da man den aufkommenden Traffic nicht mehr vernünftig bewältigen konnte und sich das Ganze wohl nicht mehr rechnete. Einzig die Datenbasis blieb bestehen und wird auch weiter gepflegt. Jeder interessierte Webmaster kann sich die Daten der IP-To-Country-Database (zur Zeit ca. 63.000 Datensätze) in Form einer CSV-Datei gepackt als ZIP herunterladen und weiterverarbeiten.

Die Daten liegen in folgendem Format vor:

IP-From    IP-To      Country (2-Letter-Code, 3-Letter-Code, Name)
=======    =====      ==== ===== =================================
"33996344","33996351","GB","GBR","UNITED KINGDOM"
"50331648","69956103","US","USA","UNITED STATES"
"69956104","69956111","BM","BMU","BERMUDA"
...
"264482816","264486911","DE","DEU","GERMANY"

Jeder Datensatz repräsentiert einen IP-Bereich und ist einem Land zugeordnet. Die IP-Adressen liegen der besseren Vergleichbarkeit halber als Ganzzahlen vor.

Vor dem Einsatz der Daten, müssen sie zunächst in eine Datenbank importiert werden. In meinem Beispiel kommt eine Access-Datenbank zum Einsatz, da man eine solche Datei bei einem der regelmäßigen Updates der IP-To-Country-Daten einfach nur erneut erstellen und über die alte kopieren braucht und sich CSV-Dateien zudem sehr leicht über die eingebauten Assistenten in eine Access-MDB pumpen lassen. Beachten sollte man beim Import der CSV-Datei über ein deutsches Access, dass als Feld-Trennzeichen ein Komma verwendet wurde und dies in Access als Dezimaltrennzeichen gewertet wird.

Da der Import regelmäßig stattfinden sollte, verändern wir die Standardeinstellungen des Import-Assistenten in Bezug auf den Namen der neuen Tabelle nicht. Sie heißt nachher ebenso wie die CSV-Datei: Ip-to-country. Die Feldnamen werden nicht geändert. Die von Access vorgeschlagene fortlaufende Nummerierung (Feld1, Feld2,...) genügt. Die Access-Datenbank benennen wir ip2country.mdb.

Zum Vergleich einer IP-Adresse mit den Daten der Tabelle, muss diese zunächst ebenfalls in eine Ganzzahl umgerechnet werden:

Public Function IP2Number(strIP)

   arr = Split(strIP, ".")

   intConvert = _
   (arr(0) * (256*256*256)) + _
   (arr(1) * (256*256)) + _
   (arr(2) * 256) + _
   (arr(3))

   IP2Number = intConvert

End Function

Mit dieser Zahl fragen wir dann die Access-Tabelle ab:

Public Sub GetCountry_LocalDB(intIP, strCode, strName)

   'Connection-String erzeugen
   strConString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source="
   strConString = strConString & Server.MapPath("/database/ip2country.mdb")

   'Verbindung zur Datenbank aufbauen
   Set connIP = Server.CreateObject("ADODB.Connection")
   connIP.Open strConString

   'Recordset erzeugen und Daten abfragen
   Set rsLocIP = Server.CreateObject("ADODB.Recordset")
   strSQL = "SELECT * FROM [Ip-to-country] " & _
      "WHERE Feld1 <= " & strIPNr & " AND Feld2 >= " & strIPNr
   rsLocIP.Open strSQL, connIP

   'gefundenen Datensatz auswerten
   If Not(rsLocIP.EOF) OR Not(rsLocIP.BOF) Then
      strCode = rsLocIP.Fields("Feld3")
      strName = rsLocIP.Fields("Feld5")
   Else
      strCode = ""
      strName = ""
   End if

   'Recordset und Verbindung wieder schließen
   rsLocIP.Close
   connIP.Close
   Set rsLocIP = nothing
   Set connIP = nothing

End Sub

Fazit

Es gibt bei der kostenfreien Ermittlung der Länderkennung einer IP-Adresse keine Lösung die vollends überzeugt. Durch den geschickten Einsatz aller drei hier vorgestellten Ansätze, lässt sich jedoch eine recht saubere Statistik erzeugen, die wohl ziemlich nahe an der Wirklichkeit liegt.

Wer eine solche Statistik mit etwas Farbe aufpeppen möchte, dem lege ich meine 222 Länder-Icons in der Größe 20 x 13 Pixeln im GIF-Format ans Herz.

Downloads

kick it on dotnet-kicks.de AddThis 0 wikio-Stimme(n) Trackback-Url...

Keine Kommentare bislang...

Dein Kommentar hierzu...


Kommentar-Feed für diesen Beitrag
Gravatare werden unterstützt .:. eMail-Adressen werden nicht veröffentlicht
 

RSS-Feed

Die URL des Standard-Newsfeed von zerbit.de lautet:

http://www.zerbit.de/rssfeed.aspx

Login


 

 

Statistik



kürzlich kommentiert

Artikel 57

  • Datum: 09.01.2006
    Kategorie: ASP Classic
    Zugriffe: 6.115
    Kommentare: 0
    Trackbacks: 0

Letzte Beiträge

Kategorien

Buttons & More

Blog-Roll

Banner Piraten-Partei