Seite 1 von 1

RSS Parser Fehler Unicode/Latin

Verfasst: Dienstag 7. August 2007, 10:52
von andreaszdw
Folgendes Programm ergibt Fehler:

Code: Alles auswählen

import urllib2
from xml.dom.minidom import parse, parseString

def parseFeed(url):
    request=urllib2.Request(url)
    request.add_header('User-Agent', 'Mozilla/4.0 (compatible; MSIE 5.5;Windows NT')
    opener = urllib2.build_opener()
    data = opener.open(request).read()
    return data
   
def parseRssDoc(doc):
    rootNode = doc.documentElement
    channelNode = rootNode.firstChild
    itemNodeList = channelNode.getElementsByTagName('item')
    for item in itemNodeList:
        rssItemNodes = item.childNodes
        try:
            for n in rssItemNodes:
                prefix = ""
                if n.nodeName == 'title' or n.nodeName == 'link':
                    print "prefix=%s val=%s" % (n.nodeName, n.firstChild.nodeValue)
        except Exception, e:
            print "*************"
            print "WARN: unable to parse node"
            print e
            print "*************"
	    

def parse(url):
    data = parseFeed(url)
    doc = parseString(data)
    parseRssDoc(doc)
   
if __name__ == '__main__':
    print "running"
    initialFeed = 'http://www.spiegel.de/schlagzeilen/rss/0,5291,20,00.xml'
    #initialFeed = 'http://news.google.com/nwshp?sourceid=navclient&ie=UTF-8&output=rss'
    parse(initialFeed)
    print "done"
Hier die Ausgabe:

>>>
running

Traceback (most recent call last):
File "C:\burn\rssparser.py", line 38, in <module>
parse(initialFeed)
File "C:\burn\rssparser.py", line 32, in parse
parseRssDoc(doc)
File "C:\burn\rssparser.py", line 14, in parseRssDoc
itemNodeList = channelNode.getElementsByTagName('item')
AttributeError: Text instance has no attribute 'getElementsByTagName'
>>>

Wenn ich den auskommentierten String (google) parse, kommt kein Fehler.

Liegt vielleicht ein Unicode/Latin-Fehler vor?

Was kann ich machen?

MfG
Andreas

Verfasst: Dienstag 7. August 2007, 15:56
von BlackJack
Der erste Knoten in dem Dokument ist kein <channel>-Tag, sondern ein Textknoten und Textknoten haben keine `getElementsByTagName()`-Methode. Das sagt die Fehlermeldung recht deutlich.

Du musst halt sichergehen, dass Du auch den Knoten herausfischst, den Du wirklich haben willst und nicht einfach den ersten.

Das RSS sieht so aus:

Code: Alles auswählen

<?xml version="1.0" encoding="iso-8859-1"?>
<rss version="0.91">
<channel>

                   <title>SPIEGEL ONLINE - Politik</title>
        <link>http://www.spiegel.de/politik/0,1518,,00.html</link>
        <description>Schneller wissen, was wichtig ist</description>
        <language>de</language>
Der erste Kindknoten unter dem <rss>-Tag ist ein Textknoten, der den Zeilenumbruch vor dem <channel>-Tag enthält.

Verfasst: Donnerstag 8. April 2010, 12:24
von twist
Hallo,
ich hab den selben Fehler
beim Knoten s.u. <startzeile>
von dem ich alle <condition>
Knoten haben möchte die er inne hält.
und ich bin mir sicher das dieser Knoten der ist den ich gerade haben möchte.

kann man irgentwie den Knoten in ELEMENT_NODE umwandeln?

Code: Alles auswählen

for c0 in self.m_doc.childNodes:
			if(c0.nodeType == c0.ELEMENT_NODE):
				if(line.find(c0.getAttribute("start"))>=0):
					self.m_Record=True
				if(not self.m_Record):
					return -1
				if(line.find(c0.getAttribute("end"))>=0):
					self.m_Record=False
		#Bestimmen des typs der uebergebenen Zeile an hand von m_doc
				sep=c0.getAttribute("sep")
				pList=line.split(sep)
				if(len(pList)==0):
					return -1
				dType=None
				for c1 in c0.childNodes:
					isNot=0
					test=c1.nodeType
					for c2 in c1.GetElementsByTagName("condition"):

Code: Alles auswählen

<datensatz0 start="START" end="ENDE" sep=";" >
	<startzeile>
		<condition feld="0" type="string" value="START" />
		<data name="start" type="string" />
		<data name="dsSatus" type="string" />
		<data name="dNr" type="int" />
		<data name="messTyp" type="string" />
		<data name="rNr" type="int" />
		<data name="rTyp" type="int" />
		<data name="tNr" type="int" />
		<data name="ergebnis" type="string" />
		<data name="datum" type="date"  typeformat="%Y.%m.%d" />
		<data name="uhrzeit" type="time" typeformat="%H:%M:%S" />
	</startzeile >
	<endzeile>
		<condition feld="0" type="string" value="ENDE" />
		<data endMaker="string" />
		<data dNr="int" />
	</endzeile >
</datensatz0 >

Verfasst: Donnerstag 8. April 2010, 12:27
von twist
ok hat sich erledigt.
habd die Letzte zeile eben erst endeckt!
sorry

Verfasst: Donnerstag 8. April 2010, 14:17
von jens
warum nicht http://feedparser.org/ verwenden?

Verfasst: Donnerstag 8. April 2010, 14:49
von BlackJack
@twist: Der Quelltextschnippsel sieht *sehr* unpythonisch aus. Bist Du sicher dass Du in Python programmieren willst!?

Was sollen die `m_`-Präfixe? Die verwendet man in C++ häufig um Membervariablen von lokalen Namen zu unterscheiden. Da man in Python aber zwingend ein `self` vor Attribute schreiben muss, ist es ziemlich sinnfrei zusätzlich ein `m_` vor den Namen zu klatschen.

``return -1`` sieht nach "Fehlercode" aus!? In Python braucht man sich keine Gedanken um "exception safety" machen und sollte Ausnahmen statt speziellen Fehlerwerten verwenden. Da kann man für die verschiedenen Fälle unterschiedliche Klassen verwenden oder zumindest in der Nachricht detailliertere Informationen unterbringen.

Klammern um Bedingungen sind nicht nötig. Die `find()`-Aufrufe solltest Du besser mit dem ``in``-Operator ausdrücken. Das ist kürzer und deutlicher.

Die Namensgebung ist nicht PEP8-konform und manche Namen könnten besser gewählt werden. `pList` zum Beispiel ist ziemlich nichtssagend. Ein Name sollte die Bedeutung reflektieren und nicht den Typ.

Warum verwendest Du nicht ElementTree? Das gehört mittlerweile zur Standardbibliothek und ist IMHO angenehmer als die DOM-API.

Nochwas zum XML: Was soll die 0 am Ende von <datensatz…>? Das sind doch nicht etwa durchnummerierte Tagnamen? Wer hat das denn verbrochen?

@jens: Das hilft twist nicht weiter, weil sein XML so gar nicht nach Newsfeed aussieht, und der Rest vom Thread ist schon etwas älter. :-)