2010-06-17 2 views
3

J'utilise google site pour récupérer des informations météorologiques, je veux trouver des valeurs entre les balises XML. Code suivant me donner les conditions météorologiques d'une ville, mais je ne peux pas obtenir d'autres paramètres tels que la température et, si possible, expliquer travail de fonction split implicite dans le code:Comment implémenter python pour trouver de la valeur entre balises xml?

import urllib 

def getWeather(city): 

    #create google weather api url 
    url = "http://www.google.com/ig/api?weather=" + urllib.quote(city) 

    try: 
     # open google weather api url 
     f = urllib.urlopen(url) 
    except: 
     # if there was an error opening the url, return 
     return "Error opening url" 

    # read contents to a string 
    s = f.read() 

    # extract weather condition data from xml string 
    weather = s.split("<current_conditions><condition data=\"")[-1].split("\"")[0] 

    # if there was an error getting the condition, the city is invalid 


    if weather == "<?xml version=": 
     return "Invalid city" 

    #return the weather condition 
    return weather 

def main(): 
    while True: 
     city = raw_input("Give me a city: ") 
     weather = getWeather(city) 
     print(weather) 

if __name__ == "__main__": 
    main() 

Merci

+0

Voir aussi la http://stackoverflow.com/questions/3106480/ associée pour une solution basée sur XML parseurs utiliser –

Répondre

0

Eh bien, va ici - une solution d'analyseur non complet pour votre particulier cas:

import urllib 

def getWeather(city): 
    ''' given city name or postal code, 
     return dictionary with current weather conditions 
    ''' 
    url = 'http://www.google.com/ig/api?weather=' 
    try: 
     f = urllib.urlopen(url + urllib.quote(city)) 
    except: 
     return "Error opening url" 
    s = f.read().replace('\r','').replace('\n','') 
    if '<problem' in s: 
     return "Problem retreaving weather (invalid city?)" 

    weather = s.split('</current_conditions>')[0] \ 
       .split('<current_conditions>')[-1] \ 
       .strip('</>')      
    wdict = dict(i.split(' data="') for i in weather.split('"/><')) 
    return wdict 

et exemple d'utilisation:

>>> weather = getWeather('94043') 
>>> weather 
{'temp_f': '67', 'temp_c': '19', 'humidity': 'Humidity: 61%', 'wind_condition': 'Wind: N at 21 mph', 'condition': 'Sunny', 'icon': '/ig/images/weather/sunny.gif'} 
>>> weather['humidity'] 
'Humidity: 61%' 
>>> print '%(condition)s\nTemperature %(temp_c)s C (%(temp_f)s F)\n%(humidity)s\n%(wind_condition)s' % weather 
Sunny 
Temperature 19 C (67 F) 
Humidity: 61% 
Wind: N at 21 mph 

PS. Notez qu'un changement assez banal dans le format de sortie de Google va casser ceci - disons s'ils devaient ajouter des espaces ou des onglets supplémentaires entre les balises ou les attributs. Ce qu'ils évitent de réduire la taille de la réponse http. Mais s'ils le faisaient, nous devions nous familiariser avec les expressions régulières et re.split()

PPS. comment str.split(sep) fonctionne est expliqué dans la documentation, voici un extrait: Retourne une liste des mots de la chaîne, en utilisant sep comme chaîne de délimitation. ... L'argument sep peut comporter plusieurs caractères (par exemple, '1 <> 2 <> 3'.split (' <> ') renvoie [' 1 ',' 2 ',' 3 ']).Donc, 'text1<tag>text2</tag>text3'.split('</tag>') nous donne ['text1<tag>text2', 'text3'], puis [0] ramasse le 1er élément 'text1<tag>text2', puis nous nous séparons et ramasser 'text2' qui contient les données qui nous intéressent. Très banal vraiment.

+0

Pouvez-vous expliquer ou un lien comment ce .split ("..........") [0] \ ... Je veux dire la logique derrière cela sera utile .. Merci –

+0

@Harshit Sharma : ok, explication ajoutée –

8

USE

A

PARSER

Vous ne pouvez pas pa rse XML en utilisant regex (es), n'essayez donc pas. Voici un start to finding an XML parser in Python. Voici un good site for learning about parsing XML in Python. MISE À JOUR: Compte tenu des nouvelles informations sur PyS60, voici le documentation for using XML du site Web de Nokia.

MISE À JOUR 2: @Nas Banov a demandé des exemples de code, donc la voici:

import urllib 

from xml.parsers import expat 

def start_element_handler(name, attrs): 
    """ 
    My handler for the event that fires when the parser sees an 
    opening tag in the XML. 
    """ 
    # If we care about more than just the temp data, we can extend this 
    # logic with ``elif``. If the XML gets really hairy, we can create a 
    # ``dict`` of handler functions and index it by tag name, e.g., 
    # { 'humidity': humidity_handler } 
    if 'temp_c' == name: 
     print "The current temperature is %(data)s degrees Celsius." % attrs 

def process_weather_conditions(): 
    """ 
    Main logic of the POC; set up the parser and handle resource 
    cleanup. 
    """ 
    my_parser = expat.ParserCreate() 
    my_parser.StartElementHandler = start_element_handler 

    # I don't know if the S60 supports try/finally, but that's not 
    # the point of the POC. 
    try: 
     f = urllib.urlopen("http://www.google.com/ig/api?weather=30096") 
     my_parser.ParseFile(f) 
    finally: 
     f.close() 

if __name__ == '__main__': 
    process_weather_conditions() 
+0

Merci pour le lien, mais je voulais vraiment savoir comment ci-dessus fonction split orks et pourquoi même dévers e utilisé pour La recherche des valeurs de balises temp_c, je suis tyro en python quand mon utilisation du module est limitée –

+0

Les expressions régulières sont prouvablement insuffisantes pour l'analyse XML générale, et voici une raison (parmi beaucoup d'autres possibles): XML peut avoir des balises arbitrairement imbriquées. Pour un seul document spécifique (pas un schéma, un document XML réel), vous pouvez parfois obtenir des valeurs utiles en utilisant des regex. Ce piratage échouera alors (généralement en production), lorsqu'il est utilisé sur un document similaire (qu'un analyseur XML aurait très bien manipulé) car le formatage est différent, ou le nouveau document contient de nouvelles données dans une nouvelle balise, etc. –

+0

vraiment?! ne peut pas utiliser regex pour analyser * any * (par rapport à * all *) genre de xml? Même en considérant que le site pour PyS60 est lié à des points "un ensemble d'expressions régulières qui peuvent être utilisées - très facilement et efficacement - pour analyser le contenu XML." ... même si nous considérons que les DTD sont basées sur des expressions régulières et que, de nos jours, regex couvre bien plus que la classe des "langues normales"? –

2

XML est des données structurées. Vous pouvez faire beaucoup mieux que l'utilisation de la manipulation de chaînes pour extraire des données à partir de. Il y a les modules sax, dom et elementree dans la bibliothèque standard ainsi que la bibliothèque de haute qualité lxml qui peut faire votre travail pour vous de manière beaucoup plus fiable.

+0

En fait, je suis limité à l'utilisation du module car je programme en PyS60 Module –

+0

sax, dom et elementree font partie de la distribution standard. Dans tous les cas, l'analyse syntaxique basée sur les chaînes de XML va se casser et votre code ne pourra pas vraiment survivre dans la nature. –

4

Je suggère d'utiliser un analyseur XML, comme Hank Gay l'a suggéré. Ma suggestion personnelle serait lxml, car je l'utilise actuellement sur un projet et elle étend l'interface ElementTree très utilisable déjà présente dans la lib standard (xml.etree). Lxml inclut un support supplémentaire pour xpath, xslt et diverses autres fonctionnalités qui font défaut dans le module ElementTree standard. Quel que soit votre choix, un analyseur XML est de loin la meilleure option, car vous serez capable de traiter le document XML comme un objet Python. Cela signifie que votre code serait quelque chose comme:

# existing code up to... 
s = f.read() 
import lxml.etree as ET 
tree = ET.parse(s) 
current = tree.find("current_condition/condition") 
condition_data = current.get("data") 
weather = condition_data 
return weather 
+0

Appréciez votre réponse, mais je suis en train de programmer dans PyS60 et j'ai besoin d'effectuer une tâche avec une utilisation limitée du module –

+0

Eh bien, vous pouvez facilement faire cette même fonctionnalité en utilisant le module xml.etree dans la bibliothèque standard. Vous n'aurez rien à installer. Un peu de googling montre que ce module semble être inclus dans le sous-ensemble Py60: http://pys60.garage.maemo.org/doc/lib/module-xml.etree.ElementTree.html – nearlymonolith

+0

Ok, j'ai essayé d'importer cElementTree, Je suppose que cela aidera, confirmera après la mise en œuvre. Merci encore –

Questions connexes