Seite 1 von 1
minidom Ergebnis filtern
Verfasst: Freitag 18. März 2016, 21:36
von sveni_lee
Ich habe eiene xml-Abrage die eine große Anzahl von Ergebnissen liefert.
Code: Alles auswählen
#!/usr/bin/env python
# coding: utf8
from xml.dom import minidom
import urllib
staffel = 1
episode = 10
def get_detail_thetvdb():
url_str="http://thetvdb.com/api/DECE3B6B5464C552/series/72108/all/de.xml"
xml_str = urllib.urlopen(url_str).read()
xmldoc = minidom.parseString(xml_str)
episodes_detail = xmldoc.getElementsByTagName("Episode")
for Episode in episodes_detail:
epiid_tvdb = Episode.getElementsByTagName("id")[0]
epino_tvdb = Episode.getElementsByTagName("EpisodeNumber")[0]
seano_tvdb = Episode.getElementsByTagName("SeasonNumber")[0]
epidesc_tvdb = Episode.getElementsByTagName("Overview")
print("epiid_tvdb:%s, pino_tvdb:%s, seano_tvdb:%s" %
(epiid_tvdb.firstChild.data, epino_tvdb.firstChild.data, seano_tvdb.firstChild.data))
get_detail_thetvdb()
Ergebis (Auszug):
Code: Alles auswählen
epiid_tvdb:74098, pino_tvdb:1, seano_tvdb:1
epiid_tvdb:74099, pino_tvdb:2, seano_tvdb:1
epiid_tvdb:74100, pino_tvdb:3, seano_tvdb:1
epiid_tvdb:74101, pino_tvdb:4, seano_tvdb:1
epiid_tvdb:74102, pino_tvdb:5, seano_tvdb:1
epiid_tvdb:74103, pino_tvdb:6, seano_tvdb:1
epiid_tvdb:74104, pino_tvdb:7, seano_tvdb:1
epiid_tvdb:74105, pino_tvdb:8, seano_tvdb:1
epiid_tvdb:74106, pino_tvdb:9, seano_tvdb:1
epiid_tvdb:74107, pino_tvdb:10, seano_tvdb:1
epiid_tvdb:74108, pino_tvdb:11, seano_tvdb:1
epiid_tvdb:74109, pino_tvdb:12, seano_tvdb:1
epiid_tvdb:74110, pino_tvdb:13, seano_tvdb:1
epiid_tvdb:74111, pino_tvdb:14, seano_tvdb:1
epiid_tvdb:74112, pino_tvdb:15, seano_tvdb:1
epiid_tvdb:74113, pino_tvdb:16, seano_tvdb:1
epiid_tvdb:74114, pino_tvdb:17, seano_tvdb:1
epiid_tvdb:74115, pino_tvdb:18, seano_tvdb:1
epiid_tvdb:74116, pino_tvdb:19, seano_tvdb:1
epiid_tvdb:74117, pino_tvdb:20, seano_tvdb:1
epiid_tvdb:74118, pino_tvdb:21, seano_tvdb:1
epiid_tvdb:74119, pino_tvdb:22, seano_tvdb:1
epiid_tvdb:74120, pino_tvdb:23, seano_tvdb:1
epiid_tvdb:74121, pino_tvdb:1, seano_tvdb:2
epiid_tvdb:74122, pino_tvdb:2, seano_tvdb:2
epiid_tvdb:74123, pino_tvdb:3, seano_tvdb:2
epiid_tvdb:74124, pino_tvdb:4, seano_tvdb:2
epiid_tvdb:74125, pino_tvdb:5, seano_tvdb:2
epiid_tvdb:74126, pino_tvdb:6, seano_tvdb:2
epiid_tvdb:74127, pino_tvdb:7, seano_tvdb:2
epiid_tvdb:74128, pino_tvdb:8, seano_tvdb:2
epiid_tvdb:74129, pino_tvdb:9, seano_tvdb:2
Ich möchte aber beispielweise nur die Eintrag haben, bei dem bspw. seano_tvdb=1 und pino_tvdb=10 ist
bekomme ich aber nicht hin...
da ich seano_tvdb.firstChild.data irgendwie nicht in eine if / else Fuktion hineinbekomme..
Re: minidom Ergebnis filtern
Verfasst: Freitag 18. März 2016, 22:07
von BlackJack
@sveni_lee: Ich würde Minidom durch die ElementTree-API austauschen und da dann am besten auch gleich `lxml.etree` statt des Moduls aus der Standardbibliothek. Dann kann man XPath verwenden.
Re: minidom Ergebnis filtern
Verfasst: Samstag 19. März 2016, 18:20
von Sirius3
@sveni_lee: wo ist das Problem? if solltest Du ja schon kennen?
Code: Alles auswählen
def get_detail_thetvdb():
url_str="http://thetvdb.com/api/DECE3B6B5464C552/series/72108/all/de.xml"
episodes = ET.parse(urllib.urlopen(url_str))
for episode in episodes.iterfind('.//Episode'):
id = int(episode.findtext('id'))
episode_number = int(episode.findtext('EpisodeNumber'))
season_number = int(episode.findtext('SeasonNumber'))
overview = episode.findtext('Overview')
if staffel == season_number and episode == episode_number:
print(overview)
Re: minidom Ergebnis filtern
Verfasst: Montag 21. März 2016, 10:16
von sveni_lee
I hab's jetzt mit viel googeln hinbekommen...
Code: Alles auswählen
#!/usr/bin/env python
# coding: utf8
from xml.dom import minidom
import urllib
staffel = "13"
episode ="7"
def get_detail_thetvdb():
url_str="http://thetvdb.com/api/DECE3B6B5464C552/series/72108/all/de.xml"
xml_str = urllib.urlopen(url_str).read()
xmldoc = minidom.parseString(xml_str)
episodes_detail = xmldoc.getElementsByTagName("Episode")
for Episode in episodes_detail:
if Episode.getElementsByTagName('SeasonNumber')[0].firstChild.nodeValue == staffel and Episode.getElementsByTagName('EpisodeNumber')[0].firstChild.nodeValue == episode:
epiid_tvdb = Episode.getElementsByTagName("id")[0].firstChild.nodeValue
epidesc_tvdb = Episode.getElementsByTagName("Overview")[0].firstChild.nodeValue.encode('utf-8')
print epiid_tvdb
print epidesc_tvdb
break
get_detail_thetvdb()
Re: minidom Ergebnis filtern
Verfasst: Montag 21. März 2016, 10:41
von Sirius3
@sveni_lee: ich frage mich, was es da zu googeln gibt? Dass ein String nicht gleich einer Zahl ist, sollte doch klar sein. Du solltest unbedingt lernen, was Funktionsargumente sind, url_str, staffel und episode sollten alle Argumente von get_detail_thetvdb sein. Zudem fehlt noch ein sinnvoller Rückgabewert. Ich hoffe Du siehst anhand meines Beispiels, dass ElementTree die deutlich schönere API hat als minidom.
Re: minidom Ergebnis filtern
Verfasst: Dienstag 22. März 2016, 08:00
von sveni_lee
ich habe es jetzt so gelöst:
Code: Alles auswählen
def get_detail_thetvdb(imdbnumber, staffel, episode):
url_str="http://thetvdb.com/api/DECE3B6B5464C552/series/"+imdbnumber+"/all/de.xml"
xml_str = urllib.urlopen(url_str).read()
xmldoc = minidom.parseString(xml_str)
episodes_detail = xmldoc.getElementsByTagName("Episode")
for Episode in episodes_detail:
try:
if Episode.getElementsByTagName('SeasonNumber')[0].firstChild.nodeValue == staffel and Episode.getElementsByTagName('EpisodeNumber')[0].firstChild.nodeValue == episode:
epiid = Episode.getElementsByTagName("id")[0].firstChild.nodeValue
epidesc = Episode.getElementsByTagName("Overview")[0].firstChild.nodeValue
rating = Episode.getElementsByTagName("Rating")[0].firstChild.nodeValue
firstaired = Episode.getElementsByTagName("FirstAired")[0].firstChild.nodeValue
return {'epiid':epiid, 'epidesc':epidesc, 'rating':rating, 'firstaired':firstaired}
break
except:
return 0
Code: Alles auswählen
details = get_detail_thetvdb(imdbnumber, staffel, episode)
if (details ==0):
debug("Episode nicht in TheTVDB")
details = get_SerienDetails_Wunschliste(detailurl)
epidesc = details['desc']
rating = details['rating']
firstaired = details['oirg_erst']
thumbUrl = details['pic_path']
else:
epiid = details['epiid']
epidesc = details['epidesc']
rating = details['rating']
firstaired = details['firstaired']
thumbUrl = "http://www.thetvdb.com/banners/episodes/"+imdbnumber+"/"+epiid+".jpg"
liefert mir das gewünschte Ergebnis
Re: minidom Ergebnis filtern
Verfasst: Dienstag 22. März 2016, 08:54
von Sirius3
@sveni_lee: was soll denn das try-except bewirken? Ein nacktes except ist (fast) nie sinnvoll, weil damit alle Fehler (auch manche Programmierfehler) verdeckt werden, so dass die Fehlersuche quasi unmöglich wird. Was soll das return 0? Eine Funktion sollte praktischer Weise nur einen Typ (oder None) als Rückgabewert haben, damit man sinnvoll mit dem Ergebnis weiterarbeiten kann. Hier wäre es besser überhaupt nichts zurückzugeben, sondern die Exception einfach nach oben durchzureichen, dann weiß der Aufrufer genauso, dass ein Fehler aufgetreten ist und hat zusätzlich noch die Möglichkeit darauf individuell zu reagieren. Das break nach return ist überflüssig. Was passiert, wenn Episode oder Season gar nicht gefunden werden?
Die Einrückung ist falsch, es wird immer mit 4 Leerzeichen pro Ebene eingerückt. Im übrigen bin ich immer noch der Meinung, dass ElementTree die klarere API hat. Lerne lieber gleich den eleganteren Weg, Du willst danach minidom nie wieder anfassen.
Im zweiten Teil sind die Klammern um die if-Bedingung überflüssig. Das würde man auch besser mit einem exception-Handling machen.
Re: minidom Ergebnis filtern
Verfasst: Dienstag 22. März 2016, 12:03
von sveni_lee
Sirius3 hat geschrieben:was soll denn das try-except bewirken? Ein nacktes except ist (fast) nie sinnvoll, weil damit alle Fehler (auch manche Programmierfehler) verdeckt werden, so dass die Fehlersuche quasi unmöglich wird. Was soll das return 0? Eine Funktion sollte praktischer Weise nur einen Typ (oder None) als Rückgabewert haben, damit man sinnvoll mit dem Ergebnis weiterarbeiten kann.
Ich hatte folgende Überlegung: es ist ja durchaus möglich, dass keine Details auf TheTVDB gefunden werden, dann wird eine Null zurück gegeben. Wenn der wert == 0 ist werden die details woanders hergeholt... ich könnte an der Stelle sicher auch ein None verwenden...
Re: minidom Ergebnis filtern
Verfasst: Dienstag 22. März 2016, 13:03
von Sirius3
@sveni_lee: dass keine Details da sind, ist eine Ausnahme und daher solltest Du Exceptions verwenden.
Re: minidom Ergebnis filtern
Verfasst: Mittwoch 23. März 2016, 08:33
von sveni_lee
okay... danke für den Hinweiß...
so ganz habe ich das noch nicht verstanden, meinst Du das in der Form?
Code: Alles auswählen
def get_detail_thetvdb(imdbnumber, staffel, episode):
url_str="http://thetvdb.com/api/DECE3B6B5464C552/series/"+imdbnumber+"/all/de.xml"
xml_str = urllib.urlopen(url_str).read()
xmldoc = minidom.parseString(xml_str)
episodes_detail = xmldoc.getElementsByTagName("Episode")
for Episode in episodes_detail:
try:
if Episode.getElementsByTagName('SeasonNumber')[0].firstChild.nodeValue == staffel and Episode.getElementsByTagName('EpisodeNumber')[0].firstChild.nodeValue == episode:
epiid = Episode.getElementsByTagName("id")[0].firstChild.nodeValue
epidesc = Episode.getElementsByTagName("Overview")[0].firstChild.nodeValue
rating = Episode.getElementsByTagName("Rating")[0].firstChild.nodeValue
firstaired = Episode.getElementsByTagName("FirstAired")[0].firstChild.nodeValue
return {'epiid':epiid, 'epidesc':epidesc, 'rating':rating, 'firstaired':firstaired}
break
except ValueError:
return False
Re: minidom Ergebnis filtern
Verfasst: Mittwoch 23. März 2016, 09:50
von Sirius3
@sveni_lee: nein, ich meine das so:
Code: Alles auswählen
def get_detail_thetvdb(imdbnumber, staffel, episode):
url_str="http://thetvdb.com/api/DECE3B6B5464C552/series/%s/all/de.xml" % imdbnumber
episodes = ET.parse(urllib.urlopen(url_str))
for episode in episodes.iterfind('.//Episode'):
episode_number = episode.findtext('EpisodeNumber')
season_number = episode.findtext('SeasonNumber')
if staffel == season_number and episode == episode_number:
id = int(episode.findtext('id'))
overview = episode.findtext('Overview')
rating = episode.findtext("Rating")
firstaired = episode.findtext("FirstAired")
return {
'epiid':id,
'epidesc':overview,
'rating':rating,
'firstaired':firstaired,
'thumb_url': "http://www.thetvdb.com/banners/episodes/%s/%s.jpg" % (imdbnumber, id)
}
raise KeyError('not found')
def get_details(imdbnumber, staffel, episode):
try:
details = get_detail_thetvdb(imdbnumber, staffel, episode)
except KeyError:
debug("Episode nicht in TheTVDB")
details = get_SerienDetails_Wunschliste(detailurl)
return details
get_SerienDetails_Wunschliste sollte natürlich ein gleich strukturiertes Wörterbuch zurückgeben wie get_detail_thetvdb, denn es ist doch unnötiger Mehraufwand, erst ein Wörterbuch zu erstellen, um es danach noch einmal umkopieren zu müssen.