Dictionary aus Webdatei generieren

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
python64
User
Beiträge: 4
Registriert: Montag 31. Juli 2017, 17:22

Hallo,
bin relativ neu in Python und versuche eine Liste/Dictionary (assoziatives Array) aus der folgenden Webdatei zu generieren:
[codebox=html5 file=Unbenannt.html]<html><head>
<meta http-equiv="content-type" content="text/html"></head><body>{ 0: "File1.exe",
1: "File14.exe",
2: "File7.exe",
3: "File90.exe",
4: "File100.exe",
23: "File23.exe",
700: "File19.exe",
}</body></html>[/code]

Das technische herunterladen und Verarbeiten mit BS klappt gut. Im Ergebnis möchte ich die Wertepaare (0 : File1.exe....), die nicht fortlaufend sind, über eien Schleife iterieren und verarbeiten können. Wisst Ihr evtl., wie das geht?
Vielen Dank!
Zuletzt geändert von Anonymous am Dienstag 1. August 2017, 12:49, insgesamt 1-mal geändert.
Grund: Quelltext in Codebox-Tags gesetzt.
BlackJack

@python64: Wo kommen die Daten denn her? Warum ist das fast JSON aber dann in HTML verpackt und eben doch nicht ganz JSON? Kann man das nicht in einem vernünftigen Standardformat bekommen, beispielsweise JSON?
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Du müsstest mal nach einer API für die Seite suchen, also ob irgendwo json ausgeliefert wird.

Hintergrund für die Rückfrage ist, dass es mit dem json-Modul eine eigene Bibliothek in der Standardbibliothek gibt, die mit json-Objekten umgehen kann, was den Umweg über ein Abrufen und Parsen der Seite unnötig machen würde.

https://docs.python.org/3/library/json.html
python64
User
Beiträge: 4
Registriert: Montag 31. Juli 2017, 17:22

Danke für Eure Antworten!
Leider habe ich keinen Einfluss auf das Format und eine API ist mir nicht bekannt. Die Datei steht einfach so im Netz und muss verarbeitet werden.
BlackJack

@python64: Dann würde ich `ast.literaleval()` vorschlagen und hoffen das die Webseite nichts liefert was damit nicht verarbeitet werden kann.

Code: Alles auswählen

In [47]: source = '''
    ...: {  0: "File1.exe",
    ...:     1: "File14.exe",
    ...:     2: "File7.exe",
    ...:     3: "File90.exe",
    ...:     4: "File100.exe",
    ...:     23: "File23.exe",
    ...:     700: "File19.exe",
    ...: }
    ...: '''

In [48]: ast.literal_eval(source)
Out[48]: 
{0: 'File1.exe',
 1: 'File14.exe',
 2: 'File7.exe',
 3: 'File90.exe',
 4: 'File100.exe',
 23: 'File23.exe',
 700: 'File19.exe'}
python64
User
Beiträge: 4
Registriert: Montag 31. Juli 2017, 17:22

Vielen Dank! Habs jetzt anders gelöst, vermutlich unelegant, aber funktioniert:

<body> mir BS auslesen und dann den String zurechtbasteln:

Code: Alles auswählen

 def getSite(url):  
 try:
        bsObj = BeautifulSoup(html.read(), "html.parser")
        allText = bsObj.find('body')
    except AttributeError as e:
        return None
    return allText
allText = getSite(http://...)
......
    str1 = allText.text
    str1 = str1.replace("\t", "")
    str1 = str1.replace("\r\n", "")
    str1 = str1.replace(":", " :")
    str1 = str1.replace(",", ", ")
    str1 = str1.replace(", }", "}")
    str1 = re.sub(r'(\d*) :', r'"\1":', str1)
    resp = json.loads(str1)
    print(resp["1"])
>>File14.exe
Zuletzt geändert von Anonymous am Dienstag 1. August 2017, 19:26, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@python64: Was soll denn in den zwei Zeilen zu einem `AttributeError` führen und wieviel Sinn macht es in dem Fall `None` als Ergebnis zu liefern? Entweder liefert man da beispielsweise eine leere Zeichenkette, oder noch besser, man meldet das als Ausnahme weiter. Eventuell sogar in dem man die vorhandene Ausnahme einfach gar nicht in der Funktion behandelt.

`Obj` ist ein unsinniger Namenszusatz. *Alles* was man in Python an einen Namen binden kann ist ein Objekt. Also könnte man an *jeden* Namen `Obj` anhängen, aber es gibt halt bei keinem Namen einen Mehrwert, denn das es ein Objekt ist, ist ja eh klar. ;-)

Warum gibt die Funktion das `Element`-Objekt zurück und nicht einfach den Text? Und `getSite()` verspricht mehr als da passiert. Eine Website ist die Gesamtheit aller zusammengehörenden Webseiten hinter einer Domain.

Einige Namen halten sich nicht an die Namenschreibweise aus dem Style Guide for Python Code und Abkürzungen und unsinnige angehängte Nummern sollte man bei Namen nicht verwenden.

Unelegant ist das eine, aber das sieht nicht wirklich robust aus. Zumal der `ast.literal_eval()`-Aufruf wesentlich kürzer ist.
python64
User
Beiträge: 4
Registriert: Montag 31. Juli 2017, 17:22

Code: Alles auswählen

from urllib.request import urlopen, Request
from urllib.error import HTTPError
from bs4 import BeautifulSoup
import ast

def getUrl(url):
    try:
        html = urlopen(Request(url))
    except HTTPError as e:
        print(e)
        return None
    try:
        bs = BeautifulSoup(html.read(), "html.parser")
        allText = bs.find('body')
    except AttributeError as e:
        print(e)
        return None
    return allText.text

allText = getUrl("http://....")
if allText == None:
    print("Generator could not be found")
else:
    dict = ast.literal_eval(allText)
    print(dict[0])
Stimmt, ist wirklich kürzer und robuster...Danke Dir!
Zuletzt geändert von Anonymous am Mittwoch 2. August 2017, 15:24, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Schau Dir mal das requests-Modul an, ist einfacher in der Handhabung als das urllib-Teil...

http://docs.python-requests.org/en/master/
Antworten