import json from gzip import GzipFile from os.path import basename, join from urllib.error import URLError from urllib.parse import urlparse from urllib.request import Request, urlopen class UrlReader(object): def __init__(self, _url): self.url = _url def openUrl(self): """ Öffnet eine URL-Verbindung, fragt GZIP-Kompression an und gibt das Response-Objekt zurück :return: Response-Objekt oder None im Fehlerfall """ print("openURL: url: \"%s\"" % (self.url,)) try: request = Request(self.url) request.add_header('Accept-Encoding', 'gzip') response = urlopen(request) print("openURL: Verbindung hergestellt") return response except URLError as e: # auch HTTPError print("openURL: FEHLER: " + str(e)) return None # Fehler def getDataResponse(self): """ Benutzt openUrl und gibt die (entpackten) Daten zurück. :return: (entpackte) Daten oder None im Fehlerfall """ print("getDataResponse: url: \"%s\"" % (self.url,)) response = self.openUrl() if response is None: print("getDataResponse: FEHLER: Kein Response-Objekt erhalten") return None try: if response.headers['Content-Encoding'] == 'gzip': print("getDataResponse: Empfange GZIP Daten...") daten = GzipFile(fileobj=response).read() else: print("getDataResponse: Empfange unkomprimierte Daten...") daten = response.read() print("getDataResponse: Daten empfangen") return daten except OSError as e: print("getDataResponse: FEHLER: " + str(e)) return None # Kein Erfolg def getJsonResponse(self): """ Benutzt getDataResponse zum Herunterladen, interpretiert die Daten als JSON und gibt das Ergebnis zurück. :return: Geparste JSON Daten oder None im Fehlerfall """ print("getJsonResponse: url=" + self.url) daten = self.getDataResponse() if daten is None: print("getJsonResponse: FEHLER: Keine Daten erhalten") return None try: print("getJsonResponse: Lese JSON...") parsed = json.loads(daten) print("getJsonResponse: JSON gelesen") return parsed except ValueError as e: # JSONDecodeError print("getJsonResponse: ValueError: " + str(e)) except TypeError as e: # JSONDecodeError print("getJsonResponse: TypeError: " + str(e)) return None # Kein Erfolg def _dateiname_von_url(self): result = urlparse(self.url) dateiname = basename(result.path) return dateiname def getFileResponse(self, pfad): """ Benutzt getDataResponse zum Herunterladen, schreibt die Daten in eine Datei und gibt ihren Pfad zurück (gegebenes Verzeichnis + basename des URL-Pfades). :param pfad: Verzeichnis in dem die Datei gespeichert werden soll. :return: Pfad der erzeugten Datei oder None im Fehlerfall """ print("getFileResponse: url: \"%s\"" % (self.url,)) print("getFileResponse: pfad: \"%s\"" % (pfad,)) daten = self.getDataResponse() if daten is None: print("getFileResponse: FEHLER: Keine Daten erhalten") return None dateiname = self._dateiname_von_url() print("getFileResponse: dateiname: \"%s\"" % (dateiname,)) dateipfad = join(pfad, dateiname) print("getFileResponse: dateipfad: \"%s\"" % (dateipfad,)) try: print("getFileResponse: Schreibe Datei...") with open(dateipfad, 'wb') as datei: datei.write(daten) print("getFileResponse: Datei geschrieben") return dateipfad except OSError as e: print("getFilesResponse: FEHLER: " + str(e)) return None if __name__ == '__main__': url = "https://ia800302.us.archive.org/8/items/BennyGoodmanQuartetAndTrio/BodySoul-BennyGoodmanGeneKrupaTeddyWilsoncarnegieHall1938_64kb.mp3" print(UrlReader(url).getFileResponse(""))