diff --git a/lesson08/home_work/export_openweather.py b/lesson08/home_work/export_openweather.py index 0ae937519..39985c9fc 100644 --- a/lesson08/home_work/export_openweather.py +++ b/lesson08/home_work/export_openweather.py @@ -1,24 +1,108 @@ - -""" OpenWeatherMap (экспорт) - -Сделать скрипт, экспортирующий данные из базы данных погоды, -созданной скриптом openweather.py. Экспорт происходит в формате CSV или JSON. - -Скрипт запускается из командной строки и получает на входе: - export_openweather.py --csv filename [<город>] - export_openweather.py --json filename [<город>] - export_openweather.py --html filename [<город>] - -При выгрузке в html можно по коду погоды (weather.id) подтянуть -соответствующие картинки отсюда: http://openweathermap.org/weather-conditions - -Экспорт происходит в файл filename. - -Опционально можно задать в командной строке город. В этом случае -экспортируются только данные по указанному городу. Если города нет в базе - -выводится соответствующее сообщение. - -""" - -import csv -import json + +""" OpenWeatherMap (экспорт) + +Сделать скрипт, экспортирующий данные из базы данных погоды, +созданной скриптом openweather.py. Экспорт происходит в формате CSV или JSON. + +Скрипт запускается из командной строки и получает на входе: + export_openweather.py --csv filename [<город>] + export_openweather.py --json filename [<город>] + export_openweather.py --html filename [<город>] + +При выгрузке в html можно по коду погоды (weather.id) подтянуть +соответствующие картинки отсюда: http://openweathermap.org/weather-conditions + +Экспорт происходит в файл filename. + +Опционально можно задать в командной строке город. В этом случае +экспортируются только данные по указанному городу. Если города нет в базе - +выводится соответствующее сообщение. + +""" + +import csv +import json +import sys +import sqlite3 + +db_weather = 'weather.db' +csv.register_dialect('excel-semicolon', delimiter=';') +#encoding = 'utf-8' +encoding = 'windows-1251' + + +def open_db(): + with sqlite3.connect(db_weather) as conn: + cur = conn.cursor() + cur.execute("SELECT * FROM Погода") + column_names = [description[0] for description in cur.description] + table_content = cur.fetchall() + content = [] + for _ in range(len(table_content)): + content.append(dict(zip(column_names, table_content[_]))) + return content, column_names + + +def export_json(fname, c_name=None): + content, column_names = open_db() + fname = fname + '.json' + write_content = [] + if c_name: + for elem in content: + if c_name in elem.values(): + write_content.append(elem) + else: + write_content = content + if len(write_content) == 0: + print('Данных нет в базе') + exit() + with open(fname, 'w', encoding='UTF8') as write_json: + json.dump(write_content, write_json, ensure_ascii=False, indent=2) + + +def export_csv(fname, c_name=None): + content, column_names = open_db() + fname = fname + '.csv' + write_content = [] + if c_name: + for elem in content: + if c_name in elem.values(): + write_content.append(elem) + else: + write_content = content + if len(write_content) == 0: + print('Данных нет в базе') + exit() + with open(fname, 'w', encoding=encoding) as csvfile: + writer = csv.DictWriter(csvfile, fieldnames=column_names, dialect='excel-semicolon') + headers = {name: name for name in column_names} + writer.writerow(headers) + for _ in range(len(write_content)): + writer.writerow(write_content[_]) + + +do = { + '--csv': export_csv, + '--json': export_json, +} + +try: + city_name = sys.argv[3] +except IndexError: + city_name = None + +try: + filename = sys.argv[2] +except IndexError: + filename = None + +try: + operation = sys.argv[1] +except IndexError: + operation = None + +if operation: + if do[operation]: + do[operation](filename, city_name) + else: + print("Задана неверная команда") \ No newline at end of file diff --git a/lesson08/home_work/openweather.py b/lesson08/home_work/openweather.py index a9debfa1c..e5f64bcfd 100644 --- a/lesson08/home_work/openweather.py +++ b/lesson08/home_work/openweather.py @@ -1,125 +1,350 @@ - -""" -== OpenWeatherMap == - -OpenWeatherMap — онлайн-сервис, который предоставляет бесплатный API - для доступа к данным о текущей погоде, прогнозам, для web-сервисов - и мобильных приложений. Архивные данные доступны только на коммерческой основе. - В качестве источника данных используются официальные метеорологические службы - данные из метеостанций аэропортов, и данные с частных метеостанций. - -Необходимо решить следующие задачи: - -== Получение APPID == - Чтобы получать данные о погоде необходимо получить бесплатный APPID. - - Предлагается 2 варианта (по желанию): - - получить APPID вручную - - автоматизировать процесс получения APPID, - используя дополнительную библиотеку GRAB (pip install grab) - - Необходимо зарегистрироваться на сайте openweathermap.org: - https://home.openweathermap.org/users/sign_up - - Войти на сайт по ссылке: - https://home.openweathermap.org/users/sign_in - - Свой ключ "вытащить" со страницы отсюда: - https://home.openweathermap.org/api_keys - - Ключ имеет смысл сохранить в локальный файл, например, "app.id" - - -== Получение списка городов == - Список городов может быть получен по ссылке: - http://bulk.openweathermap.org/sample/city.list.json.gz - - Далее снова есть несколько вариантов (по желанию): - - скачать и распаковать список вручную - - автоматизировать скачивание (ulrlib) и распаковку списка - (воспользоваться модулем gzip - или распаковать внешним архиватором, воспользовавшись модулем subprocess) - - Список достаточно большой. Представляет собой JSON-строки: -{"_id":707860,"name":"Hurzuf","country":"UA","coord":{"lon":34.283333,"lat":44.549999}} -{"_id":519188,"name":"Novinki","country":"RU","coord":{"lon":37.666668,"lat":55.683334}} - - -== Получение погоды == - На основе списка городов можно делать запрос к сервису по id города. И тут как раз понадобится APPID. - By city ID - Examples of API calls: - http://api.openweathermap.org/data/2.5/weather?id=2172797&appid=b1b15e88fa797225412429c1c50c122a - - Для получения температуры по Цельсию: - http://api.openweathermap.org/data/2.5/weather?id=520068&units=metric&appid=b1b15e88fa797225412429c1c50c122a - - Для запроса по нескольким городам сразу: - http://api.openweathermap.org/data/2.5/group?id=524901,703448,2643743&units=metric&appid=b1b15e88fa797225412429c1c50c122a - - - Данные о погоде выдаются в JSON-формате - {"coord":{"lon":38.44,"lat":55.87}, - "weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04n"}], - "base":"cmc stations","main":{"temp":280.03,"pressure":1006,"humidity":83, - "temp_min":273.15,"temp_max":284.55},"wind":{"speed":3.08,"deg":265,"gust":7.2}, - "rain":{"3h":0.015},"clouds":{"all":76},"dt":1465156452, - "sys":{"type":3,"id":57233,"message":0.0024,"country":"RU","sunrise":1465087473, - "sunset":1465149961},"id":520068,"name":"Noginsk","cod":200} - - -== Сохранение данных в локальную БД == -Программа должна позволять: -1. Создавать файл базы данных SQLite со следующей структурой данных - (если файла базы данных не существует): - - Погода - id_города INTEGER PRIMARY KEY - Город VARCHAR(255) - Дата DATE - Температура INTEGER - id_погоды INTEGER # weather.id из JSON-данных - -2. Выводить список стран из файла и предлагать пользователю выбрать страну -(ввиду того, что список городов и стран весьма велик - имеет смысл запрашивать у пользователя имя города или страны - и искать данные в списке доступных городов/стран (регуляркой)) - -3. Скачивать JSON (XML) файлы погоды в городах выбранной страны -4. Парсить последовательно каждый из файлов и добавлять данные о погоде в базу - данных. Если данные для данного города и данного дня есть в базе - обновить - температуру в существующей записи. - - -При повторном запуске скрипта: -- используется уже скачанный файл с городами; -- используется созданная база данных, новые данные добавляются и обновляются. - - -При работе с XML-файлами: - -Доступ к данным в XML-файлах происходит через пространство имен: -