automatisiertes einlesen unbekannter Daten

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Moses4python
User
Beiträge: 13
Registriert: Donnerstag 16. Mai 2019, 20:43

Hallo Zusammen,

ich hoffe, ich bin hier richtig, da ich denke, dass pandas und numpy ein guter Ausgangspunkt sind für meine Problemstellung.

Also wie bereits in anderen Fragestellungen geht es um die Analyse von Headern. Nun stehe ich aber vor einem Problem und bin mir nicht ganz sicher wie am besten herangehen soll.

Wenn ich Header von einigen wenigen URLs einlesen möchte kann ich mir die Daten sowohl mit dem csv.writer als auch pandas in eine csv Datei schreiben lassen. Dann kann ich manuell hingehen und diese Daten auswerten.

Da ich nun aber 8 verschiedene Browser verwende, muss ich feststellen, dass die Reihenfolge der Header unterschiedlich ist und die Anzahl der Daten manuell unhandlich wird, wenn ich beispielsweise 8 * 30 Webseiten abfrage.

ich hatte gedacht, dass eine Möglichkeit wäre die Daten als Dictionaries in einer Liste zu verpacken, ungefähr so:

Code: Alles auswählen

import pandas as pd
import numpy as np


test = pd.DataFrame({'Browser': ['firefox_linux', 'firefox_win', 'opera_linux'],
                   'OS': ['Kali_Linux', 'Windows10', 'MacOS'],
                   'URL': ['http://python.de', 'http://example.com', 'http://github.com'],
                   'User-Agent': ['Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36 OPR/62.0.3331.43',
                                  'Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0',
                                  'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36'],
                   'Server': ['Apache-Coyote/1.1', 'Apache', 'Apache/2.4.18 (Ubuntu)']},
                    index=pd.Index(range(3), name='idx'))

test.to_csv('foo.csv')
pd.read_csv('foo.csv')

Den Code habe ich entsprechend der Doku: https://pandas.pydata.org/pandas-docs/s ... 10min.html ummodeliert
Allerdings ist der Code für meine Zwecke Blödsinn. Natürlich hätte ich dann eine schöne Tabelle, aber die Variablen wären ja nicht richtig zugeordnet.

Um die Tabelle auswerten zu können, bräuchte ich eindeutige Spalten:

Index, Browser, OS, User-Agent, Server, Content-Length, Content-Language + ... n

Wenn ich Daten also auslese und die Reihenfolge der hereinkommenden Daten variieren, sind also unbekannt, gibt es dann eine Möglichkeit, die dennoch automatisiert Variablen zuordnen zu lassen?.

Beispielsweise wird in python per default kein DNT (DoNotTrack) attribut ausgegeben, in Firefox schon (es sein denn man baut den header nach). Bei Python müsste dann Naan angegeben sein, bei Firefox wäre dann als Eintrag '1' zu sehen. Die Server unterscheiden sich von mal zu mal, auch wenn die gleiche Seite gescannt wird... usw. es können A/B Tests auf den Seiten vorkommen, was ebenfalls zu einer unterschiedlichen Datenstruktur führt.

Macht es hier Sinn machine learning anzuwenden? Hat Scikit-learn hier vielleicht Möglichkeiten anzusetzen? Wenn man einen Spamfilter mit der bayesianischen Methode baut, dann trainiert man ja im Grunde auch einen Algorithmus, damit dieser erkennt, was spam ist und was nicht und kann am Ende unbekannte Daten verarbeiten und zuordnen (korrigiert mich, wenn ich falsch liege). Ich musste das zumindest mal in einem Tutorial machen, dort hatten wir dann 500 Text Dateien, mit E-Mail Headern und Schimpfwörtern und 500 Text Dateien mit regulären Mails. Diese haben wir dann unterteilt in zwei Ordner "Spam" & "Ham". Wenn ich also je Browser einen Ordner erstelle mit Text Dateien und den entsprechenden Headern... wäre das realistisch oder habe ich hier einen Denkfehler?

Ich bin für jeden Tip dankbar, der Zielführend ist und wenn einfach der Link zu einer Dokumentation ist für irgendeine hilfreiche Bibliothek, die ich mir anschauen soll.

Ich hoffe, der Text war nicht zu verwirrend und danke vorab.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Ich verstehe Dein Problem nicht. Du hast unterschiedliche HTTP-Header, die jeweils aus Key:Value bestehen. Da ist die Reihenfolge also egal, weil Du nach dem Schlüssel darauf zugreifen mußt.

Kannst Du ein konkretes Beispiel mit Code geben, anhand dessen man sehen kann, was Dein Problem ist?
Moses4python
User
Beiträge: 13
Registriert: Donnerstag 16. Mai 2019, 20:43

Ich verstehe Dein Problem nicht. Du hast unterschiedliche HTTP-Header, die jeweils aus Key:Value bestehen. Da ist die Reihenfolge also egal, weil Du nach dem Schlüssel darauf zugreifen mußt.
Kannst Du ein konkretes Beispiel mit Code geben, anhand dessen man sehen kann, was Dein Problem ist?
hm, also wenn ich aber die Daten nun in eine csv schreibe, kommen die doch unbereinigt an.

Hier der Code in gekürzter Form:

Code: Alles auswählen

import requests
import csv
import time

urls = ['http://11st.co.kr',
        'http://39.net',
        'http://4chan.org',
        'http://4pda.ru',
        'http://51sole.com',
        'http://52kards.com',
        'http://accuweather.com',
        'http://addroplet.com',
        'http://adexchangecloud.com',
        'http://adhoc2.net',
        'http://ajkzd9h.com',
        'http://albawabhnews.com',
        'http://english.caijing.com.cn/',
        'http://mikrosimage.com',
        'http://osbot.org',
        'http://p-zwei.de',
        'http://www.163.com',
        'http://www.aaacommerce.co.za',
        'http://www.caijing.com',
        'http://www.china.com.cn',
        'http://www.eastday.com',
        'http://www.example.com',
        'http://www.homedepot.com',
        'http://www.igiyi.com',
        'http://www.ortodoncia.com.mx',
        'http://www.sfvvv.com',
        'http://www.sportsdecathlon.com',
        'http://www.ard.de/home/ard/ARD_Startseite/21920/index.html']


def firefox_linux(urls):

    with open('.../http.csv', 'r') as csvfile, open('.../result.csv', 'w') as result:
            filereader = csv.reader(csvfile)
            for line in csvfile:
                headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0',
                           'Accept': 'text/html,apllication/xhtml+xml,application/xml;q=0.9,*/*;q=8',
                           'Accept-Language': 'de,en-US;q=0.7,en;q=0.3',
                           'Accept-Encoding': 'gzip, deflate',
                           'DNT': '1',
                           'Connnection': 'keep-alive',
                           'Upgrade-Insecure-Requests': '1'}

            for i in range(1):
                for url in urls:
                    r = requests.get(url, headers=headers)
                    time.sleep(5)
                    print(r.url)
                    print(r.status_code)
                    print(r.headers)
                    result.write("Browser: Firefox | Linux" + ',' + "\n")
                    result.write("URL: " + url + ',' + "\n")
                    result.write((str(headers)) + ',' + '\n')

                    print("firefox_linux:  Done")


firefox_linux(urls)

def firefox_win(urls):
    with open('.../http.csv', 'r') as csvfile, open('.../result.csv', 'a') as result:
            filereader = csv.reader(csvfile)
            for line in csvfile:
                headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0',
                           'Accept': 'text/html,apllication/xhtml+xml,application/xml;q=0.9,*/*;q=8',
                           'Accept-Language': 'de,en-US;q=0.7,en;q=0.3',
                           'Accept-Encoding': 'gzip, deflate',
                           'DNT': '1',
                           'Connnection': 'keep-alive',
                           'Upgrade-Insecure-Requests': '1'}

            for url in urls:
                r = requests.get(url, headers=headers)
                time.sleep(5)
                print(r.url)
                print(r.status_code)
                print(r.headers)
                result.write("Browser: Firefox | Windows10" + ',' + "\n")
                result.write("URL: " + url + ',' + "\n")
                result.write((str(headers)) + ',' + '\n')
                print("firefox_win: " + " Done")


firefox_win(urls)

def edge_win(urls):
    with open('.../http.csv', 'r') as csvfile, open('.../result.csv', 'a') as result:
            filereader = csv.reader(csvfile)
            for line in csvfile:
                headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362',
                           'Accept': 'text/html,apllication/xhtml+xml,application/xml;q=0.9,*/*;q=8',
                           'Accept-Language': 'de,en-US;q=0.7,en;q=0.3',
                           'Accept-Encoding': 'gzip, deflate',
                           'DNT': '1',
                           'Connnection': 'keep-alive',
                           'Upgrade-Insecure-Requests': '1'}

            for url in urls:
                r = requests.get(url, headers=headers)
                time.sleep(5)
                print(r.url)
                print(r.status_code)
                print(r.headers)
                result.write("Browser: Edge | Windows10" + ',' + "\n")
                result.write("URL: " + url + ',' + "\n")
                result.write((str(headers)) + ',' + '\n')
                print("edge_win: " + " Done")


edge_win(urls)
In dieser Form kriege ich also in der csv untereinander den Output raus, der entsprechend wie oben dann so ausschaut:

Code: Alles auswählen

Browser: Firefox | Linux,
URL: http://example.com,
{'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0', 'Accept': 'text/html,apllication/xhtml+xml,application/xml;q=0.9,*/*;q=8', 'Accept-Language': 'de,en-US;q=0.7,en;q=0.3', 'Accept-Encoding': 'gzip, deflate', 'DNT': '1', 'Connnection': 'keep-alive', 'Upgrade-Insecure-Requests': '1'},
Damit erhalte ich die Request Header untereinander in einer csv Datei aufgelistet.

Aber um dann die Ergebnisse vergleichen und analysieren zu können, bräuchte ich eine Tabelle, mit Spalten Überschriften:

Code: Alles auswählen

Browser | OS,	Host,	Connection,	Upgrade-Insecure-Requests,	User-Agent,	DNT,	Accept,	Accept-Encoding,	Accept-Language,	HTTP/1.1,	Server, Last Modified,	ETag, Accept-Ranges,	Content-Type, Content-Encoding, Content-Length, Content-Language, Location, Cache-Control, Date, Connection, Connection,	X-N, Vary, Keep-Alive,
Heißt, die Tabelle muss nicht nur die Daten mit den Request Daten enthalten sondern auch die Responses. Und man kann eine Seite mehrfach crawlen und enthält unterschiedliche Variablen. Beispielsweise unterscheidet sich der Content-Length jedesmal bei dynamischen Seiten wie beispielsweise der ARD. Und wenn man die ARD Seite 10 mal cralwed erhält man auch unterschiedliche Antworten für Content-Language.

Wenn ich nun die Dictionary Variante angebe, deklariere ich ja bereits die Variablen im Dictionary aber bräuchte im Grunde genommen Platzhalter, die dann ausgefüllt werden. Nimm das Beispiel Content-Language.
Bei der Ard wir einem manchmal de angezeigt, dann de-DE oder en-US oder nur en oder manchmal tr-TR. Hier wäre also Content-Language der 'Key' aber der 'Value' wäre mal 'de', mal 'en' oder 'en-US' etc. Und das ist noch das am wenigsten komplexe Beispiel, IMHO. Mit Accept sieht es nicht besser aus.

Aber vielleicht sehe ich es auch zu kompliziert?
@Sirius3, ich hoffe, diesmal habe ich es besser erklärt?

Also wenn ich es wie in meinem Ausgangs Post durch definieren muss, dann könnte es zwar funktionieren, aber dann wäre es mit recht viel manuellem Aufwand verbunden, da ich doch dann alle möglichen Varianten einzelnd schreiben müsste oder nicht?
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Du hast keine csv-Datei, wenn Du die Daten zu einer URL untereinander schreibst. Willst Du wirklich eine csv-Datei schreiben, dann mußt Du halt alle Spaltennamen wissen und ist der entsprechende Header nicht gesetzt, kann der Eintrag auch leer bleiben.
Willst Du alle Header-Daten speichern, dann ist csv das falsche Format.

Wie Du den Inhalt dann weiter verarbeitest, ist eine ganz andere Frage und hängt davon ab, was Du denn konkret machen willst.
Moses4python
User
Beiträge: 13
Registriert: Donnerstag 16. Mai 2019, 20:43

Ich kenne nicht alle Spalten Überschriften. Wüsste auch nicht ganz, ob es überhaupt möglich ist, alle Varinaten zu kennen.

Über die Frage, ob ich csv verwenden sollte, denke ich schon länger nach. Es war schön einfach bei 4 bis 5 URLs und mit wireshark, konnte ich ja dann auch die fehlenden Daten über den http stream sehen und ergänzen. Aber nun bezweifel ich a), dass es für die Analyse noch handlebar sein wird und b) es das richtige Format ist.
Was würdest du denn empfehlen? Denn ja ich möchte alle Header Informationen speichern. Die Abweichungen liegen meistens im Detail und die muss ich für meine Studie finden.

Ist hdf5 für sowas besser geeignet? -> https://pandas.pydata.org/pandas-docs/s ... ml#io-hdf5
oder würdest du die Daten in eine SQLite Datenbank schreiben?

Naja, am Ende des Tages wäre es cool eine Art Bot Detector zu haben. Die meisten Studien Frameworks die ich kenne, legen den Fokus auf Fingerprinting in Verbindung mit JavaScript (vgl. FPDetector, OpenWPM etc.). Ich versuche vorher anzusetzen, bevor die scripts geladen werden. Um aber heraus zufinden, warum und ob mein bot mit dem einen User-Agent erkannt und blockiert wird und mit dem anderen nicht, muss ich einerseits die Datenmenge erhöhen und andererseits soviel wie möglich automatisieren... Ich bin für alle Ideen offen und dankbar.
Antworten