Как реализовать Python, чтобы найти значение между тегами XML? - PullRequest
3 голосов
/ 17 июня 2010

Я использую сайт Google для получения информации о погоде, я хочу найти значения между тегами 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()

Спасибо

Ответы [ 4 ]

8 голосов
/ 17 июня 2010

USE

A

PARSER

Вы не можете анализировать XML с помощью регулярных выражений, поэтому не пытайтесь. Вот начало поиска синтаксического анализатора XML в Python . Вот хороший сайт для изучения синтаксического анализа XML в Python .

ОБНОВЛЕНИЕ: Учитывая новую информацию о PyS60, вот документация для использования XML с сайта Nokia.

ОБНОВЛЕНИЕ 2: @Nas Banov запросил пример кода, поэтому вот он:

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()
4 голосов
/ 17 июня 2010

Я бы предложил использовать парсер XML, как предложил Хэнк Гэй.Мое личное предложение будет lxml , так как в настоящее время я использую его в проекте, и это расширяет очень удобный интерфейс ElementTree, уже присутствующий в стандартном lib (xml.etree).

Lxmlвключает в себя добавленную поддержку xpath, xslt и различных других функций, которых нет в стандартном модуле ElementTree.

Независимо от того, что вы выберете, синтаксический анализатор XML является безусловно лучшим вариантом, так как вы сможете справиться сXML-документ как объект Python.Это означает, что ваш код будет выглядеть примерно так:

# 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
2 голосов
/ 17 июня 2010

XML - это структурированные данные.Вы можете сделать намного лучше, чем использовать строковые манипуляции для извлечения данных из него.В стандартной библиотеке есть модули sax , dom и elementree , а также высококачественная библиотека lxml , которая может выполнять вашу работудля вас гораздо надежнее.

0 голосов
/ 18 июня 2010

Ну, вот и все - неполное решение парсера для вашего конкретного случая:

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

и пример использования:

>>> 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Обратите внимание, что довольно тривиальное изменение в формате вывода Google сломает это - скажем, если бы они добавили дополнительные пробелы или табуляции между тегами или атрибутами.Чего они избегают, чтобы уменьшить размер http ответа.Но если бы они это сделали, нам пришлось бы знакомиться с регулярными выражениями и re.split ()

PPS.как str.split(sep) работает, объясняется в документации, вот выдержка: Возвращает список слов в строке, используя sep в качестве строки-разделителя.... Аргумент sep может состоять из нескольких символов (например, '1 <> 2 <> 3' .split ('<>') возвращает ['1', '2', '3']) ,Так что 'text1<tag>text2</tag>text3'.split('</tag>') дает нам ['text1<tag>text2', 'text3'], затем [0] берет 1-й элемент 'text1<tag>text2', затем мы разбиваемся и выбираем 'text2', который содержит данные, которые нас интересуют. Действительно банально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...