Hallo
ich habe die bekommen eine Textdatei Zeile für Zeile auszulesen. Die Datei ist soll eine Apache-Logdatei simulieren.
Ich soll die IP-Adressen aus der Datei filtern und muss auch angeben wie viele IPs es insgesamt gibt.
Die IPs und die anzahl sollen dann in eine Textdatei geschrieben werden.
ich bin ein Python Anfänger. Ich denke es kann funktionieren, wenn die ich die Datei öffne, die Daten mit einer schleife auslese und in einer liste speicher.
Die Liste kann ich dann in eine Textdatei schreiben. Das Problem: ich wüsste nicht wie ich die Schleifen für das einlesen aufbauen soll. Mir fehlt dazu einfach die Syntax. habt ihr Vorschläge für die Schleife??
vielen Dank schon mal
das ist ein kleiner teil der Apache-Logdatei:
die IP-Adressen stehen immer am Anfang und nach der letzten Ziffer kommt immer --
127.0.0.1 - - [20/Nov/2008:17:38:06 +0100] "GET /joomla/installation/index.php HTTP/1.1" 200 8478
127.0.0.1 - - [20/Nov/2008:17:38:15 +0100] "GET /joomla/installation/favicon.ico HTTP/1.1" 200 1150
127.0.0.1 - - [20/Nov/2008:17:38:15 +0100] "GET /joomla/installation/template/css/template.css HTTP/1.1" 200 7375
127.0.0.1 - - [20/Nov/2008:17:38:15 +0100] "GET /joomla/media/system/js/mootools.js HTTP/1.1" 200 74404
127.0.0.1 - - [20/Nov/2008:17:38:16 +0100] "GET /joomla/installation/includes/js/installation.js HTTP/1.1" 200 598
127.0.0.1 - - [20/Nov/2008:17:38:16 +0100] "GET /joomla/installation/template/js/validation.js HTTP/1.1" 200 7137
127.0.0.1 - - [20/Nov/2008:17:38:16 +0100] "GET /joomla/installation/template/images/j_border.png HTTP/1.1" 200 213
127.0.0.1 - - [20/Nov/2008:17:38:16 +0100] "GET /joomla/installation/template/images/j_header_middle.png HTTP/1.1" 200 385
Einlesen einer Text Datei in Python
- noisefloor
- User
- Beiträge: 3854
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
... und willkommen im Forum
Dein Denkansatz ist schon mal richtig.
Zeig' doch mal deinen Code, den du probiert hast und beschreib', was nicht so funktioniert, wie du dir das vorstellst.
Wenn du das Grundlagentutorial auf docs.python.org durchgearbeitet hast, sollte die Aufgabe eigentlich problemlos lösbar sein.
Gruß, noisefloor
... und willkommen im Forum
Dein Denkansatz ist schon mal richtig.
Zeig' doch mal deinen Code, den du probiert hast und beschreib', was nicht so funktioniert, wie du dir das vorstellst.
Wenn du das Grundlagentutorial auf docs.python.org durchgearbeitet hast, sollte die Aufgabe eigentlich problemlos lösbar sein.
Gruß, noisefloor
Was hast Du schon gelernt? Was hast Du damit versucht? Zeig den Code, den Du ausprobiert hast, und beschreibe genau, was nicht so funktioniert, wie Du Dir das vorstellst.
Zum Zählen der IPs bietet sich `collections.Counter` an.
Zum Zählen der IPs bietet sich `collections.Counter` an.
-
- User
- Beiträge: 5
- Registriert: Sonntag 2. Juni 2019, 17:31
Hallo
erstmal danke an euch, dass ihr mir ein bisschen Motivation gegeben habt.
Ich hab mich mit dem split befehl auseinander gesetzt. So kann ich jetzt die IP filtern.
Lieder fehlt mir immer noch die die Quantität. zudem kann ich die IP Adressen nur in einer Liste in die txt schreiben. Aber es gibt dafür schon gute Methoden.... hab ich gesehen.
hier der code
erstmal danke an euch, dass ihr mir ein bisschen Motivation gegeben habt.
Ich hab mich mit dem split befehl auseinander gesetzt. So kann ich jetzt die IP filtern.
Lieder fehlt mir immer noch die die Quantität. zudem kann ich die IP Adressen nur in einer Liste in die txt schreiben. Aber es gibt dafür schon gute Methoden.... hab ich gesehen.
hier der code
Code: Alles auswählen
Adressen = [] #Liste für die IP adressen
daten = open('access.log','r') #Apache-Logdatei wird im lesemodus geöffnet
line = daten.readline() #einelsen einer Zeile
while line != "": # Schleife lieste die Zeilen aus
text = line.split() # IP wird aus der Zeile gefiltert
Adressen.append(text[0]) # gefilterte IP wird in die Liste eingetragen
line = daten.readline() # Schleife endet, wenn zeile leer ist
f = open('adressen.txt','w') # ausgeben der liste in eie txt
f.write(str(Adressen) +'\n')
f.close()
Gewöhn es dir gleich richtig an:
Variablennamen schreibt man klein_mit_unterstrich, Klasennamen CamelCase, Konstanten KOMPLETT_GROSS.
Such mal in der Python-Dokumentation nach dem Schlüsselwort "with" und verwende open damit.um Dateien zu öffnen.
Und dann schau dir die for-Schleife an.
Variablennamen schreibt man klein_mit_unterstrich, Klasennamen CamelCase, Konstanten KOMPLETT_GROSS.
Such mal in der Python-Dokumentation nach dem Schlüsselwort "with" und verwende open damit.um Dateien zu öffnen.
Und dann schau dir die for-Schleife an.
- noisefloor
- User
- Beiträge: 3854
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
Ergänzend so dem von sparrow gesagten:
Python kann direkt zeilenweise über eine geöffnete (Text-) Datei iterieren, du brauchst nicht über readline() oder readlines() zu gehen.
In deinem Beispeil ist das Doppelminus -- der Trenner von IP und Rest - warum spilttest du dann an Whitespaces (was `split()` macht)?
Warum speicherst du die Liste einfach als String? Das macht relativ wenig Sinn und ist blöd beim weiterverarbeiten. Wenn du in der Datei `adressen.txt` die IP-Adresse zeilenweise speichern willst, dann musst du so wie so anders vorgehen. (Stichwort: über Liste iterieren). Aktuell stünden alle IP-Adressen in einer Zeile und die Zeile ist von eckigen Klammern eingeschlossen.
Gruß, noisefloor
Ergänzend so dem von sparrow gesagten:
Python kann direkt zeilenweise über eine geöffnete (Text-) Datei iterieren, du brauchst nicht über readline() oder readlines() zu gehen.
In deinem Beispeil ist das Doppelminus -- der Trenner von IP und Rest - warum spilttest du dann an Whitespaces (was `split()` macht)?
Warum speicherst du die Liste einfach als String? Das macht relativ wenig Sinn und ist blöd beim weiterverarbeiten. Wenn du in der Datei `adressen.txt` die IP-Adresse zeilenweise speichern willst, dann musst du so wie so anders vorgehen. (Stichwort: über Liste iterieren). Aktuell stünden alle IP-Adressen in einer Zeile und die Zeile ist von eckigen Klammern eingeschlossen.
Gruß, noisefloor
@Hannes.LNG: wenn die Bedingung, wann eine while-Schleife abbrechen soll, erst innerhalb der while-Schleife feststeht (also nachdem Du eine Zeile gelesen hast), nimmt man eine while-True-Schleife mit break:
Hier aber brauchst Du gar keine while-Schleife, weil ein file-Objekt auch als Iterator fungieren kann, und daher eine for-Schleife besser ist:
Dateien, die man öffnet, sollte man auch wieder schließen, das tust Du bei `daten` nicht. Um solche Fehler erst gar nicht aufkommen zu lassen, benutze das with-Statement, das automatisch schließt:
Alle Deine Kommentare beschreiben nur, was ohnehin schon im Code steht, Kommentare sollten beschreiben, warum etwas gemacht wird. Wenn Du bessere Variablennamen verwendest, werden die Kommentare noch überflüssiger.
Deutsch und Englisch zu mischen, ist ein Stolperstein beim Lesen, am besten nur Englische Begriffe verwenden:
Die String-Repräsentation einer Liste ist nur für Debuggingzwecke gedacht, nicht dafür dass man sie in eine Text-Datei schreibt. Zum Schreiben brauchst Du wieder eine Schleife:
Zum Zählen der Vorkommnisse der IP-Adressen habe ich Dir schon `collections.Counter` vorgeschlagen.
Code: Alles auswählen
while True:
line = daten.readline()
if not line:
break
text = line.split()
Adressen.append(text[0])
Code: Alles auswählen
for line in daten:
text = line.split()
Adressen.append(text[0])
Code: Alles auswählen
with open("access.log") as daten:
for line in daten:
text = line.split()
Adressen.append(text[0])
Deutsch und Englisch zu mischen, ist ein Stolperstein beim Lesen, am besten nur Englische Begriffe verwenden:
Code: Alles auswählen
ip_addresses= []
with open("access.log") as lines:
for line in lines:
ip_address, _remains = line.split(None, 1)
ip_addresses.append(ip_address)
Code: Alles auswählen
with open("adressen.txt", "w") as output:
for ip_address in ip_addresses:
output.write("{}\n".format(ip_address))
-
- User
- Beiträge: 5
- Registriert: Sonntag 2. Juni 2019, 17:31
Danke für die Hilfe mit den for schleifen. Das hat mir schon sehr geholfen.
leider glaube ich das ich doch auf den Holzweg bin. Der counter ist für mich als Anfänger schwer zu verstehen.
Deshalb habe ich versucht die Durchläufe der Schleife zu zählen. Leider schaffe ich es nicht mal diesen wert in die txt zu schreiben.
leider glaube ich das ich doch auf den Holzweg bin. Der counter ist für mich als Anfänger schwer zu verstehen.
Deshalb habe ich versucht die Durchläufe der Schleife zu zählen. Leider schaffe ich es nicht mal diesen wert in die txt zu schreiben.
Code: Alles auswählen
ip_addresses= []
counter = 0
with open("access.log") as lines:
for line in lines:
counter += 1
ip_address, _remains = line.split(None, 1)
ip_addresses.append(ip_address)
print(counter)
output = open('adressen.txt','w')
output.writelines(str(counter))
output.close()
with open("adressen.txt", "w") as output:
for ip_address in ip_addresses:
output.write("{}\n".format(ip_address))
-
- User
- Beiträge: 5
- Registriert: Sonntag 2. Juni 2019, 17:31
"w" öffnet die Datei im Schreibmodus. Überschreibt "w" auch die Datei??
Ja. https://docs.python.org/3/library/functions.html#open
""
w: open for writing, truncating the file first
"""
""
w: open for writing, truncating the file first
"""
Kann es sein, dass Deine Aufgabenstellung lautet, die Zahl der *unterschiedlichen* IPs herauszufinden und deren Anzahl als auch eine Auflistung dieser IPs zu speichern?Hannes.LNG hat geschrieben: ↑Sonntag 2. Juni 2019, 18:02 Ich soll die IP-Adressen aus der Datei filtern und muss auch angeben wie viele IPs es insgesamt gibt.
Die IPs und die anzahl sollen dann in eine Textdatei geschrieben werden.
Code: Alles auswählen
ip_addresses = set()
with open("access.log") as lines:
for line in lines:
ip_address, _remains = line.split(None, 1)
ip_addresses.add(ip_address)
# to do: save data here ...
# print number of different ips:
print(len(ip_addresses))
Die Zahl *aller* IPs herauszufinden ist trivial: dafür brauchst Du nur die Zeilen der Datei zu zählen, sofern nur gültige Einträge vorkommen.
Oder sollst Du herausfinden, wie viele *unterschiedliche* IPs vorkommen und wie oft diese *jeweils* vorkommen? Das wäre schon etwas anspruchsvoller, lässt sich aber mit dem bereits erwähnten collections.counter gut lösen.
-
- User
- Beiträge: 5
- Registriert: Sonntag 2. Juni 2019, 17:31
ja du hast recht. Ich soll tatsächlich die Häufigkeit der IPs zählen und dann mit ihrer Anzahl in einer Txt ausgeben.
- noisefloor
- User
- Beiträge: 3854
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
dann wäre eine mögliche Lösung, die auch "nur" mit Grundwissen von Python umsetzbar ist, als Datenstruktur ein Dictionary zu verwenden.
Der Schlüssel ist die IP-Adresse, der Wert die Anzahl der Vorkommen.
Womit du im Prinzip das nach programmierst, was `collections.Counter` so wie so macht. Also Übung für's Verständnis ist das aber nicht verkehrt.
Gruß, noisefloor
dann wäre eine mögliche Lösung, die auch "nur" mit Grundwissen von Python umsetzbar ist, als Datenstruktur ein Dictionary zu verwenden.
Der Schlüssel ist die IP-Adresse, der Wert die Anzahl der Vorkommen.
Womit du im Prinzip das nach programmierst, was `collections.Counter` so wie so macht. Also Übung für's Verständnis ist das aber nicht verkehrt.
Gruß, noisefloor
- __blackjack__
- User
- Beiträge: 13071
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Mit `collections.Counter` und dem `ipaddress`-Modul um sicher zu stellen, das man wirklich gültige IPs zählt:
Code: Alles auswählen
#!/usr/bin/env python3
from collections import Counter
from ipaddress import ip_address
LOG_LINES = '''\
127.0.0.1 - - [20/Nov/2008:17:38:06 +0100] "GET /joomla/installation/index.php HTTP/1.1" 200 8478
127.0.0.1 - - [20/Nov/2008:17:38:15 +0100] "GET /joomla/installation/favicon.ico HTTP/1.1" 200 1150
127.0.0.1 - - [20/Nov/2008:17:38:15 +0100] "GET /joomla/installation/template/css/template.css HTTP/1.1" 200 7375
127.0.0.1 - - [20/Nov/2008:17:38:15 +0100] "GET /joomla/media/system/js/mootools.js HTTP/1.1" 200 74404
127.0.0.1 - - [20/Nov/2008:17:38:16 +0100] "GET /joomla/installation/includes/js/installation.js HTTP/1.1" 200 598
127.0.0.1 - - [20/Nov/2008:17:38:16 +0100] "GET /joomla/installation/template/js/validation.js HTTP/1.1" 200 7137
127.0.0.1 - - [20/Nov/2008:17:38:16 +0100] "GET /joomla/installation/template/images/j_border.png HTTP/1.1" 200 213
127.0.0.1 - - [20/Nov/2008:17:38:16 +0100] "GET /joomla/installation/template/images/j_header_middle.png HTTP/1.1" 200 385
'''.splitlines(True)
def parse_line(line):
ip_part, dash, _ = line.partition(' - ')
if not dash:
raise ValueError('dash expected')
return ip_address(ip_part)
def parse_lines(log_lines):
for line in log_lines:
try:
yield parse_line(line)
except ValueError:
pass # No IP — intentionally ignored.
def create_histogram(log_lines):
return Counter(parse_lines(log_lines))
def save_histogram(filename, histogram):
with open(filename, 'w', encoding='ascii') as file:
file.writelines(
f'{address} {count}\n' for address, count in histogram.most_common()
)
def main():
histogram = create_histogram(LOG_LINES)
print(histogram)
save_histogram('test.txt', histogram)
if __name__ == '__main__':
main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman