From 0456f04f3a1e3c12931c96b98fb662fb12825ce5 Mon Sep 17 00:00:00 2001 From: Dima Date: Tue, 9 Feb 2021 21:38:55 +0600 Subject: [PATCH 01/16] Class news_api_client has been implemented. Main api provides consolidated info about weather and news. --- conf.py | 10 +++---- index.py | 68 +++++++++++++++++++++++++++------------------- news_api_client.py | 25 +++++++++++++++++ 3 files changed, 70 insertions(+), 33 deletions(-) create mode 100644 news_api_client.py diff --git a/conf.py b/conf.py index b486b98..6a5f0ea 100644 --- a/conf.py +++ b/conf.py @@ -5,12 +5,12 @@ "url": "http://api.weatherstack.com/" } -# con_ow_data = { -# "api_key": "0a0b534b809a9d3ff21530f757d9509d", -# "url": "https://api.openweathermap.org/" -# } - con_wb = { "api_key": "a7e7248f711a4aeea8d6b7529040e94b", "url": "https://api.weatherbit.io/v2.0/current" +} + +con_top_news = { + "api_key": "0ffe15ac03b847999aa821a7eb904453", + "url": "http://newsapi.org/v2/top-headlines" } \ No newline at end of file diff --git a/index.py b/index.py index 07bc85a..ba91a8d 100644 --- a/index.py +++ b/index.py @@ -1,5 +1,5 @@ from weather_api_client import WeatherApiClient -# from open_weather_api_client import OpenWeatherApiClient +from news_api_client import NewsApiClient from weatherbit_api_client import WeatherbitApiClient from flask import Flask from flask import request @@ -22,34 +22,48 @@ def index(): def main(): # city = request.args.get('city') body = request.get_json(silent=True) - # print(body) - city = body['city'] - if city: - new_weather = WeatherApiClient(city) - status = new_weather.get_data() - if status: - wind_info = new_weather.get_wind() - moisture_info = new_weather.get_moisture() - main_weather_params = new_weather.get_main_weather_params() - data = {"moisture_info": moisture_info, - "wind_info": wind_info, - "main_weather_params": main_weather_params} - return jsonify(data) - else: - # new_weather = OpenWeatherApiClient(city) - new_weather = WeatherbitApiClient(city) - status = new_weather.get_data() - print("status", status) - if status: - weather_descr = new_weather.get_weather() + print(body) + if body: + country = body['country'] + city = body['city'] + if city and country: + new_weather = WeatherApiClient(city) + news = NewsApiClient(country) + status_news = news.get_data() + status_weather = new_weather.get_data() + if status_weather and status_news: + top_news_info = news.get_top_news() wind_info = new_weather.get_wind() - main_info = new_weather.get_main() - data = {"weather_descr": weather_descr, - "wind_info": wind_info, - "main_info": main_info} + moisture_info = new_weather.get_moisture() + main_weather_params = new_weather.get_main_weather_params() + data = { + "local_weather": {"moisture_info": moisture_info, + "wind_info": wind_info, + "main_weather_params": main_weather_params + }, + "top_news_info": top_news_info} return jsonify(data) else: - return render_template('error.html', city=city) + # new_weather = OpenWeatherApiClient(city) + new_weather = WeatherbitApiClient(city) + news = NewsApiClient(country) + status_news = news.get_data() + status_weather = new_weather.get_data() + if status_weather and status_news: + top_news_info = news.get_top_news() + weather_descr = new_weather.get_weather() + wind_info = new_weather.get_wind() + main_info = new_weather.get_main() + data = { + "local_weather": {"weather_descr": weather_descr, + "wind_info": wind_info, + "main_info": main_info}, + "top_news_info": top_news_info} + return jsonify(data) + else: + return render_template('error.html') + else: + return render_template('error.html') @app.route('/wind-info') @@ -75,7 +89,5 @@ def moisture(): return redirect("/", code=302) - - if __name__ == '__main__': app.run(debug=True) diff --git a/news_api_client.py b/news_api_client.py new file mode 100644 index 0000000..30deb21 --- /dev/null +++ b/news_api_client.py @@ -0,0 +1,25 @@ +import requests +import conf + + +class NewsApiClient: + + def __init__(self, country): + self.config = conf.con_top_news + self.country = country + self.news_data = {} + + def get_data(self): + response = requests.get(f"{self.config['url']}?country={self.country}&apiKey={self.config['api_key']}") + if 'status' not in response.json(): + return False + else: + self.news_data = response.json() + print(self.news_data) + return True + + def get_top_news(self): + top_news = { + "top_news": self.news_data['articles'][0:5] + } + return top_news From cc2258ab825f742c3fa5f2e8752ed53604102617 Mon Sep 17 00:00:00 2001 From: Dima Date: Wed, 10 Feb 2021 11:10:09 +0600 Subject: [PATCH 02/16] The structure of weather_api classes has been unified - same methods for both classes. --- index.py | 60 +++++++++++++++++--------------------- open_weather_api_client.py | 37 ----------------------- weather_api_client.py | 28 ++++-------------- weatherbit_api_client.py | 25 ++++------------ 4 files changed, 38 insertions(+), 112 deletions(-) delete mode 100644 open_weather_api_client.py diff --git a/index.py b/index.py index ba91a8d..bb43432 100644 --- a/index.py +++ b/index.py @@ -20,50 +20,44 @@ def index(): @app.route('/main', methods=['POST', 'GET']) def main(): - # city = request.args.get('city') - body = request.get_json(silent=True) - print(body) - if body: - country = body['country'] - city = body['city'] - if city and country: - new_weather = WeatherApiClient(city) + city = request.args.get('city') + country = request.args.get('country') + if city and country: + new_weather = WeatherApiClient(city) + news = NewsApiClient(country) + status_news = news.get_data() + status_weather = new_weather.get_data() + if status_weather and status_news: + top_news_info = news.get_top_news() + wind_info = new_weather.get_wind() + weather_info = new_weather.get_weather_description() + temperature_info = new_weather.get_temperature() + data = { + "local_weather": {"wind_info": wind_info, + "weather_info": weather_info, + "temperature_info": temperature_info + }, + "top_news_info": top_news_info} + return jsonify(data) + else: + new_weather = WeatherbitApiClient(city) news = NewsApiClient(country) status_news = news.get_data() status_weather = new_weather.get_data() if status_weather and status_news: top_news_info = news.get_top_news() wind_info = new_weather.get_wind() - moisture_info = new_weather.get_moisture() - main_weather_params = new_weather.get_main_weather_params() + weather_info = new_weather.get_weather_description() + temperature_info = new_weather.get_temperature() data = { - "local_weather": {"moisture_info": moisture_info, - "wind_info": wind_info, - "main_weather_params": main_weather_params + "local_weather": {"wind_info": wind_info, + "weather_info": weather_info, + "temperature_info": temperature_info }, "top_news_info": top_news_info} return jsonify(data) else: - # new_weather = OpenWeatherApiClient(city) - new_weather = WeatherbitApiClient(city) - news = NewsApiClient(country) - status_news = news.get_data() - status_weather = new_weather.get_data() - if status_weather and status_news: - top_news_info = news.get_top_news() - weather_descr = new_weather.get_weather() - wind_info = new_weather.get_wind() - main_info = new_weather.get_main() - data = { - "local_weather": {"weather_descr": weather_descr, - "wind_info": wind_info, - "main_info": main_info}, - "top_news_info": top_news_info} - return jsonify(data) - else: - return render_template('error.html') - else: - return render_template('error.html') + return render_template('error.html') @app.route('/wind-info') diff --git a/open_weather_api_client.py b/open_weather_api_client.py deleted file mode 100644 index ee0aed2..0000000 --- a/open_weather_api_client.py +++ /dev/null @@ -1,37 +0,0 @@ -import requests -import json -import conf - - -class OpenWeatherApiClient: - - weather_data = {} - - def __init__(self, city): - config = conf.con_ow_data - # self.weather_data = requests.get(config['url'] + "current?access_key=" + config['api_key'] + "&query=" + city) - response = requests.get(f"{config['url']}data/2.5/find?q={city}&appid={config['api_key']}") - self.weather_data = json.loads(response.text) - print(self.weather_data) - - def get_weather(self): - weather_descr = { - "weather_descr": self.weather_data['list'][0]['weather'][0]['description'] - } - return weather_descr - - def get_wind(self): - wind_info = { - "wind_speed": self.weather_data['list'][0]['wind']['speed'], - "wind_degree": self.weather_data['list'][0]['wind']['deg'] - } - return wind_info - - def get_main(self): - main_info = { - "temp": self.weather_data['list'][0]['main']['temp'], - "feels_like": self.weather_data['list'][0]['main']['feels_like'], - "pressure": self.weather_data['list'][0]['main']['pressure'], - "humidity": self.weather_data['list'][0]['main']['humidity'] - } - return main_info diff --git a/weather_api_client.py b/weather_api_client.py index 83845e5..23752d2 100644 --- a/weather_api_client.py +++ b/weather_api_client.py @@ -7,7 +7,6 @@ class WeatherApiClient: def __init__(self, city): self.config = conf.con self.city = city - # self.weather_data = requests.get(config['url'] + "current?access_key=" + config['api_key'] + "&query=" + city) self.weather_data = {} def get_data(self): @@ -20,27 +19,10 @@ def get_data(self): return True def get_wind(self): - wind_info = { - "wind_speed": self.weather_data['current']['wind_speed'], - "wind_degree": self.weather_data['current']['wind_degree'], - "wind_dir": self.weather_data['current']['wind_dir'], - } - return wind_info + return self.weather_data['current']['wind_speed'], "km/h" - def get_moisture(self): - moisture_info = { - "precip": self.weather_data['current']['precip'], - "humidity": self.weather_data['current']['humidity'], - "cloudcover": self.weather_data['current']['cloudcover'], - } - return moisture_info + def get_weather_description(self): + return self.weather_data['current']['weather_descriptions'][0] - def get_main_weather_params(self): - other_info = { - "temperature": self.weather_data['current']['temperature'], - "feelslike": self.weather_data['current']['feelslike'], - "weather_descriptions": self.weather_data['current']['weather_descriptions'][0], - "uv_index": self.weather_data['current']['uv_index'], - "visibility": self.weather_data['current']['visibility'], - } - return other_info + def get_temperature(self): + return self.weather_data['current']['temperature'], "celsius" diff --git a/weatherbit_api_client.py b/weatherbit_api_client.py index d1e26f5..0338650 100644 --- a/weatherbit_api_client.py +++ b/weatherbit_api_client.py @@ -19,24 +19,11 @@ def get_data(self): print(self.weather_data) return True - def get_weather(self): - weather_descr = { - "weather_descr": self.weather_data['data'][0]['weather']['description'] - } - return weather_descr - def get_wind(self): - wind_info = { - "wind_speed": self.weather_data['data'][0]['wind_spd'], - "wind_dir": self.weather_data['data'][0]['wind_cdir_full'] - } - return wind_info + return self.weather_data['data'][0]['wind_spd'], "km/h" + + def get_weather_description(self): + return self.weather_data['data'][0]['weather']['description'] - def get_main(self): - main_info = { - "temp": self.weather_data['data'][0]['temp'], - "feels_like": self.weather_data['data'][0]['app_temp'], - "pressure": self.weather_data['data'][0]['pres'], - "humidity": self.weather_data['data'][0]['rh'] - } - return main_info + def get_temperature(self): + return self.weather_data['data'][0]['temp'], "celsius" From d684baaac1e65c09188339cd7a5489a5f91070d9 Mon Sep 17 00:00:00 2001 From: Dima Date: Wed, 10 Feb 2021 20:59:36 +0600 Subject: [PATCH 03/16] Trying to unify a response from the news api. --- index.py | 16 +++++++++++----- news_api_client.py | 19 +++++++++++++------ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/index.py b/index.py index bb43432..6db4495 100644 --- a/index.py +++ b/index.py @@ -28,16 +28,19 @@ def main(): status_news = news.get_data() status_weather = new_weather.get_data() if status_weather and status_news: - top_news_info = news.get_top_news() + top_news = news.get_title() wind_info = new_weather.get_wind() weather_info = new_weather.get_weather_description() temperature_info = new_weather.get_temperature() data = { + "city": city, + "country": country, + "hot_news": top_news, "local_weather": {"wind_info": wind_info, "weather_info": weather_info, "temperature_info": temperature_info - }, - "top_news_info": top_news_info} + } + } return jsonify(data) else: new_weather = WeatherbitApiClient(city) @@ -50,11 +53,14 @@ def main(): weather_info = new_weather.get_weather_description() temperature_info = new_weather.get_temperature() data = { + "city": city, + "country": country, + "hot_news": top_news_info, "local_weather": {"wind_info": wind_info, "weather_info": weather_info, "temperature_info": temperature_info - }, - "top_news_info": top_news_info} + } + } return jsonify(data) else: return render_template('error.html') diff --git a/news_api_client.py b/news_api_client.py index 30deb21..14d03eb 100644 --- a/news_api_client.py +++ b/news_api_client.py @@ -16,10 +16,17 @@ def get_data(self): else: self.news_data = response.json() print(self.news_data) - return True + return self.news_data - def get_top_news(self): - top_news = { - "top_news": self.news_data['articles'][0:5] - } - return top_news + def get_title(self): + top_three_news = self.news_data['articles'][0:3] + news = [] + i = 0 + for k in top_three_news: + i += 1 + news.append('title' + str(i)) + news.append(k['title']) + news.append('body' + str(i)) + news.append(k['content']) + print(news) + return [news[i::3] for i in range(3)] From 1d26c24568b9fe39fa4858d41c27667f62fdf616 Mon Sep 17 00:00:00 2001 From: Dima Date: Fri, 12 Feb 2021 20:24:24 +0600 Subject: [PATCH 04/16] Formatted output for the news api and some minimal error handling for the rest of APIs were realized. --- conf.py | 2 +- index.py | 46 +++++++++++++++------------------------- news_api_client.py | 23 ++++++++++---------- weather_api_client.py | 3 ++- weatherbit_api_client.py | 4 ++-- 5 files changed, 33 insertions(+), 45 deletions(-) diff --git a/conf.py b/conf.py index 6a5f0ea..2b756a9 100644 --- a/conf.py +++ b/conf.py @@ -11,6 +11,6 @@ } con_top_news = { - "api_key": "0ffe15ac03b847999aa821a7eb904453", + "api_key": "0ffe15ac03b847999aa821a7eb9044533", "url": "http://newsapi.org/v2/top-headlines" } \ No newline at end of file diff --git a/index.py b/index.py index 6db4495..6efdef0 100644 --- a/index.py +++ b/index.py @@ -24,47 +24,35 @@ def main(): country = request.args.get('country') if city and country: new_weather = WeatherApiClient(city) - news = NewsApiClient(country) - status_news = news.get_data() status_weather = new_weather.get_data() - if status_weather and status_news: - top_news = news.get_title() + if status_weather: wind_info = new_weather.get_wind() weather_info = new_weather.get_weather_description() temperature_info = new_weather.get_temperature() - data = { - "city": city, - "country": country, - "hot_news": top_news, - "local_weather": {"wind_info": wind_info, - "weather_info": weather_info, - "temperature_info": temperature_info - } - } - return jsonify(data) else: new_weather = WeatherbitApiClient(city) - news = NewsApiClient(country) - status_news = news.get_data() status_weather = new_weather.get_data() - if status_weather and status_news: - top_news_info = news.get_top_news() + if status_weather: wind_info = new_weather.get_wind() weather_info = new_weather.get_weather_description() temperature_info = new_weather.get_temperature() - data = { - "city": city, - "country": country, - "hot_news": top_news_info, - "local_weather": {"wind_info": wind_info, - "weather_info": weather_info, - "temperature_info": temperature_info - } - } - return jsonify(data) else: return render_template('error.html') - + news = NewsApiClient(country) + status_news = news.get_data() + top_news = "test" + if status_news: + top_news = news.get_top_news() + data = { + "city": city, + "country": country, + "hot_news": top_news, + "local_weather": {"wind_info": wind_info, + "weather_info": weather_info, + "temperature_info": temperature_info + } + } + return jsonify(data) @app.route('/wind-info') def wind(): diff --git a/news_api_client.py b/news_api_client.py index 14d03eb..f202ddf 100644 --- a/news_api_client.py +++ b/news_api_client.py @@ -11,22 +11,21 @@ def __init__(self, country): def get_data(self): response = requests.get(f"{self.config['url']}?country={self.country}&apiKey={self.config['api_key']}") - if 'status' not in response.json(): + if response.status_code != 200: + print(response.status_code) return False else: self.news_data = response.json() print(self.news_data) return self.news_data - def get_title(self): + def get_top_news(self): top_three_news = self.news_data['articles'][0:3] - news = [] - i = 0 - for k in top_three_news: - i += 1 - news.append('title' + str(i)) - news.append(k['title']) - news.append('body' + str(i)) - news.append(k['content']) - print(news) - return [news[i::3] for i in range(3)] + our_three = [] + for news in top_three_news: + formatted_news = { + "title": news['title'], + "body": news['content'] + } + our_three.append(formatted_news) + return our_three diff --git a/weather_api_client.py b/weather_api_client.py index 23752d2..4f7d3fc 100644 --- a/weather_api_client.py +++ b/weather_api_client.py @@ -11,7 +11,8 @@ def __init__(self, city): def get_data(self): response = requests.get(f"{self.config['url']}current?access_key={self.config['api_key']}&query={self.city}") - if 'request' not in response.json(): + if response.status_code != 200: + print(response.status_code) return False else: self.weather_data = response.json() diff --git a/weatherbit_api_client.py b/weatherbit_api_client.py index 0338650..4fcfe5a 100644 --- a/weatherbit_api_client.py +++ b/weatherbit_api_client.py @@ -8,11 +8,11 @@ def __init__(self, city): self.config = conf.con_wb self.city = city self.weather_data = {} - # self.weather_data = requests.get(config['url'] + "current?access_key=" + config['api_key'] + "&query=" + city) def get_data(self): response = requests.get(f"{self.config['url']}?city={self.city}&key={self.config['api_key']}") - if 'data' not in response.json(): + if response.status_code != 200: + print(response.status_code) return False else: self.weather_data = response.json() From 4a3b450b1a2ef8d700171479f579e1b60683352d Mon Sep 17 00:00:00 2001 From: Dima Date: Sat, 13 Feb 2021 18:15:41 +0600 Subject: [PATCH 05/16] ParentWeatherApi class has been realized for usage of advantage of inheritance --- ParentWeatherApi.py | 6 ++++++ weather_api_client.py | 10 ++++------ weatherbit_api_client.py | 7 +++---- 3 files changed, 13 insertions(+), 10 deletions(-) create mode 100644 ParentWeatherApi.py diff --git a/ParentWeatherApi.py b/ParentWeatherApi.py new file mode 100644 index 0000000..dc551be --- /dev/null +++ b/ParentWeatherApi.py @@ -0,0 +1,6 @@ +class ParentWeatherApi: + + def __init__(self, city, config): + self.config = config + self.city = city + self.weather_data = {} diff --git a/weather_api_client.py b/weather_api_client.py index 4f7d3fc..8d5713f 100644 --- a/weather_api_client.py +++ b/weather_api_client.py @@ -1,18 +1,16 @@ import requests import conf +from ParentWeatherApi import ParentWeatherApi -class WeatherApiClient: +class WeatherApiClient(ParentWeatherApi): def __init__(self, city): - self.config = conf.con - self.city = city - self.weather_data = {} + super().__init__(city, config=conf.con) def get_data(self): response = requests.get(f"{self.config['url']}current?access_key={self.config['api_key']}&query={self.city}") - if response.status_code != 200: - print(response.status_code) + if 'success' in response.json(): return False else: self.weather_data = response.json() diff --git a/weatherbit_api_client.py b/weatherbit_api_client.py index 4fcfe5a..46ade2f 100644 --- a/weatherbit_api_client.py +++ b/weatherbit_api_client.py @@ -1,13 +1,12 @@ import requests import conf +from ParentWeatherApi import ParentWeatherApi -class WeatherbitApiClient: +class WeatherbitApiClient(ParentWeatherApi): def __init__(self, city): - self.config = conf.con_wb - self.city = city - self.weather_data = {} + super().__init__(city, config=conf.con_wb) def get_data(self): response = requests.get(f"{self.config['url']}?city={self.city}&key={self.config['api_key']}") From e71b4dbc4f3881867c493ce672ff90f21dcc0e1e Mon Sep 17 00:00:00 2001 From: Dima Date: Sun, 14 Feb 2021 20:43:26 +0600 Subject: [PATCH 06/16] LentaParser class has been added as a backup source for news, that class gathers all main news from the lenta.ru portal. --- LentaParser.py | 34 ++++++++++++++++++++++++++++++++++ conf.py | 4 ++++ index.py | 5 ++++- 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 LentaParser.py diff --git a/LentaParser.py b/LentaParser.py new file mode 100644 index 0000000..5e21eb0 --- /dev/null +++ b/LentaParser.py @@ -0,0 +1,34 @@ +from bs4 import BeautifulSoup as bs +import requests +import time +from conf import con_lenta + + +class LentaParser: + + def __init__(self): + self.top_news = [] + + def get_news(self): + response = requests.get(f"{con_lenta['url']}").text + soup = bs(response, 'lxml') + all_paragraphs = [] + for each in soup.select('div[class*="yellow-box__wrap"]'): + children = each.findChildren(recursive=False) + main_news = children[1:] + for news in main_news: + news_data = {} + news_title = news.getText() + news_title = news_title.replace(u'\xa0', u' ') + news_data['title'] = news_title + news_href = con_lenta['url'] + news.find('a', href=True).get('href') + body = requests.get(news_href).text + time.sleep(1) + soup_article = bs(body, 'lxml') + for element in soup_article.select('div[itemprop*="articleBody"]'): + paragraph = element.find_all('p') + for p in paragraph: + all_paragraphs = p.getText() + news_data['body'] = all_paragraphs + self.top_news.append(news_data) + return self.top_news diff --git a/conf.py b/conf.py index 2b756a9..6fd015c 100644 --- a/conf.py +++ b/conf.py @@ -13,4 +13,8 @@ con_top_news = { "api_key": "0ffe15ac03b847999aa821a7eb9044533", "url": "http://newsapi.org/v2/top-headlines" +} + +con_lenta = { + "url": "https://lenta.ru/" } \ No newline at end of file diff --git a/index.py b/index.py index 6efdef0..4bd52d4 100644 --- a/index.py +++ b/index.py @@ -1,6 +1,7 @@ from weather_api_client import WeatherApiClient from news_api_client import NewsApiClient from weatherbit_api_client import WeatherbitApiClient +from LentaParser import LentaParser from flask import Flask from flask import request from flask import render_template @@ -40,9 +41,11 @@ def main(): return render_template('error.html') news = NewsApiClient(country) status_news = news.get_data() - top_news = "test" if status_news: top_news = news.get_top_news() + else: + news = LentaParser() + top_news = news.get_news() data = { "city": city, "country": country, From e1e4b4232af4c969ca6af3daa24f502f29c1fd21 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 15 Feb 2021 21:21:21 +0600 Subject: [PATCH 07/16] Some minor fixes --- LentaParser.py | 7 ++++--- api_not_available.py | 2 ++ index.py | 4 ++-- weather_api_client.py | 22 +++++++++++++++------- weatherbit_api_client.py | 29 ++++++++++++++++++----------- 5 files changed, 41 insertions(+), 23 deletions(-) create mode 100644 api_not_available.py diff --git a/LentaParser.py b/LentaParser.py index 5e21eb0..afda4c5 100644 --- a/LentaParser.py +++ b/LentaParser.py @@ -12,7 +12,6 @@ def __init__(self): def get_news(self): response = requests.get(f"{con_lenta['url']}").text soup = bs(response, 'lxml') - all_paragraphs = [] for each in soup.select('div[class*="yellow-box__wrap"]'): children = each.findChildren(recursive=False) main_news = children[1:] @@ -27,8 +26,10 @@ def get_news(self): soup_article = bs(body, 'lxml') for element in soup_article.select('div[itemprop*="articleBody"]'): paragraph = element.find_all('p') + all_paragraphs = "" for p in paragraph: - all_paragraphs = p.getText() - news_data['body'] = all_paragraphs + p_text = p.getText() + all_paragraphs = "".join(p_text) + news_data['body'] = all_paragraphs self.top_news.append(news_data) return self.top_news diff --git a/api_not_available.py b/api_not_available.py new file mode 100644 index 0000000..5d10b1f --- /dev/null +++ b/api_not_available.py @@ -0,0 +1,2 @@ +class ApiNotAvailableException(Exception): + pass diff --git a/index.py b/index.py index 4bd52d4..886f000 100644 --- a/index.py +++ b/index.py @@ -25,14 +25,14 @@ def main(): country = request.args.get('country') if city and country: new_weather = WeatherApiClient(city) - status_weather = new_weather.get_data() + status_weather = new_weather.get_weather_data() if status_weather: wind_info = new_weather.get_wind() weather_info = new_weather.get_weather_description() temperature_info = new_weather.get_temperature() else: new_weather = WeatherbitApiClient(city) - status_weather = new_weather.get_data() + status_weather = new_weather.get_weather_data() if status_weather: wind_info = new_weather.get_wind() weather_info = new_weather.get_weather_description() diff --git a/weather_api_client.py b/weather_api_client.py index 8d5713f..1951e72 100644 --- a/weather_api_client.py +++ b/weather_api_client.py @@ -1,21 +1,29 @@ import requests import conf from ParentWeatherApi import ParentWeatherApi +from api_not_available import ApiNotAvailableException -class WeatherApiClient(ParentWeatherApi): +class WeatherApiClient(): + BASE_URL = "{}current?access_key={}&query={}" def __init__(self, city): - super().__init__(city, config=conf.con) + self.weather_data = {} + self.city = city + self.send_request() - def get_data(self): - response = requests.get(f"{self.config['url']}current?access_key={self.config['api_key']}&query={self.city}") + def send_request(self): + response = requests.get(self.BASE_URL.format(conf.con['url'], conf.con['api_key'], self.city)) if 'success' in response.json(): - return False + error_message = response.json()['error']['info'] + print(ApiNotAvailableException(f"{error_message} occurred in WeatherApiClient")) + return None else: self.weather_data = response.json() - print(self.weather_data) - return True + return self.weather_data + + def get_weather_data(self): + return self.weather_data def get_wind(self): return self.weather_data['current']['wind_speed'], "km/h" diff --git a/weatherbit_api_client.py b/weatherbit_api_client.py index 46ade2f..25faa52 100644 --- a/weatherbit_api_client.py +++ b/weatherbit_api_client.py @@ -1,22 +1,29 @@ import requests import conf +from api_not_available import ApiNotAvailableException from ParentWeatherApi import ParentWeatherApi -class WeatherbitApiClient(ParentWeatherApi): +class WeatherbitApiClient(): + BASE_URL = "{}?city={}&key={}" def __init__(self, city): - super().__init__(city, config=conf.con_wb) - - def get_data(self): - response = requests.get(f"{self.config['url']}?city={self.city}&key={self.config['api_key']}") - if response.status_code != 200: - print(response.status_code) - return False - else: + self.weather_data = {} + self.city = city + self.send_request() + + def send_request(self): + response = requests.get(self.BASE_URL.format(conf.con_wb['url'], self.city, conf.con_wb['api_key'])) + try: self.weather_data = response.json() - print(self.weather_data) - return True + return self.weather_data + except ApiNotAvailableException: + if response.status_code != 200: + error_message = response.json()['error'] + raise ApiNotAvailableException(f"{error_message} occurred in WeatherbitApiClient") + + def get_weather_data(self): + return self.weather_data def get_wind(self): return self.weather_data['data'][0]['wind_spd'], "km/h" From 0e314dd8a28979fb61b8930f0e35aa35de9a7aa2 Mon Sep 17 00:00:00 2001 From: Dima Date: Tue, 16 Feb 2021 12:47:15 +0600 Subject: [PATCH 08/16] Lentaparser's output has been fixed. Also realized abstraction on a base of ParentWeatherApi class. --- LentaParser.py | 5 +---- ParentWeatherApi.py | 15 +++++++++++---- conf.py | 2 +- weather_api_client.py | 6 ++---- weatherbit_api_client.py | 6 ++---- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/LentaParser.py b/LentaParser.py index afda4c5..4e85e7b 100644 --- a/LentaParser.py +++ b/LentaParser.py @@ -26,10 +26,7 @@ def get_news(self): soup_article = bs(body, 'lxml') for element in soup_article.select('div[itemprop*="articleBody"]'): paragraph = element.find_all('p') - all_paragraphs = "" - for p in paragraph: - p_text = p.getText() - all_paragraphs = "".join(p_text) + all_paragraphs = (''.join(p.getText() for p in paragraph)) news_data['body'] = all_paragraphs self.top_news.append(news_data) return self.top_news diff --git a/ParentWeatherApi.py b/ParentWeatherApi.py index dc551be..dadb23e 100644 --- a/ParentWeatherApi.py +++ b/ParentWeatherApi.py @@ -1,6 +1,13 @@ -class ParentWeatherApi: +from abc import ABC, abstractmethod - def __init__(self, city, config): - self.config = config - self.city = city + +class ParentWeatherApi(ABC): + + def __init__(self, city): self.weather_data = {} + self.city = city + self.send_request() + + @abstractmethod + def send_request(self): + pass diff --git a/conf.py b/conf.py index 6fd015c..4e4e98d 100644 --- a/conf.py +++ b/conf.py @@ -11,7 +11,7 @@ } con_top_news = { - "api_key": "0ffe15ac03b847999aa821a7eb9044533", + "api_key": "0ffe15ac03b847999aa821a7eb904453", "url": "http://newsapi.org/v2/top-headlines" } diff --git a/weather_api_client.py b/weather_api_client.py index 1951e72..3f3691e 100644 --- a/weather_api_client.py +++ b/weather_api_client.py @@ -4,13 +4,11 @@ from api_not_available import ApiNotAvailableException -class WeatherApiClient(): +class WeatherApiClient(ParentWeatherApi): BASE_URL = "{}current?access_key={}&query={}" def __init__(self, city): - self.weather_data = {} - self.city = city - self.send_request() + super().__init__(city) def send_request(self): response = requests.get(self.BASE_URL.format(conf.con['url'], conf.con['api_key'], self.city)) diff --git a/weatherbit_api_client.py b/weatherbit_api_client.py index 25faa52..e9fd990 100644 --- a/weatherbit_api_client.py +++ b/weatherbit_api_client.py @@ -4,13 +4,11 @@ from ParentWeatherApi import ParentWeatherApi -class WeatherbitApiClient(): +class WeatherbitApiClient(ParentWeatherApi): BASE_URL = "{}?city={}&key={}" def __init__(self, city): - self.weather_data = {} - self.city = city - self.send_request() + super().__init__(city) def send_request(self): response = requests.get(self.BASE_URL.format(conf.con_wb['url'], self.city, conf.con_wb['api_key'])) From 477ae6595d5fa576d556d22fde42489aef0aa516 Mon Sep 17 00:00:00 2001 From: Dima Date: Tue, 16 Feb 2021 21:53:52 +0600 Subject: [PATCH 09/16] Minor fixes --- ParentWeatherApi.py | 3 +++ conf.py | 11 +++++++++-- index.py | 6 +++++- weather_api_client.py | 3 --- weatherbit_api_client.py | 3 --- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/ParentWeatherApi.py b/ParentWeatherApi.py index dadb23e..daed6ae 100644 --- a/ParentWeatherApi.py +++ b/ParentWeatherApi.py @@ -11,3 +11,6 @@ def __init__(self, city): @abstractmethod def send_request(self): pass + + def get_weather_data(self): + return self.weather_data diff --git a/conf.py b/conf.py index 4e4e98d..d14ad7a 100644 --- a/conf.py +++ b/conf.py @@ -1,4 +1,4 @@ - +import psycopg2 con = { "api_key": "ca6a19006afff952f0e5246316b1ff94", @@ -17,4 +17,11 @@ con_lenta = { "url": "https://lenta.ru/" -} \ No newline at end of file +} + +con_db = psycopg2.connect( + host="localhost", + database="GatherApiData", + user="postgres", + password="123QWEasd" +) \ No newline at end of file diff --git a/index.py b/index.py index 886f000..4a64d7b 100644 --- a/index.py +++ b/index.py @@ -2,17 +2,20 @@ from news_api_client import NewsApiClient from weatherbit_api_client import WeatherbitApiClient from LentaParser import LentaParser +from conf import con_db from flask import Flask from flask import request from flask import render_template from flask import redirect -from flask_restful import Resource, Api +from flask_restful import Api from flask import jsonify app = Flask(__name__) api = Api(app) +cur = con_db.cursor() + @app.route('/') def index(): @@ -57,6 +60,7 @@ def main(): } return jsonify(data) + @app.route('/wind-info') def wind(): city = request.args.get('city') diff --git a/weather_api_client.py b/weather_api_client.py index 3f3691e..cc2ccdf 100644 --- a/weather_api_client.py +++ b/weather_api_client.py @@ -20,9 +20,6 @@ def send_request(self): self.weather_data = response.json() return self.weather_data - def get_weather_data(self): - return self.weather_data - def get_wind(self): return self.weather_data['current']['wind_speed'], "km/h" diff --git a/weatherbit_api_client.py b/weatherbit_api_client.py index e9fd990..f802feb 100644 --- a/weatherbit_api_client.py +++ b/weatherbit_api_client.py @@ -20,9 +20,6 @@ def send_request(self): error_message = response.json()['error'] raise ApiNotAvailableException(f"{error_message} occurred in WeatherbitApiClient") - def get_weather_data(self): - return self.weather_data - def get_wind(self): return self.weather_data['data'][0]['wind_spd'], "km/h" From 85dcc858b02b5e38cb85606d318109a87169e4a9 Mon Sep 17 00:00:00 2001 From: Dima Date: Thu, 18 Feb 2021 18:42:09 +0600 Subject: [PATCH 10/16] Realized abstraction for news on a base of ParentNews class. --- LentaParser.py | 18 ++++++------- ParentNews.py | 12 +++++++++ ParentWeatherApi.py | 16 ++++++++--- conf.py | 8 +++--- index.py | 57 +++++++--------------------------------- news_api_client.py | 41 ++++++++++++++--------------- weather_api_client.py | 11 +++----- weatherbit_api_client.py | 16 +++++------ 8 files changed, 75 insertions(+), 104 deletions(-) create mode 100644 ParentNews.py diff --git a/LentaParser.py b/LentaParser.py index 4e85e7b..0097fd6 100644 --- a/LentaParser.py +++ b/LentaParser.py @@ -2,24 +2,22 @@ import requests import time from conf import con_lenta +from ParentNews import ParentNews -class LentaParser: +class LentaParser(ParentNews): - def __init__(self): - self.top_news = [] - - def get_news(self): + def send_request(self): response = requests.get(f"{con_lenta['url']}").text soup = bs(response, 'lxml') for each in soup.select('div[class*="yellow-box__wrap"]'): children = each.findChildren(recursive=False) main_news = children[1:] for news in main_news: - news_data = {} + news_output = {} news_title = news.getText() news_title = news_title.replace(u'\xa0', u' ') - news_data['title'] = news_title + news_output['title'] = news_title news_href = con_lenta['url'] + news.find('a', href=True).get('href') body = requests.get(news_href).text time.sleep(1) @@ -27,6 +25,6 @@ def get_news(self): for element in soup_article.select('div[itemprop*="articleBody"]'): paragraph = element.find_all('p') all_paragraphs = (''.join(p.getText() for p in paragraph)) - news_data['body'] = all_paragraphs - self.top_news.append(news_data) - return self.top_news + news_output['body'] = all_paragraphs + self.news_data.append(news_output) + return self.news_data diff --git a/ParentNews.py b/ParentNews.py new file mode 100644 index 0000000..36d4c24 --- /dev/null +++ b/ParentNews.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod + + +class ParentNews(ABC): + + def __init__(self): + self.news_data = [] + self.send_request() + + @abstractmethod + def send_request(self): + raise NotImplementedError diff --git a/ParentWeatherApi.py b/ParentWeatherApi.py index daed6ae..b2e6353 100644 --- a/ParentWeatherApi.py +++ b/ParentWeatherApi.py @@ -10,7 +10,17 @@ def __init__(self, city): @abstractmethod def send_request(self): - pass + raise NotImplementedError + + @abstractmethod + def get_wind(self): + raise NotImplementedError + + @abstractmethod + def get_weather_description(self): + raise NotImplementedError + + @abstractmethod + def get_temperature(self): + raise NotImplementedError - def get_weather_data(self): - return self.weather_data diff --git a/conf.py b/conf.py index d14ad7a..92b5a48 100644 --- a/conf.py +++ b/conf.py @@ -1,7 +1,7 @@ import psycopg2 con = { - "api_key": "ca6a19006afff952f0e5246316b1ff94", + "api_key": "ca6a19006afff952f0e5246316b1ff944", "url": "http://api.weatherstack.com/" } @@ -10,8 +10,8 @@ "url": "https://api.weatherbit.io/v2.0/current" } -con_top_news = { - "api_key": "0ffe15ac03b847999aa821a7eb904453", +con_api_news = { + "api_key": "0ffe15ac03b847999aa821a7eb9044533", "url": "http://newsapi.org/v2/top-headlines" } @@ -24,4 +24,4 @@ database="GatherApiData", user="postgres", password="123QWEasd" -) \ No newline at end of file +) diff --git a/index.py b/index.py index 4a64d7b..d3240a2 100644 --- a/index.py +++ b/index.py @@ -2,20 +2,17 @@ from news_api_client import NewsApiClient from weatherbit_api_client import WeatherbitApiClient from LentaParser import LentaParser -from conf import con_db from flask import Flask from flask import request from flask import render_template -from flask import redirect from flask_restful import Api from flask import jsonify +from api_not_available import ApiNotAvailableException app = Flask(__name__) api = Api(app) -cur = con_db.cursor() - @app.route('/') def index(): @@ -27,32 +24,19 @@ def main(): city = request.args.get('city') country = request.args.get('country') if city and country: - new_weather = WeatherApiClient(city) - status_weather = new_weather.get_weather_data() - if status_weather: - wind_info = new_weather.get_wind() - weather_info = new_weather.get_weather_description() - temperature_info = new_weather.get_temperature() - else: + try: + new_weather = WeatherApiClient(city) + news = NewsApiClient(country) + except ApiNotAvailableException: new_weather = WeatherbitApiClient(city) - status_weather = new_weather.get_weather_data() - if status_weather: - wind_info = new_weather.get_wind() - weather_info = new_weather.get_weather_description() - temperature_info = new_weather.get_temperature() - else: - return render_template('error.html') - news = NewsApiClient(country) - status_news = news.get_data() - if status_news: - top_news = news.get_top_news() - else: news = LentaParser() - top_news = news.get_news() + wind_info = new_weather.get_wind() + weather_info = new_weather.get_weather_description() + temperature_info = new_weather.get_temperature() data = { "city": city, "country": country, - "hot_news": top_news, + "hot_news": news.news_data, "local_weather": {"wind_info": wind_info, "weather_info": weather_info, "temperature_info": temperature_info @@ -61,28 +45,5 @@ def main(): return jsonify(data) -@app.route('/wind-info') -def wind(): - city = request.args.get('city') - if city: - new_weather = WeatherApiClient(city) - wind_info = new_weather.get_wind() - print(wind_info) - return render_template('wind-info.html', wind=wind_info) - else: - return redirect("/", code=302) - - -@app.route('/moisture-info') -def moisture(): - city = request.args.get('city') - if city: - new_weather = WeatherApiClient(city) - moisture_info = new_weather.get_moisture() - return render_template('moisture-info.html', moisture=moisture_info) - else: - return redirect("/", code=302) - - if __name__ == '__main__': app.run(debug=True) diff --git a/news_api_client.py b/news_api_client.py index f202ddf..3ca2a0c 100644 --- a/news_api_client.py +++ b/news_api_client.py @@ -1,31 +1,30 @@ import requests -import conf +from conf import con_api_news +from api_not_available import ApiNotAvailableException +from ParentNews import ParentNews +from pprint import pprint -class NewsApiClient: +class NewsApiClient(ParentNews): def __init__(self, country): - self.config = conf.con_top_news self.country = country - self.news_data = {} + super().__init__() - def get_data(self): - response = requests.get(f"{self.config['url']}?country={self.country}&apiKey={self.config['api_key']}") + def send_request(self): + response = requests.get(f"{con_api_news['url']}?country={self.country}&apiKey={con_api_news['api_key']}") if response.status_code != 200: - print(response.status_code) - return False + error_message = response.json()['error'] + raise ApiNotAvailableException(f"{error_message} occurred in NewsApiClient") else: - self.news_data = response.json() - print(self.news_data) + news_data = response.json() + news_data = news_data['articles'][0:] + pprint(news_data) + for news in news_data: + formatted_news = { + "title": news['title'], + "body": news['content'] + } + self.news_data.append(formatted_news) + pprint(self.news_data) return self.news_data - - def get_top_news(self): - top_three_news = self.news_data['articles'][0:3] - our_three = [] - for news in top_three_news: - formatted_news = { - "title": news['title'], - "body": news['content'] - } - our_three.append(formatted_news) - return our_three diff --git a/weather_api_client.py b/weather_api_client.py index cc2ccdf..0940ced 100644 --- a/weather_api_client.py +++ b/weather_api_client.py @@ -1,5 +1,5 @@ import requests -import conf +from conf import con from ParentWeatherApi import ParentWeatherApi from api_not_available import ApiNotAvailableException @@ -7,18 +7,13 @@ class WeatherApiClient(ParentWeatherApi): BASE_URL = "{}current?access_key={}&query={}" - def __init__(self, city): - super().__init__(city) - def send_request(self): - response = requests.get(self.BASE_URL.format(conf.con['url'], conf.con['api_key'], self.city)) + response = requests.get(self.BASE_URL.format(con['url'], con['api_key'], self.city)) if 'success' in response.json(): error_message = response.json()['error']['info'] - print(ApiNotAvailableException(f"{error_message} occurred in WeatherApiClient")) - return None + raise ApiNotAvailableException(f"{error_message} occurred in WeatherApiClient") else: self.weather_data = response.json() - return self.weather_data def get_wind(self): return self.weather_data['current']['wind_speed'], "km/h" diff --git a/weatherbit_api_client.py b/weatherbit_api_client.py index f802feb..08ac5f1 100644 --- a/weatherbit_api_client.py +++ b/weatherbit_api_client.py @@ -1,5 +1,5 @@ import requests -import conf +from conf import con_wb from api_not_available import ApiNotAvailableException from ParentWeatherApi import ParentWeatherApi @@ -7,18 +7,14 @@ class WeatherbitApiClient(ParentWeatherApi): BASE_URL = "{}?city={}&key={}" - def __init__(self, city): - super().__init__(city) - def send_request(self): - response = requests.get(self.BASE_URL.format(conf.con_wb['url'], self.city, conf.con_wb['api_key'])) - try: + response = requests.get(self.BASE_URL.format(con_wb['url'], self.city, con_wb['api_key'])) + if response.status_code != 200: + error_message = response.json()['error'] + raise ApiNotAvailableException(f"{error_message} occurred in WeatherbitApiClient") + else: self.weather_data = response.json() return self.weather_data - except ApiNotAvailableException: - if response.status_code != 200: - error_message = response.json()['error'] - raise ApiNotAvailableException(f"{error_message} occurred in WeatherbitApiClient") def get_wind(self): return self.weather_data['data'][0]['wind_spd'], "km/h" From 419393f355340b714682bf532ed39d733dd2e817 Mon Sep 17 00:00:00 2001 From: Dima Date: Fri, 19 Feb 2021 10:04:41 +0600 Subject: [PATCH 11/16] Some fixes --- LentaParser.py | 18 +++++++++---- ParentNews.py | 4 +-- ParentWeatherApi.py | 4 +-- conf.py | 7 ----- db_creation.py | 56 ++++++++++++++++++++++++++++++++++++++++ db_insert_data.py | 43 ++++++++++++++++++++++++++++++ index.py | 6 +++-- news_api_client.py | 27 ++++++++++--------- pgconnection.py | 8 ++++++ weather_api_client.py | 2 +- weatherbit_api_client.py | 2 +- 11 files changed, 143 insertions(+), 34 deletions(-) create mode 100644 db_creation.py create mode 100644 db_insert_data.py create mode 100644 pgconnection.py diff --git a/LentaParser.py b/LentaParser.py index 0097fd6..1cc5b08 100644 --- a/LentaParser.py +++ b/LentaParser.py @@ -3,13 +3,21 @@ import time from conf import con_lenta from ParentNews import ParentNews +from api_not_available import ApiNotAvailableException class LentaParser(ParentNews): - def send_request(self): - response = requests.get(f"{con_lenta['url']}").text - soup = bs(response, 'lxml') + def __send_request(self): + response = requests.get(f"{con_lenta['url']}") + if response.status_code != 200: + raise ApiNotAvailableException("Error occurred in LentaParser") + else: + self.news_data = response.text + + def get_top_news(self): + soup = bs(self.news_data, 'lxml') + output_news = [] for each in soup.select('div[class*="yellow-box__wrap"]'): children = each.findChildren(recursive=False) main_news = children[1:] @@ -26,5 +34,5 @@ def send_request(self): paragraph = element.find_all('p') all_paragraphs = (''.join(p.getText() for p in paragraph)) news_output['body'] = all_paragraphs - self.news_data.append(news_output) - return self.news_data + output_news.append(news_output) + return output_news diff --git a/ParentNews.py b/ParentNews.py index 36d4c24..0a6c22a 100644 --- a/ParentNews.py +++ b/ParentNews.py @@ -5,8 +5,8 @@ class ParentNews(ABC): def __init__(self): self.news_data = [] - self.send_request() + self.__send_request() @abstractmethod - def send_request(self): + def __send_request(self): raise NotImplementedError diff --git a/ParentWeatherApi.py b/ParentWeatherApi.py index b2e6353..bcb9ee6 100644 --- a/ParentWeatherApi.py +++ b/ParentWeatherApi.py @@ -6,10 +6,10 @@ class ParentWeatherApi(ABC): def __init__(self, city): self.weather_data = {} self.city = city - self.send_request() + self.__send_request() @abstractmethod - def send_request(self): + def __send_request(self): raise NotImplementedError @abstractmethod diff --git a/conf.py b/conf.py index 92b5a48..6b71baf 100644 --- a/conf.py +++ b/conf.py @@ -18,10 +18,3 @@ con_lenta = { "url": "https://lenta.ru/" } - -con_db = psycopg2.connect( - host="localhost", - database="GatherApiData", - user="postgres", - password="123QWEasd" -) diff --git a/db_creation.py b/db_creation.py new file mode 100644 index 0000000..7e742b6 --- /dev/null +++ b/db_creation.py @@ -0,0 +1,56 @@ +from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT +import psycopg2 + +import pgconnection + + +def main(): + queries = ({"Description": "Create database", + "Database": "postgres", + "SQL": """CREATE DATABASE apidata"""}, + + {"Description": "Create city table ", + "Database": "apidata", + "SQL": """CREATE TABLE city(cityid serial PRIMARY KEY, name varchar(256) NOT NULL)"""}, + + {"Description": "Create weather table ", + "Database": "apidata", + "SQL": """CREATE TABLE weather(weatherid serial PRIMARY KEY, + cityid smallint REFERENCES city(cityid) NOT NULL, + weather_info varchar(256) NOT NULL, + temp_in_celsius DECIMAL(3,1) NOT NULL, + wind_speed_kmph smallint NOT NULL, dateadded date)"""}, + + {"Description": "Create country table ", + "Database": "apidata", + "SQL": """CREATE TABLE country(countryid serial PRIMARY KEY, name varchar(256) NOT NULL)"""}, + + {"Description": "Create news table ", + "Database": "apidata", + "SQL": """CREATE TABLE news(newsid serial PRIMARY KEY, + countryid smallint REFERENCES country(countryid) NOT NULL, + title varchar(1024) NOT NULL, + body text NOT NULL, + dateadded date)"""}) + + try: + + for query in queries: + conn = pgconnection.get_connection(query["Database"]) + print(conn) + conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) + cursor = conn.cursor() + + cursor.execute(query["SQL"]) + + print("Executed {}".format(query["Description"])) + + cursor.close() + conn.close() + + except psycopg2.ProgrammingError as e: + + print(e) + + +main() diff --git a/db_insert_data.py b/db_insert_data.py new file mode 100644 index 0000000..c93e5b9 --- /dev/null +++ b/db_insert_data.py @@ -0,0 +1,43 @@ +import datetime +import requests +import psycopg2 +from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT +import sqlalchemy +import pgconnection + + +class InsertData: + + BASE_URL = "http://127.0.0.1:5000/main?city=Ottawa&country=ca" + + def __init__(self): + self.data_response = {} + self.send_request() + + def send_request(self): + response = requests.get(InsertData.BASE_URL) + self.data_response = response.json() + return self.data_response + + def insert_data(self): + try: + conn = pgconnection.get_connection("apidata") + conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) + cursor = conn.cursor() + for item in self.data_response(): + + cursor.execute("""INSERT INTO city(name) + VALUE (%(name)s);""", item["city"]) + print("City inserted") + + cursor.execute("""INSERT INTO weather(cityid, weather_info, temp_in_celsius, wind_speed_kmph, dateadded) + VALUES (%(cityid)s, %(weather_info)s, %(temp_in_celsius)s, %(wind_speed_kmph)s, %(dateadded)s);""", item) + + cursor.close() + conn.close() + + except psycopg2.Error as e: + + print(type(e)) + + print(e) \ No newline at end of file diff --git a/index.py b/index.py index d3240a2..87539e3 100644 --- a/index.py +++ b/index.py @@ -26,9 +26,11 @@ def main(): if city and country: try: new_weather = WeatherApiClient(city) - news = NewsApiClient(country) except ApiNotAvailableException: new_weather = WeatherbitApiClient(city) + try: + news = NewsApiClient(country) + except ApiNotAvailableException: news = LentaParser() wind_info = new_weather.get_wind() weather_info = new_weather.get_weather_description() @@ -36,7 +38,7 @@ def main(): data = { "city": city, "country": country, - "hot_news": news.news_data, + "hot_news": news.get_top_news(), "local_weather": {"wind_info": wind_info, "weather_info": weather_info, "temperature_info": temperature_info diff --git a/news_api_client.py b/news_api_client.py index 3ca2a0c..c45f150 100644 --- a/news_api_client.py +++ b/news_api_client.py @@ -2,7 +2,6 @@ from conf import con_api_news from api_not_available import ApiNotAvailableException from ParentNews import ParentNews -from pprint import pprint class NewsApiClient(ParentNews): @@ -11,20 +10,20 @@ def __init__(self, country): self.country = country super().__init__() - def send_request(self): + def __send_request(self): response = requests.get(f"{con_api_news['url']}?country={self.country}&apiKey={con_api_news['api_key']}") if response.status_code != 200: - error_message = response.json()['error'] + error_message = response.json()['message'] raise ApiNotAvailableException(f"{error_message} occurred in NewsApiClient") else: - news_data = response.json() - news_data = news_data['articles'][0:] - pprint(news_data) - for news in news_data: - formatted_news = { - "title": news['title'], - "body": news['content'] - } - self.news_data.append(formatted_news) - pprint(self.news_data) - return self.news_data + self.news_data = response.json() + + def get_top_news(self): + output_news = [] + for news in self.news_data['articles'][0:]: + formatted_news = { + "title": news['title'], + "body": news['content'] + } + output_news.append(formatted_news) + return output_news diff --git a/pgconnection.py b/pgconnection.py new file mode 100644 index 0000000..ef10058 --- /dev/null +++ b/pgconnection.py @@ -0,0 +1,8 @@ +import psycopg2 + + +def get_connection(dbname): + + connect_str = "dbname={} host='localhost' user='postgres' password='123QWEasd'".format(dbname) + + return psycopg2.connect(connect_str) diff --git a/weather_api_client.py b/weather_api_client.py index 0940ced..818ad1b 100644 --- a/weather_api_client.py +++ b/weather_api_client.py @@ -7,7 +7,7 @@ class WeatherApiClient(ParentWeatherApi): BASE_URL = "{}current?access_key={}&query={}" - def send_request(self): + def __send_request(self): response = requests.get(self.BASE_URL.format(con['url'], con['api_key'], self.city)) if 'success' in response.json(): error_message = response.json()['error']['info'] diff --git a/weatherbit_api_client.py b/weatherbit_api_client.py index 08ac5f1..23a213c 100644 --- a/weatherbit_api_client.py +++ b/weatherbit_api_client.py @@ -7,7 +7,7 @@ class WeatherbitApiClient(ParentWeatherApi): BASE_URL = "{}?city={}&key={}" - def send_request(self): + def __send_request(self): response = requests.get(self.BASE_URL.format(con_wb['url'], self.city, con_wb['api_key'])) if response.status_code != 200: error_message = response.json()['error'] From 859e2f719b13ed7e8f655f026458ec5799f26f94 Mon Sep 17 00:00:00 2001 From: Dima Date: Sun, 21 Feb 2021 13:23:13 +0600 Subject: [PATCH 12/16] db_creation has been renewed with usage of sqlalchemy --- LentaParser.py | 2 +- ParentNews.py | 4 +-- ParentWeatherApi.py | 4 +-- conf.py | 2 +- db_creation.py | 74 ++++++++++++++++++---------------------- db_insert_data.py | 30 ++++++++++------ news_api_client.py | 2 +- weather_api_client.py | 2 +- weatherbit_api_client.py | 2 +- 9 files changed, 62 insertions(+), 60 deletions(-) diff --git a/LentaParser.py b/LentaParser.py index 1cc5b08..2b8e88b 100644 --- a/LentaParser.py +++ b/LentaParser.py @@ -8,7 +8,7 @@ class LentaParser(ParentNews): - def __send_request(self): + def _send_request(self): response = requests.get(f"{con_lenta['url']}") if response.status_code != 200: raise ApiNotAvailableException("Error occurred in LentaParser") diff --git a/ParentNews.py b/ParentNews.py index 0a6c22a..e07bfeb 100644 --- a/ParentNews.py +++ b/ParentNews.py @@ -5,8 +5,8 @@ class ParentNews(ABC): def __init__(self): self.news_data = [] - self.__send_request() + self._send_request() @abstractmethod - def __send_request(self): + def _send_request(self): raise NotImplementedError diff --git a/ParentWeatherApi.py b/ParentWeatherApi.py index bcb9ee6..cd2d319 100644 --- a/ParentWeatherApi.py +++ b/ParentWeatherApi.py @@ -6,10 +6,10 @@ class ParentWeatherApi(ABC): def __init__(self, city): self.weather_data = {} self.city = city - self.__send_request() + self._send_request() @abstractmethod - def __send_request(self): + def _send_request(self): raise NotImplementedError @abstractmethod diff --git a/conf.py b/conf.py index 6b71baf..792a9aa 100644 --- a/conf.py +++ b/conf.py @@ -11,7 +11,7 @@ } con_api_news = { - "api_key": "0ffe15ac03b847999aa821a7eb9044533", + "api_key": "0ffe15ac03b847999aa821a7eb904453", "url": "http://newsapi.org/v2/top-headlines" } diff --git a/db_creation.py b/db_creation.py index 7e742b6..e53a25b 100644 --- a/db_creation.py +++ b/db_creation.py @@ -1,56 +1,48 @@ -from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT -import psycopg2 +from sqlalchemy import create_engine, func, Column, Integer, String, ForeignKey, DateTime +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship -import pgconnection +Base = declarative_base() +engine = create_engine("postgresql://postgres:123QWEasd@localhost:5432/apidata") -def main(): - queries = ({"Description": "Create database", - "Database": "postgres", - "SQL": """CREATE DATABASE apidata"""}, +class Country(Base): + __tablename__ = "country" - {"Description": "Create city table ", - "Database": "apidata", - "SQL": """CREATE TABLE city(cityid serial PRIMARY KEY, name varchar(256) NOT NULL)"""}, + id = Column('id', Integer, primary_key=True) + name = Column('name', String, unique=True) + news = relationship("News", uselist=False, back_populates="country") - {"Description": "Create weather table ", - "Database": "apidata", - "SQL": """CREATE TABLE weather(weatherid serial PRIMARY KEY, - cityid smallint REFERENCES city(cityid) NOT NULL, - weather_info varchar(256) NOT NULL, - temp_in_celsius DECIMAL(3,1) NOT NULL, - wind_speed_kmph smallint NOT NULL, dateadded date)"""}, - {"Description": "Create country table ", - "Database": "apidata", - "SQL": """CREATE TABLE country(countryid serial PRIMARY KEY, name varchar(256) NOT NULL)"""}, +class News(Base): + __tablename__ = "news" - {"Description": "Create news table ", - "Database": "apidata", - "SQL": """CREATE TABLE news(newsid serial PRIMARY KEY, - countryid smallint REFERENCES country(countryid) NOT NULL, - title varchar(1024) NOT NULL, - body text NOT NULL, - dateadded date)"""}) + id = Column('id', Integer, primary_key=True) + country_id = Column(Integer, ForeignKey('country.id')) + country = relationship("Country", back_populates="news") + title = Column('title', String) + body = Column('body', String) + date = Column('dateadded', DateTime, onupdate=func.now()) - try: - for query in queries: - conn = pgconnection.get_connection(query["Database"]) - print(conn) - conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) - cursor = conn.cursor() +class City(Base): + __tablename__ = "city" - cursor.execute(query["SQL"]) + id = Column('id', Integer, primary_key=True) + name = Column('name', String, unique=True) + weather = relationship("Weather", uselist=False, back_populates="city") - print("Executed {}".format(query["Description"])) - cursor.close() - conn.close() +class Weather(Base): + __tablename__ = "weather" - except psycopg2.ProgrammingError as e: + id = Column('id', Integer, primary_key=True) + city_id = Column(Integer, ForeignKey('city.id')) + city = relationship("City", back_populates="weather") + weather_info = Column('weather_info', String) + temp_in_c = Column('temp_in_c', Integer) + wind_speed_kmph = Column('wind_speed_kmph', Integer) + date = Column('dateadded', DateTime, onupdate=func.now()) - print(e) - -main() +Base.metadata.create_all(bind=engine) diff --git a/db_insert_data.py b/db_insert_data.py index c93e5b9..6e14c05 100644 --- a/db_insert_data.py +++ b/db_insert_data.py @@ -1,23 +1,33 @@ +from weather_api_client import WeatherApiClient +from news_api_client import NewsApiClient +from weatherbit_api_client import WeatherbitApiClient +from LentaParser import LentaParser +from api_not_available import ApiNotAvailableException import datetime -import requests +from flask import request import psycopg2 from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT import sqlalchemy import pgconnection +import pycountry -class InsertData: - BASE_URL = "http://127.0.0.1:5000/main?city=Ottawa&country=ca" +class InsertData: def __init__(self): - self.data_response = {} - self.send_request() + self.gathered_apis_data = {} + + def gather_data_news_api(self): + countries = (country.alpha_2 for country in list(pycountry.countries)) + for country in countries: + try: + news = NewsApiClient(country) + except ApiNotAvailableException: + news = LentaParser() - def send_request(self): - response = requests.get(InsertData.BASE_URL) - self.data_response = response.json() - return self.data_response + def gather_apis_data(self): + return self.gathered_apis_data def insert_data(self): try: @@ -40,4 +50,4 @@ def insert_data(self): print(type(e)) - print(e) \ No newline at end of file + print(e) diff --git a/news_api_client.py b/news_api_client.py index c45f150..1466b27 100644 --- a/news_api_client.py +++ b/news_api_client.py @@ -10,7 +10,7 @@ def __init__(self, country): self.country = country super().__init__() - def __send_request(self): + def _send_request(self): response = requests.get(f"{con_api_news['url']}?country={self.country}&apiKey={con_api_news['api_key']}") if response.status_code != 200: error_message = response.json()['message'] diff --git a/weather_api_client.py b/weather_api_client.py index 818ad1b..9207d55 100644 --- a/weather_api_client.py +++ b/weather_api_client.py @@ -7,7 +7,7 @@ class WeatherApiClient(ParentWeatherApi): BASE_URL = "{}current?access_key={}&query={}" - def __send_request(self): + def _send_request(self): response = requests.get(self.BASE_URL.format(con['url'], con['api_key'], self.city)) if 'success' in response.json(): error_message = response.json()['error']['info'] diff --git a/weatherbit_api_client.py b/weatherbit_api_client.py index 23a213c..562a519 100644 --- a/weatherbit_api_client.py +++ b/weatherbit_api_client.py @@ -7,7 +7,7 @@ class WeatherbitApiClient(ParentWeatherApi): BASE_URL = "{}?city={}&key={}" - def __send_request(self): + def _send_request(self): response = requests.get(self.BASE_URL.format(con_wb['url'], self.city, con_wb['api_key'])) if response.status_code != 200: error_message = response.json()['error'] From aa4e6c34903d1c5f522b9a9e3776e97539c56e59 Mon Sep 17 00:00:00 2001 From: Dima Date: Sun, 21 Feb 2021 20:45:11 +0600 Subject: [PATCH 13/16] The class InsertData with two static methods have been realized with usage of sqlalchemy. Those methods made for the data insertion from requests to news_api and weather_api classes. --- country-capitals.json | 1 + db_creation.py | 2 +- db_insert_data.py | 103 ++++++++++++++++++++++++++---------------- news_api_client.py | 2 +- 4 files changed, 67 insertions(+), 41 deletions(-) create mode 100644 country-capitals.json diff --git a/country-capitals.json b/country-capitals.json new file mode 100644 index 0000000..542c08c --- /dev/null +++ b/country-capitals.json @@ -0,0 +1 @@ +[{"CountryName":"Somaliland","CapitalName":"Hargeisa","CapitalLatitude":"9.55","CapitalLongitude":"44.050000","CountryCode":"NULL","ContinentName":"Africa"},{"CountryName":"South Georgia and South Sandwich Islands","CapitalName":"King Edward Point","CapitalLatitude":"-54.283333","CapitalLongitude":"-36.500000","CountryCode":"GS","ContinentName":"Antarctica"},{"CountryName":"French Southern and Antarctic Lands","CapitalName":"Port-aux-Français","CapitalLatitude":"-49.35","CapitalLongitude":"70.216667","CountryCode":"TF","ContinentName":"Antarctica"},{"CountryName":"Palestine","CapitalName":"Jerusalem","CapitalLatitude":"31.766666666666666","CapitalLongitude":"35.233333","CountryCode":"PS","ContinentName":"Asia"},{"CountryName":"Aland Islands","CapitalName":"Mariehamn","CapitalLatitude":"60.116667","CapitalLongitude":"19.900000","CountryCode":"AX","ContinentName":"Europe"},{"CountryName":"Nauru","CapitalName":"Yaren","CapitalLatitude":"-0.5477","CapitalLongitude":"166.920867","CountryCode":"NR","ContinentName":"Australia"},{"CountryName":"Saint Martin","CapitalName":"Marigot","CapitalLatitude":"18.0731","CapitalLongitude":"-63.082200","CountryCode":"MF","ContinentName":"North America"},{"CountryName":"Tokelau","CapitalName":"Atafu","CapitalLatitude":"-9.166667","CapitalLongitude":"-171.833333","CountryCode":"TK","ContinentName":"Australia"},{"CountryName":"Western Sahara","CapitalName":"El-Aaiún","CapitalLatitude":"27.153611","CapitalLongitude":"-13.203333","CountryCode":"EH","ContinentName":"Africa"},{"CountryName":"Afghanistan","CapitalName":"Kabul","CapitalLatitude":"34.516666666666666","CapitalLongitude":"69.183333","CountryCode":"AF","ContinentName":"Asia"},{"CountryName":"Albania","CapitalName":"Tirana","CapitalLatitude":"41.31666666666667","CapitalLongitude":"19.816667","CountryCode":"AL","ContinentName":"Europe"},{"CountryName":"Algeria","CapitalName":"Algiers","CapitalLatitude":"36.75","CapitalLongitude":"3.050000","CountryCode":"DZ","ContinentName":"Africa"},{"CountryName":"American Samoa","CapitalName":"Pago Pago","CapitalLatitude":"-14.266666666666667","CapitalLongitude":"-170.700000","CountryCode":"AS","ContinentName":"Australia"},{"CountryName":"Andorra","CapitalName":"Andorra la Vella","CapitalLatitude":"42.5","CapitalLongitude":"1.516667","CountryCode":"AD","ContinentName":"Europe"},{"CountryName":"Angola","CapitalName":"Luanda","CapitalLatitude":"-8.833333333333334","CapitalLongitude":"13.216667","CountryCode":"AO","ContinentName":"Africa"},{"CountryName":"Anguilla","CapitalName":"The Valley","CapitalLatitude":"18.216666666666665","CapitalLongitude":"-63.050000","CountryCode":"AI","ContinentName":"North America"},{"CountryName":"Antigua and Barbuda","CapitalName":"Saint John's","CapitalLatitude":"17.116666666666667","CapitalLongitude":"-61.850000","CountryCode":"AG","ContinentName":"North America"},{"CountryName":"Argentina","CapitalName":"Buenos Aires","CapitalLatitude":"-34.583333333333336","CapitalLongitude":"-58.666667","CountryCode":"AR","ContinentName":"South America"},{"CountryName":"Armenia","CapitalName":"Yerevan","CapitalLatitude":"40.166666666666664","CapitalLongitude":"44.500000","CountryCode":"AM","ContinentName":"Europe"},{"CountryName":"Aruba","CapitalName":"Oranjestad","CapitalLatitude":"12.516666666666667","CapitalLongitude":"-70.033333","CountryCode":"AW","ContinentName":"North America"},{"CountryName":"Australia","CapitalName":"Canberra","CapitalLatitude":"-35.266666666666666","CapitalLongitude":"149.133333","CountryCode":"AU","ContinentName":"Australia"},{"CountryName":"Austria","CapitalName":"Vienna","CapitalLatitude":"48.2","CapitalLongitude":"16.366667","CountryCode":"AT","ContinentName":"Europe"},{"CountryName":"Azerbaijan","CapitalName":"Baku","CapitalLatitude":"40.38333333333333","CapitalLongitude":"49.866667","CountryCode":"AZ","ContinentName":"Europe"},{"CountryName":"Bahamas","CapitalName":"Nassau","CapitalLatitude":"25.083333333333332","CapitalLongitude":"-77.350000","CountryCode":"BS","ContinentName":"North America"},{"CountryName":"Bahrain","CapitalName":"Manama","CapitalLatitude":"26.233333333333334","CapitalLongitude":"50.566667","CountryCode":"BH","ContinentName":"Asia"},{"CountryName":"Bangladesh","CapitalName":"Dhaka","CapitalLatitude":"23.716666666666665","CapitalLongitude":"90.400000","CountryCode":"BD","ContinentName":"Asia"},{"CountryName":"Barbados","CapitalName":"Bridgetown","CapitalLatitude":"13.1","CapitalLongitude":"-59.616667","CountryCode":"BB","ContinentName":"North America"},{"CountryName":"Belarus","CapitalName":"Minsk","CapitalLatitude":"53.9","CapitalLongitude":"27.566667","CountryCode":"BY","ContinentName":"Europe"},{"CountryName":"Belgium","CapitalName":"Brussels","CapitalLatitude":"50.833333333333336","CapitalLongitude":"4.333333","CountryCode":"BE","ContinentName":"Europe"},{"CountryName":"Belize","CapitalName":"Belmopan","CapitalLatitude":"17.25","CapitalLongitude":"-88.766667","CountryCode":"BZ","ContinentName":"Central America"},{"CountryName":"Benin","CapitalName":"Porto-Novo","CapitalLatitude":"6.483333333333333","CapitalLongitude":"2.616667","CountryCode":"BJ","ContinentName":"Africa"},{"CountryName":"Bermuda","CapitalName":"Hamilton","CapitalLatitude":"32.28333333333333","CapitalLongitude":"-64.783333","CountryCode":"BM","ContinentName":"North America"},{"CountryName":"Bhutan","CapitalName":"Thimphu","CapitalLatitude":"27.466666666666665","CapitalLongitude":"89.633333","CountryCode":"BT","ContinentName":"Asia"},{"CountryName":"Bolivia","CapitalName":"La Paz","CapitalLatitude":"-16.5","CapitalLongitude":"-68.150000","CountryCode":"BO","ContinentName":"South America"},{"CountryName":"Bosnia and Herzegovina","CapitalName":"Sarajevo","CapitalLatitude":"43.86666666666667","CapitalLongitude":"18.416667","CountryCode":"BA","ContinentName":"Europe"},{"CountryName":"Botswana","CapitalName":"Gaborone","CapitalLatitude":"-24.633333333333333","CapitalLongitude":"25.900000","CountryCode":"BW","ContinentName":"Africa"},{"CountryName":"Brazil","CapitalName":"Brasilia","CapitalLatitude":"-15.783333333333333","CapitalLongitude":"-47.916667","CountryCode":"BR","ContinentName":"South America"},{"CountryName":"British Virgin Islands","CapitalName":"Road Town","CapitalLatitude":"18.416666666666668","CapitalLongitude":"-64.616667","CountryCode":"VG","ContinentName":"North America"},{"CountryName":"Brunei Darussalam","CapitalName":"Bandar Seri Begawan","CapitalLatitude":"4.883333333333333","CapitalLongitude":"114.933333","CountryCode":"BN","ContinentName":"Asia"},{"CountryName":"Bulgaria","CapitalName":"Sofia","CapitalLatitude":"42.68333333333333","CapitalLongitude":"23.316667","CountryCode":"BG","ContinentName":"Europe"},{"CountryName":"Burkina Faso","CapitalName":"Ouagadougou","CapitalLatitude":"12.366666666666667","CapitalLongitude":"-1.516667","CountryCode":"BF","ContinentName":"Africa"},{"CountryName":"Myanmar","CapitalName":"Rangoon","CapitalLatitude":"16.8","CapitalLongitude":"96.150000","CountryCode":"MM","ContinentName":"Asia"},{"CountryName":"Burundi","CapitalName":"Bujumbura","CapitalLatitude":"-3.3666666666666667","CapitalLongitude":"29.350000","CountryCode":"BI","ContinentName":"Africa"},{"CountryName":"Cambodia","CapitalName":"Phnom Penh","CapitalLatitude":"11.55","CapitalLongitude":"104.916667","CountryCode":"KH","ContinentName":"Asia"},{"CountryName":"Cameroon","CapitalName":"Yaounde","CapitalLatitude":"3.8666666666666667","CapitalLongitude":"11.516667","CountryCode":"CM","ContinentName":"Africa"},{"CountryName":"Canada","CapitalName":"Ottawa","CapitalLatitude":"45.416666666666664","CapitalLongitude":"-75.700000","CountryCode":"CA","ContinentName":"Central America"},{"CountryName":"Cape Verde","CapitalName":"Praia","CapitalLatitude":"14.916666666666666","CapitalLongitude":"-23.516667","CountryCode":"CV","ContinentName":"Africa"},{"CountryName":"Cayman Islands","CapitalName":"George Town","CapitalLatitude":"19.3","CapitalLongitude":"-81.383333","CountryCode":"KY","ContinentName":"North America"},{"CountryName":"Central African Republic","CapitalName":"Bangui","CapitalLatitude":"4.366666666666666","CapitalLongitude":"18.583333","CountryCode":"CF","ContinentName":"Africa"},{"CountryName":"Chad","CapitalName":"N'Djamena","CapitalLatitude":"12.1","CapitalLongitude":"15.033333","CountryCode":"TD","ContinentName":"Africa"},{"CountryName":"Chile","CapitalName":"Santiago","CapitalLatitude":"-33.45","CapitalLongitude":"-70.666667","CountryCode":"CL","ContinentName":"South America"},{"CountryName":"China","CapitalName":"Beijing","CapitalLatitude":"39.916666666666664","CapitalLongitude":"116.383333","CountryCode":"CN","ContinentName":"Asia"},{"CountryName":"Christmas Island","CapitalName":"The Settlement","CapitalLatitude":"-10.416666666666666","CapitalLongitude":"105.716667","CountryCode":"CX","ContinentName":"Australia"},{"CountryName":"Cocos Islands","CapitalName":"West Island","CapitalLatitude":"-12.166666666666666","CapitalLongitude":"96.833333","CountryCode":"CC","ContinentName":"Australia"},{"CountryName":"Colombia","CapitalName":"Bogota","CapitalLatitude":"4.6","CapitalLongitude":"-74.083333","CountryCode":"CO","ContinentName":"South America"},{"CountryName":"Comoros","CapitalName":"Moroni","CapitalLatitude":"-11.7","CapitalLongitude":"43.233333","CountryCode":"KM","ContinentName":"Africa"},{"CountryName":"Democratic Republic of the Congo","CapitalName":"Kinshasa","CapitalLatitude":"-4.316666666666666","CapitalLongitude":"15.300000","CountryCode":"CD","ContinentName":"Africa"},{"CountryName":"Republic of Congo","CapitalName":"Brazzaville","CapitalLatitude":"-4.25","CapitalLongitude":"15.283333","CountryCode":"CG","ContinentName":"Africa"},{"CountryName":"Cook Islands","CapitalName":"Avarua","CapitalLatitude":"-21.2","CapitalLongitude":"-159.766667","CountryCode":"CK","ContinentName":"Australia"},{"CountryName":"Costa Rica","CapitalName":"San Jose","CapitalLatitude":"9.933333333333334","CapitalLongitude":"-84.083333","CountryCode":"CR","ContinentName":"Central America"},{"CountryName":"Cote d'Ivoire","CapitalName":"Yamoussoukro","CapitalLatitude":"6.816666666666666","CapitalLongitude":"-5.266667","CountryCode":"CI","ContinentName":"Africa"},{"CountryName":"Croatia","CapitalName":"Zagreb","CapitalLatitude":"45.8","CapitalLongitude":"16.000000","CountryCode":"HR","ContinentName":"Europe"},{"CountryName":"Cuba","CapitalName":"Havana","CapitalLatitude":"23.116666666666667","CapitalLongitude":"-82.350000","CountryCode":"CU","ContinentName":"North America"},{"CountryName":"Curaçao","CapitalName":"Willemstad","CapitalLatitude":"12.1","CapitalLongitude":"-68.916667","CountryCode":"CW","ContinentName":"North America"},{"CountryName":"Cyprus","CapitalName":"Nicosia","CapitalLatitude":"35.166666666666664","CapitalLongitude":"33.366667","CountryCode":"CY","ContinentName":"Europe"},{"CountryName":"Czech Republic","CapitalName":"Prague","CapitalLatitude":"50.083333333333336","CapitalLongitude":"14.466667","CountryCode":"CZ","ContinentName":"Europe"},{"CountryName":"Denmark","CapitalName":"Copenhagen","CapitalLatitude":"55.666666666666664","CapitalLongitude":"12.583333","CountryCode":"DK","ContinentName":"Europe"},{"CountryName":"Djibouti","CapitalName":"Djibouti","CapitalLatitude":"11.583333333333334","CapitalLongitude":"43.150000","CountryCode":"DJ","ContinentName":"Africa"},{"CountryName":"Dominica","CapitalName":"Roseau","CapitalLatitude":"15.3","CapitalLongitude":"-61.400000","CountryCode":"DM","ContinentName":"North America"},{"CountryName":"Dominican Republic","CapitalName":"Santo Domingo","CapitalLatitude":"18.466666666666665","CapitalLongitude":"-69.900000","CountryCode":"DO","ContinentName":"North America"},{"CountryName":"Ecuador","CapitalName":"Quito","CapitalLatitude":"-0.21666666666666667","CapitalLongitude":"-78.500000","CountryCode":"EC","ContinentName":"South America"},{"CountryName":"Egypt","CapitalName":"Cairo","CapitalLatitude":"30.05","CapitalLongitude":"31.250000","CountryCode":"EG","ContinentName":"Africa"},{"CountryName":"El Salvador","CapitalName":"San Salvador","CapitalLatitude":"13.7","CapitalLongitude":"-89.200000","CountryCode":"SV","ContinentName":"Central America"},{"CountryName":"Equatorial Guinea","CapitalName":"Malabo","CapitalLatitude":"3.75","CapitalLongitude":"8.783333","CountryCode":"GQ","ContinentName":"Africa"},{"CountryName":"Eritrea","CapitalName":"Asmara","CapitalLatitude":"15.333333333333334","CapitalLongitude":"38.933333","CountryCode":"ER","ContinentName":"Africa"},{"CountryName":"Estonia","CapitalName":"Tallinn","CapitalLatitude":"59.43333333333333","CapitalLongitude":"24.716667","CountryCode":"EE","ContinentName":"Europe"},{"CountryName":"Ethiopia","CapitalName":"Addis Ababa","CapitalLatitude":"9.033333333333333","CapitalLongitude":"38.700000","CountryCode":"ET","ContinentName":"Africa"},{"CountryName":"Falkland Islands","CapitalName":"Stanley","CapitalLatitude":"-51.7","CapitalLongitude":"-57.850000","CountryCode":"FK","ContinentName":"South America"},{"CountryName":"Faroe Islands","CapitalName":"Torshavn","CapitalLatitude":"62","CapitalLongitude":"-6.766667","CountryCode":"FO","ContinentName":"Europe"},{"CountryName":"Fiji","CapitalName":"Suva","CapitalLatitude":"-18.133333333333333","CapitalLongitude":"178.416667","CountryCode":"FJ","ContinentName":"Australia"},{"CountryName":"Finland","CapitalName":"Helsinki","CapitalLatitude":"60.166666666666664","CapitalLongitude":"24.933333","CountryCode":"FI","ContinentName":"Europe"},{"CountryName":"France","CapitalName":"Paris","CapitalLatitude":"48.86666666666667","CapitalLongitude":"2.333333","CountryCode":"FR","ContinentName":"Europe"},{"CountryName":"French Polynesia","CapitalName":"Papeete","CapitalLatitude":"-17.533333333333335","CapitalLongitude":"-149.566667","CountryCode":"PF","ContinentName":"Australia"},{"CountryName":"Gabon","CapitalName":"Libreville","CapitalLatitude":"0.38333333333333336","CapitalLongitude":"9.450000","CountryCode":"GA","ContinentName":"Africa"},{"CountryName":"The Gambia","CapitalName":"Banjul","CapitalLatitude":"13.45","CapitalLongitude":"-16.566667","CountryCode":"GM","ContinentName":"Africa"},{"CountryName":"Georgia","CapitalName":"Tbilisi","CapitalLatitude":"41.68333333333333","CapitalLongitude":"44.833333","CountryCode":"GE","ContinentName":"Europe"},{"CountryName":"Germany","CapitalName":"Berlin","CapitalLatitude":"52.516666666666666","CapitalLongitude":"13.400000","CountryCode":"DE","ContinentName":"Europe"},{"CountryName":"Ghana","CapitalName":"Accra","CapitalLatitude":"5.55","CapitalLongitude":"-0.216667","CountryCode":"GH","ContinentName":"Africa"},{"CountryName":"Gibraltar","CapitalName":"Gibraltar","CapitalLatitude":"36.13333333333333","CapitalLongitude":"-5.350000","CountryCode":"GI","ContinentName":"Europe"},{"CountryName":"Greece","CapitalName":"Athens","CapitalLatitude":"37.983333333333334","CapitalLongitude":"23.733333","CountryCode":"GR","ContinentName":"Europe"},{"CountryName":"Greenland","CapitalName":"Nuuk","CapitalLatitude":"64.18333333333334","CapitalLongitude":"-51.750000","CountryCode":"GL","ContinentName":"Central America"},{"CountryName":"Grenada","CapitalName":"Saint George's","CapitalLatitude":"12.05","CapitalLongitude":"-61.750000","CountryCode":"GD","ContinentName":"North America"},{"CountryName":"Guam","CapitalName":"Hagatna","CapitalLatitude":"13.466666666666667","CapitalLongitude":"144.733333","CountryCode":"GU","ContinentName":"Australia"},{"CountryName":"Guatemala","CapitalName":"Guatemala City","CapitalLatitude":"14.616666666666667","CapitalLongitude":"-90.516667","CountryCode":"GT","ContinentName":"Central America"},{"CountryName":"Guernsey","CapitalName":"Saint Peter Port","CapitalLatitude":"49.45","CapitalLongitude":"-2.533333","CountryCode":"GG","ContinentName":"Europe"},{"CountryName":"Guinea","CapitalName":"Conakry","CapitalLatitude":"9.5","CapitalLongitude":"-13.700000","CountryCode":"GN","ContinentName":"Africa"},{"CountryName":"Guinea-Bissau","CapitalName":"Bissau","CapitalLatitude":"11.85","CapitalLongitude":"-15.583333","CountryCode":"GW","ContinentName":"Africa"},{"CountryName":"Guyana","CapitalName":"Georgetown","CapitalLatitude":"6.8","CapitalLongitude":"-58.150000","CountryCode":"GY","ContinentName":"South America"},{"CountryName":"Haiti","CapitalName":"Port-au-Prince","CapitalLatitude":"18.533333333333335","CapitalLongitude":"-72.333333","CountryCode":"HT","ContinentName":"North America"},{"CountryName":"Vatican City","CapitalName":"Vatican City","CapitalLatitude":"41.9","CapitalLongitude":"12.450000","CountryCode":"VA","ContinentName":"Europe"},{"CountryName":"Honduras","CapitalName":"Tegucigalpa","CapitalLatitude":"14.1","CapitalLongitude":"-87.216667","CountryCode":"HN","ContinentName":"Central America"},{"CountryName":"Hungary","CapitalName":"Budapest","CapitalLatitude":"47.5","CapitalLongitude":"19.083333","CountryCode":"HU","ContinentName":"Europe"},{"CountryName":"Iceland","CapitalName":"Reykjavik","CapitalLatitude":"64.15","CapitalLongitude":"-21.950000","CountryCode":"IS","ContinentName":"Europe"},{"CountryName":"India","CapitalName":"New Delhi","CapitalLatitude":"28.6","CapitalLongitude":"77.200000","CountryCode":"IN","ContinentName":"Asia"},{"CountryName":"Indonesia","CapitalName":"Jakarta","CapitalLatitude":"-6.166666666666667","CapitalLongitude":"106.816667","CountryCode":"ID","ContinentName":"Asia"},{"CountryName":"Iran","CapitalName":"Tehran","CapitalLatitude":"35.7","CapitalLongitude":"51.416667","CountryCode":"IR","ContinentName":"Asia"},{"CountryName":"Iraq","CapitalName":"Baghdad","CapitalLatitude":"33.333333333333336","CapitalLongitude":"44.400000","CountryCode":"IQ","ContinentName":"Asia"},{"CountryName":"Ireland","CapitalName":"Dublin","CapitalLatitude":"53.31666666666667","CapitalLongitude":"-6.233333","CountryCode":"IE","ContinentName":"Europe"},{"CountryName":"Isle of Man","CapitalName":"Douglas","CapitalLatitude":"54.15","CapitalLongitude":"-4.483333","CountryCode":"IM","ContinentName":"Europe"},{"CountryName":"Israel","CapitalName":"Jerusalem","CapitalLatitude":"31.766666666666666","CapitalLongitude":"35.233333","CountryCode":"IL","ContinentName":"Asia"},{"CountryName":"Italy","CapitalName":"Rome","CapitalLatitude":"41.9","CapitalLongitude":"12.483333","CountryCode":"IT","ContinentName":"Europe"},{"CountryName":"Jamaica","CapitalName":"Kingston","CapitalLatitude":"18","CapitalLongitude":"-76.800000","CountryCode":"JM","ContinentName":"North America"},{"CountryName":"Japan","CapitalName":"Tokyo","CapitalLatitude":"35.68333333333333","CapitalLongitude":"139.750000","CountryCode":"JP","ContinentName":"Asia"},{"CountryName":"Jersey","CapitalName":"Saint Helier","CapitalLatitude":"49.18333333333333","CapitalLongitude":"-2.100000","CountryCode":"JE","ContinentName":"Europe"},{"CountryName":"Jordan","CapitalName":"Amman","CapitalLatitude":"31.95","CapitalLongitude":"35.933333","CountryCode":"JO","ContinentName":"Asia"},{"CountryName":"Kazakhstan","CapitalName":"Astana","CapitalLatitude":"51.166666666666664","CapitalLongitude":"71.416667","CountryCode":"KZ","ContinentName":"Asia"},{"CountryName":"Kenya","CapitalName":"Nairobi","CapitalLatitude":"-1.2833333333333332","CapitalLongitude":"36.816667","CountryCode":"KE","ContinentName":"Africa"},{"CountryName":"Kiribati","CapitalName":"Tarawa","CapitalLatitude":"-0.8833333333333333","CapitalLongitude":"169.533333","CountryCode":"KI","ContinentName":"Australia"},{"CountryName":"North Korea","CapitalName":"Pyongyang","CapitalLatitude":"39.016666666666666","CapitalLongitude":"125.750000","CountryCode":"KP","ContinentName":"Asia"},{"CountryName":"South Korea","CapitalName":"Seoul","CapitalLatitude":"37.55","CapitalLongitude":"126.983333","CountryCode":"KR","ContinentName":"Asia"},{"CountryName":"Kosovo","CapitalName":"Pristina","CapitalLatitude":"42.666666666666664","CapitalLongitude":"21.166667","CountryCode":"KO","ContinentName":"Europe"},{"CountryName":"Kuwait","CapitalName":"Kuwait City","CapitalLatitude":"29.366666666666667","CapitalLongitude":"47.966667","CountryCode":"KW","ContinentName":"Asia"},{"CountryName":"Kyrgyzstan","CapitalName":"Bishkek","CapitalLatitude":"42.86666666666667","CapitalLongitude":"74.600000","CountryCode":"KG","ContinentName":"Asia"},{"CountryName":"Laos","CapitalName":"Vientiane","CapitalLatitude":"17.966666666666665","CapitalLongitude":"102.600000","CountryCode":"LA","ContinentName":"Asia"},{"CountryName":"Latvia","CapitalName":"Riga","CapitalLatitude":"56.95","CapitalLongitude":"24.100000","CountryCode":"LV","ContinentName":"Europe"},{"CountryName":"Lebanon","CapitalName":"Beirut","CapitalLatitude":"33.86666666666667","CapitalLongitude":"35.500000","CountryCode":"LB","ContinentName":"Asia"},{"CountryName":"Lesotho","CapitalName":"Maseru","CapitalLatitude":"-29.316666666666666","CapitalLongitude":"27.483333","CountryCode":"LS","ContinentName":"Africa"},{"CountryName":"Liberia","CapitalName":"Monrovia","CapitalLatitude":"6.3","CapitalLongitude":"-10.800000","CountryCode":"LR","ContinentName":"Africa"},{"CountryName":"Libya","CapitalName":"Tripoli","CapitalLatitude":"32.88333333333333","CapitalLongitude":"13.166667","CountryCode":"LY","ContinentName":"Africa"},{"CountryName":"Liechtenstein","CapitalName":"Vaduz","CapitalLatitude":"47.13333333333333","CapitalLongitude":"9.516667","CountryCode":"LI","ContinentName":"Europe"},{"CountryName":"Lithuania","CapitalName":"Vilnius","CapitalLatitude":"54.68333333333333","CapitalLongitude":"25.316667","CountryCode":"LT","ContinentName":"Europe"},{"CountryName":"Luxembourg","CapitalName":"Luxembourg","CapitalLatitude":"49.6","CapitalLongitude":"6.116667","CountryCode":"LU","ContinentName":"Europe"},{"CountryName":"Macedonia","CapitalName":"Skopje","CapitalLatitude":"42","CapitalLongitude":"21.433333","CountryCode":"MK","ContinentName":"Europe"},{"CountryName":"Madagascar","CapitalName":"Antananarivo","CapitalLatitude":"-18.916666666666668","CapitalLongitude":"47.516667","CountryCode":"MG","ContinentName":"Africa"},{"CountryName":"Malawi","CapitalName":"Lilongwe","CapitalLatitude":"-13.966666666666667","CapitalLongitude":"33.783333","CountryCode":"MW","ContinentName":"Africa"},{"CountryName":"Malaysia","CapitalName":"Kuala Lumpur","CapitalLatitude":"3.1666666666666665","CapitalLongitude":"101.700000","CountryCode":"MY","ContinentName":"Asia"},{"CountryName":"Maldives","CapitalName":"Male","CapitalLatitude":"4.166666666666667","CapitalLongitude":"73.500000","CountryCode":"MV","ContinentName":"Asia"},{"CountryName":"Mali","CapitalName":"Bamako","CapitalLatitude":"12.65","CapitalLongitude":"-8.000000","CountryCode":"ML","ContinentName":"Africa"},{"CountryName":"Malta","CapitalName":"Valletta","CapitalLatitude":"35.88333333333333","CapitalLongitude":"14.500000","CountryCode":"MT","ContinentName":"Europe"},{"CountryName":"Marshall Islands","CapitalName":"Majuro","CapitalLatitude":"7.1","CapitalLongitude":"171.383333","CountryCode":"MH","ContinentName":"Australia"},{"CountryName":"Mauritania","CapitalName":"Nouakchott","CapitalLatitude":"18.066666666666666","CapitalLongitude":"-15.966667","CountryCode":"MR","ContinentName":"Africa"},{"CountryName":"Mauritius","CapitalName":"Port Louis","CapitalLatitude":"-20.15","CapitalLongitude":"57.483333","CountryCode":"MU","ContinentName":"Africa"},{"CountryName":"Mexico","CapitalName":"Mexico City","CapitalLatitude":"19.433333333333334","CapitalLongitude":"-99.133333","CountryCode":"MX","ContinentName":"Central America"},{"CountryName":"Federated States of Micronesia","CapitalName":"Palikir","CapitalLatitude":"6.916666666666667","CapitalLongitude":"158.150000","CountryCode":"FM","ContinentName":"Australia"},{"CountryName":"Moldova","CapitalName":"Chisinau","CapitalLatitude":"47","CapitalLongitude":"28.850000","CountryCode":"MD","ContinentName":"Europe"},{"CountryName":"Monaco","CapitalName":"Monaco","CapitalLatitude":"43.733333333333334","CapitalLongitude":"7.416667","CountryCode":"MC","ContinentName":"Europe"},{"CountryName":"Mongolia","CapitalName":"Ulaanbaatar","CapitalLatitude":"47.916666666666664","CapitalLongitude":"106.916667","CountryCode":"MN","ContinentName":"Asia"},{"CountryName":"Montenegro","CapitalName":"Podgorica","CapitalLatitude":"42.43333333333333","CapitalLongitude":"19.266667","CountryCode":"ME","ContinentName":"Europe"},{"CountryName":"Montserrat","CapitalName":"Plymouth","CapitalLatitude":"16.7","CapitalLongitude":"-62.216667","CountryCode":"MS","ContinentName":"North America"},{"CountryName":"Morocco","CapitalName":"Rabat","CapitalLatitude":"34.016666666666666","CapitalLongitude":"-6.816667","CountryCode":"MA","ContinentName":"Africa"},{"CountryName":"Mozambique","CapitalName":"Maputo","CapitalLatitude":"-25.95","CapitalLongitude":"32.583333","CountryCode":"MZ","ContinentName":"Africa"},{"CountryName":"Namibia","CapitalName":"Windhoek","CapitalLatitude":"-22.566666666666666","CapitalLongitude":"17.083333","CountryCode":"NA","ContinentName":"Africa"},{"CountryName":"Nepal","CapitalName":"Kathmandu","CapitalLatitude":"27.716666666666665","CapitalLongitude":"85.316667","CountryCode":"NP","ContinentName":"Asia"},{"CountryName":"Netherlands","CapitalName":"Amsterdam","CapitalLatitude":"52.35","CapitalLongitude":"4.916667","CountryCode":"NL","ContinentName":"Europe"},{"CountryName":"New Caledonia","CapitalName":"Noumea","CapitalLatitude":"-22.266666666666666","CapitalLongitude":"166.450000","CountryCode":"NC","ContinentName":"Australia"},{"CountryName":"New Zealand","CapitalName":"Wellington","CapitalLatitude":"-41.3","CapitalLongitude":"174.783333","CountryCode":"NZ","ContinentName":"Australia"},{"CountryName":"Nicaragua","CapitalName":"Managua","CapitalLatitude":"12.133333333333333","CapitalLongitude":"-86.250000","CountryCode":"NI","ContinentName":"Central America"},{"CountryName":"Niger","CapitalName":"Niamey","CapitalLatitude":"13.516666666666667","CapitalLongitude":"2.116667","CountryCode":"NE","ContinentName":"Africa"},{"CountryName":"Nigeria","CapitalName":"Abuja","CapitalLatitude":"9.083333333333334","CapitalLongitude":"7.533333","CountryCode":"NG","ContinentName":"Africa"},{"CountryName":"Niue","CapitalName":"Alofi","CapitalLatitude":"-19.016666666666666","CapitalLongitude":"-169.916667","CountryCode":"NU","ContinentName":"Australia"},{"CountryName":"Norfolk Island","CapitalName":"Kingston","CapitalLatitude":"-29.05","CapitalLongitude":"167.966667","CountryCode":"NF","ContinentName":"Australia"},{"CountryName":"Northern Mariana Islands","CapitalName":"Saipan","CapitalLatitude":"15.2","CapitalLongitude":"145.750000","CountryCode":"MP","ContinentName":"Australia"},{"CountryName":"Norway","CapitalName":"Oslo","CapitalLatitude":"59.916666666666664","CapitalLongitude":"10.750000","CountryCode":"NO","ContinentName":"Europe"},{"CountryName":"Oman","CapitalName":"Muscat","CapitalLatitude":"23.616666666666667","CapitalLongitude":"58.583333","CountryCode":"OM","ContinentName":"Asia"},{"CountryName":"Pakistan","CapitalName":"Islamabad","CapitalLatitude":"33.68333333333333","CapitalLongitude":"73.050000","CountryCode":"PK","ContinentName":"Asia"},{"CountryName":"Palau","CapitalName":"Melekeok","CapitalLatitude":"7.483333333333333","CapitalLongitude":"134.633333","CountryCode":"PW","ContinentName":"Australia"},{"CountryName":"Panama","CapitalName":"Panama City","CapitalLatitude":"8.966666666666667","CapitalLongitude":"-79.533333","CountryCode":"PA","ContinentName":"Central America"},{"CountryName":"Papua New Guinea","CapitalName":"Port Moresby","CapitalLatitude":"-9.45","CapitalLongitude":"147.183333","CountryCode":"PG","ContinentName":"Australia"},{"CountryName":"Paraguay","CapitalName":"Asuncion","CapitalLatitude":"-25.266666666666666","CapitalLongitude":"-57.666667","CountryCode":"PY","ContinentName":"South America"},{"CountryName":"Peru","CapitalName":"Lima","CapitalLatitude":"-12.05","CapitalLongitude":"-77.050000","CountryCode":"PE","ContinentName":"South America"},{"CountryName":"Philippines","CapitalName":"Manila","CapitalLatitude":"14.6","CapitalLongitude":"120.966667","CountryCode":"PH","ContinentName":"Asia"},{"CountryName":"Pitcairn Islands","CapitalName":"Adamstown","CapitalLatitude":"-25.066666666666666","CapitalLongitude":"-130.083333","CountryCode":"PN","ContinentName":"Australia"},{"CountryName":"Poland","CapitalName":"Warsaw","CapitalLatitude":"52.25","CapitalLongitude":"21.000000","CountryCode":"PL","ContinentName":"Europe"},{"CountryName":"Portugal","CapitalName":"Lisbon","CapitalLatitude":"38.71666666666667","CapitalLongitude":"-9.133333","CountryCode":"PT","ContinentName":"Europe"},{"CountryName":"Puerto Rico","CapitalName":"San Juan","CapitalLatitude":"18.466666666666665","CapitalLongitude":"-66.116667","CountryCode":"PR","ContinentName":"North America"},{"CountryName":"Qatar","CapitalName":"Doha","CapitalLatitude":"25.283333333333335","CapitalLongitude":"51.533333","CountryCode":"QA","ContinentName":"Asia"},{"CountryName":"Romania","CapitalName":"Bucharest","CapitalLatitude":"44.43333333333333","CapitalLongitude":"26.100000","CountryCode":"RO","ContinentName":"Europe"},{"CountryName":"Russia","CapitalName":"Moscow","CapitalLatitude":"55.75","CapitalLongitude":"37.600000","CountryCode":"RU","ContinentName":"Europe"},{"CountryName":"Rwanda","CapitalName":"Kigali","CapitalLatitude":"-1.95","CapitalLongitude":"30.050000","CountryCode":"RW","ContinentName":"Africa"},{"CountryName":"Saint Barthelemy","CapitalName":"Gustavia","CapitalLatitude":"17.883333333333333","CapitalLongitude":"-62.850000","CountryCode":"BL","ContinentName":"North America"},{"CountryName":"Saint Helena","CapitalName":"Jamestown","CapitalLatitude":"-15.933333333333334","CapitalLongitude":"-5.716667","CountryCode":"SH","ContinentName":"Africa"},{"CountryName":"Saint Kitts and Nevis","CapitalName":"Basseterre","CapitalLatitude":"17.3","CapitalLongitude":"-62.716667","CountryCode":"KN","ContinentName":"North America"},{"CountryName":"Saint Lucia","CapitalName":"Castries","CapitalLatitude":"14","CapitalLongitude":"-61.000000","CountryCode":"LC","ContinentName":"North America"},{"CountryName":"Saint Pierre and Miquelon","CapitalName":"Saint-Pierre","CapitalLatitude":"46.766666666666666","CapitalLongitude":"-56.183333","CountryCode":"PM","ContinentName":"Central America"},{"CountryName":"Saint Vincent and the Grenadines","CapitalName":"Kingstown","CapitalLatitude":"13.133333333333333","CapitalLongitude":"-61.216667","CountryCode":"VC","ContinentName":"Central America"},{"CountryName":"Samoa","CapitalName":"Apia","CapitalLatitude":"-13.816666666666666","CapitalLongitude":"-171.766667","CountryCode":"WS","ContinentName":"Australia"},{"CountryName":"San Marino","CapitalName":"San Marino","CapitalLatitude":"43.93333333333333","CapitalLongitude":"12.416667","CountryCode":"SM","ContinentName":"Europe"},{"CountryName":"Sao Tome and Principe","CapitalName":"Sao Tome","CapitalLatitude":"0.3333333333333333","CapitalLongitude":"6.733333","CountryCode":"ST","ContinentName":"Africa"},{"CountryName":"Saudi Arabia","CapitalName":"Riyadh","CapitalLatitude":"24.65","CapitalLongitude":"46.700000","CountryCode":"SA","ContinentName":"Asia"},{"CountryName":"Senegal","CapitalName":"Dakar","CapitalLatitude":"14.733333333333333","CapitalLongitude":"-17.633333","CountryCode":"SN","ContinentName":"Africa"},{"CountryName":"Serbia","CapitalName":"Belgrade","CapitalLatitude":"44.833333333333336","CapitalLongitude":"20.500000","CountryCode":"RS","ContinentName":"Europe"},{"CountryName":"Seychelles","CapitalName":"Victoria","CapitalLatitude":"-4.616666666666667","CapitalLongitude":"55.450000","CountryCode":"SC","ContinentName":"Africa"},{"CountryName":"Sierra Leone","CapitalName":"Freetown","CapitalLatitude":"8.483333333333333","CapitalLongitude":"-13.233333","CountryCode":"SL","ContinentName":"Africa"},{"CountryName":"Singapore","CapitalName":"Singapore","CapitalLatitude":"1.2833333333333332","CapitalLongitude":"103.850000","CountryCode":"SG","ContinentName":"Asia"},{"CountryName":"Sint Maarten","CapitalName":"Philipsburg","CapitalLatitude":"18.016666666666666","CapitalLongitude":"-63.033333","CountryCode":"SX","ContinentName":"North America"},{"CountryName":"Slovakia","CapitalName":"Bratislava","CapitalLatitude":"48.15","CapitalLongitude":"17.116667","CountryCode":"SK","ContinentName":"Europe"},{"CountryName":"Slovenia","CapitalName":"Ljubljana","CapitalLatitude":"46.05","CapitalLongitude":"14.516667","CountryCode":"SI","ContinentName":"Europe"},{"CountryName":"Solomon Islands","CapitalName":"Honiara","CapitalLatitude":"-9.433333333333334","CapitalLongitude":"159.950000","CountryCode":"SB","ContinentName":"Australia"},{"CountryName":"Somalia","CapitalName":"Mogadishu","CapitalLatitude":"2.066666666666667","CapitalLongitude":"45.333333","CountryCode":"SO","ContinentName":"Africa"},{"CountryName":"South Africa","CapitalName":"Pretoria","CapitalLatitude":"-25.7","CapitalLongitude":"28.216667","CountryCode":"ZA","ContinentName":"Africa"},{"CountryName":"South Sudan","CapitalName":"Juba","CapitalLatitude":"4.85","CapitalLongitude":"31.616667","CountryCode":"SS","ContinentName":"Africa"},{"CountryName":"Spain","CapitalName":"Madrid","CapitalLatitude":"40.4","CapitalLongitude":"-3.683333","CountryCode":"ES","ContinentName":"Europe"},{"CountryName":"Sri Lanka","CapitalName":"Colombo","CapitalLatitude":"6.916666666666667","CapitalLongitude":"79.833333","CountryCode":"LK","ContinentName":"Asia"},{"CountryName":"Sudan","CapitalName":"Khartoum","CapitalLatitude":"15.6","CapitalLongitude":"32.533333","CountryCode":"SD","ContinentName":"Africa"},{"CountryName":"Suriname","CapitalName":"Paramaribo","CapitalLatitude":"5.833333333333333","CapitalLongitude":"-55.166667","CountryCode":"SR","ContinentName":"South America"},{"CountryName":"Svalbard","CapitalName":"Longyearbyen","CapitalLatitude":"78.21666666666667","CapitalLongitude":"15.633333","CountryCode":"SJ","ContinentName":"Europe"},{"CountryName":"Swaziland","CapitalName":"Mbabane","CapitalLatitude":"-26.316666666666666","CapitalLongitude":"31.133333","CountryCode":"SZ","ContinentName":"Africa"},{"CountryName":"Sweden","CapitalName":"Stockholm","CapitalLatitude":"59.333333333333336","CapitalLongitude":"18.050000","CountryCode":"SE","ContinentName":"Europe"},{"CountryName":"Switzerland","CapitalName":"Bern","CapitalLatitude":"46.916666666666664","CapitalLongitude":"7.466667","CountryCode":"CH","ContinentName":"Europe"},{"CountryName":"Syria","CapitalName":"Damascus","CapitalLatitude":"33.5","CapitalLongitude":"36.300000","CountryCode":"SY","ContinentName":"Asia"},{"CountryName":"Taiwan","CapitalName":"Taipei","CapitalLatitude":"25.033333333333335","CapitalLongitude":"121.516667","CountryCode":"TW","ContinentName":"Asia"},{"CountryName":"Tajikistan","CapitalName":"Dushanbe","CapitalLatitude":"38.55","CapitalLongitude":"68.766667","CountryCode":"TJ","ContinentName":"Asia"},{"CountryName":"Tanzania","CapitalName":"Dar es Salaam","CapitalLatitude":"-6.8","CapitalLongitude":"39.283333","CountryCode":"TZ","ContinentName":"Africa"},{"CountryName":"Thailand","CapitalName":"Bangkok","CapitalLatitude":"13.75","CapitalLongitude":"100.516667","CountryCode":"TH","ContinentName":"Asia"},{"CountryName":"Timor-Leste","CapitalName":"Dili","CapitalLatitude":"-8.583333333333334","CapitalLongitude":"125.600000","CountryCode":"TL","ContinentName":"Asia"},{"CountryName":"Togo","CapitalName":"Lome","CapitalLatitude":"6.116666666666666","CapitalLongitude":"1.216667","CountryCode":"TG","ContinentName":"Africa"},{"CountryName":"Tonga","CapitalName":"Nuku'alofa","CapitalLatitude":"-21.133333333333333","CapitalLongitude":"-175.200000","CountryCode":"TO","ContinentName":"Australia"},{"CountryName":"Trinidad and Tobago","CapitalName":"Port of Spain","CapitalLatitude":"10.65","CapitalLongitude":"-61.516667","CountryCode":"TT","ContinentName":"North America"},{"CountryName":"Tunisia","CapitalName":"Tunis","CapitalLatitude":"36.8","CapitalLongitude":"10.183333","CountryCode":"TN","ContinentName":"Africa"},{"CountryName":"Turkey","CapitalName":"Ankara","CapitalLatitude":"39.93333333333333","CapitalLongitude":"32.866667","CountryCode":"TR","ContinentName":"Europe"},{"CountryName":"Turkmenistan","CapitalName":"Ashgabat","CapitalLatitude":"37.95","CapitalLongitude":"58.383333","CountryCode":"TM","ContinentName":"Asia"},{"CountryName":"Turks and Caicos Islands","CapitalName":"Grand Turk","CapitalLatitude":"21.466666666666665","CapitalLongitude":"-71.133333","CountryCode":"TC","ContinentName":"North America"},{"CountryName":"Tuvalu","CapitalName":"Funafuti","CapitalLatitude":"-8.516666666666667","CapitalLongitude":"179.216667","CountryCode":"TV","ContinentName":"Australia"},{"CountryName":"Uganda","CapitalName":"Kampala","CapitalLatitude":"0.31666666666666665","CapitalLongitude":"32.550000","CountryCode":"UG","ContinentName":"Africa"},{"CountryName":"Ukraine","CapitalName":"Kyiv","CapitalLatitude":"50.43333333333333","CapitalLongitude":"30.516667","CountryCode":"UA","ContinentName":"Europe"},{"CountryName":"United Arab Emirates","CapitalName":"Abu Dhabi","CapitalLatitude":"24.466666666666665","CapitalLongitude":"54.366667","CountryCode":"AE","ContinentName":"Asia"},{"CountryName":"United Kingdom","CapitalName":"London","CapitalLatitude":"51.5","CapitalLongitude":"-0.083333","CountryCode":"GB","ContinentName":"Europe"},{"CountryName":"United States","CapitalName":"Washington","CapitalLatitude":" D.C.","CapitalLongitude":"38.883333","CountryCode":"-77.000000","ContinentName":"US"},{"CountryName":"Uruguay","CapitalName":"Montevideo","CapitalLatitude":"-34.85","CapitalLongitude":"-56.166667","CountryCode":"UY","ContinentName":"South America"},{"CountryName":"Uzbekistan","CapitalName":"Tashkent","CapitalLatitude":"41.31666666666667","CapitalLongitude":"69.250000","CountryCode":"UZ","ContinentName":"Asia"},{"CountryName":"Vanuatu","CapitalName":"Port-Vila","CapitalLatitude":"-17.733333333333334","CapitalLongitude":"168.316667","CountryCode":"VU","ContinentName":"Australia"},{"CountryName":"Venezuela","CapitalName":"Caracas","CapitalLatitude":"10.483333333333333","CapitalLongitude":"-66.866667","CountryCode":"VE","ContinentName":"South America"},{"CountryName":"Vietnam","CapitalName":"Hanoi","CapitalLatitude":"21.033333333333335","CapitalLongitude":"105.850000","CountryCode":"VN","ContinentName":"Asia"},{"CountryName":"US Virgin Islands","CapitalName":"Charlotte Amalie","CapitalLatitude":"18.35","CapitalLongitude":"-64.933333","CountryCode":"VI","ContinentName":"North America"},{"CountryName":"Wallis and Futuna","CapitalName":"Mata-Utu","CapitalLatitude":"-13.95","CapitalLongitude":"-171.933333","CountryCode":"WF","ContinentName":"Australia"},{"CountryName":"Yemen","CapitalName":"Sanaa","CapitalLatitude":"15.35","CapitalLongitude":"44.200000","CountryCode":"YE","ContinentName":"Asia"},{"CountryName":"Zambia","CapitalName":"Lusaka","CapitalLatitude":"-15.416666666666666","CapitalLongitude":"28.283333","CountryCode":"ZM","ContinentName":"Africa"},{"CountryName":"Zimbabwe","CapitalName":"Harare","CapitalLatitude":"-17.816666666666666","CapitalLongitude":"31.033333","CountryCode":"ZW","ContinentName":"Africa"},{"CountryName":"US Minor Outlying Islands","CapitalName":"Washington","CapitalLatitude":" D.C.","CapitalLongitude":"38.883333","CountryCode":"-77.000000","ContinentName":"UM"},{"CountryName":"Antarctica","CapitalName":"N/A","CapitalLatitude":"0","CapitalLongitude":"0.000000","CountryCode":"AQ","ContinentName":"Antarctica"},{"CountryName":"Northern Cyprus","CapitalName":"North Nicosia","CapitalLatitude":"35.183333","CapitalLongitude":"33.366667","CountryCode":"NULL","ContinentName":"Europe"},{"CountryName":"Hong Kong","CapitalName":"N/A","CapitalLatitude":"0","CapitalLongitude":"0.000000","CountryCode":"HK","ContinentName":"Asia"},{"CountryName":"Heard Island and McDonald Islands","CapitalName":"N/A","CapitalLatitude":"0","CapitalLongitude":"0.000000","CountryCode":"HM","ContinentName":"Antarctica"},{"CountryName":"British Indian Ocean Territory","CapitalName":"Diego Garcia","CapitalLatitude":"-7.3","CapitalLongitude":"72.400000","CountryCode":"IO","ContinentName":"Africa"},{"CountryName":"Macau","CapitalName":"N/A","CapitalLatitude":"0","CapitalLongitude":"0.000000","CountryCode":"MO","ContinentName":"Asia"}] \ No newline at end of file diff --git a/db_creation.py b/db_creation.py index e53a25b..fa5d639 100644 --- a/db_creation.py +++ b/db_creation.py @@ -3,7 +3,7 @@ from sqlalchemy.orm import relationship Base = declarative_base() -engine = create_engine("postgresql://postgres:123QWEasd@localhost:5432/apidata") +engine = create_engine("postgresql://postgres:123QWEasd@localhost:5432/api_data_test") class Country(Base): diff --git a/db_insert_data.py b/db_insert_data.py index 6e14c05..58465a6 100644 --- a/db_insert_data.py +++ b/db_insert_data.py @@ -3,51 +3,76 @@ from weatherbit_api_client import WeatherbitApiClient from LentaParser import LentaParser from api_not_available import ApiNotAvailableException -import datetime -from flask import request -import psycopg2 -from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT -import sqlalchemy -import pgconnection +from db_creation import Country, City, News, Weather +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker +import json +import time import pycountry +with open('country-capitals.json') as capitals: + data_capitals = json.load(capitals) + formatted_capitals = [cap['CapitalName'] for cap in data_capitals if cap['CapitalName'] != "N/A"] class InsertData: - def __init__(self): - self.gathered_apis_data = {} - - def gather_data_news_api(self): - countries = (country.alpha_2 for country in list(pycountry.countries)) - for country in countries: + @staticmethod + def insert_data_news_api(): + engine = create_engine("postgresql://postgres:123QWEasd@localhost:5432/api_data_test") + session_maker = sessionmaker(bind=engine) + session = session_maker() + countries = [country.alpha_2 for country in list(pycountry.countries)] + identifier_c = 0 + identifier_n = 0 + for c in countries[0:10]: + identifier_c += 1 + country = Country() + country.id = identifier_c + country.name = c + session.add(country) + time.sleep(1) try: - news = NewsApiClient(country) + whole_news = NewsApiClient(c) except ApiNotAvailableException: - news = LentaParser() - - def gather_apis_data(self): - return self.gathered_apis_data - - def insert_data(self): - try: - conn = pgconnection.get_connection("apidata") - conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) - cursor = conn.cursor() - for item in self.data_response(): - - cursor.execute("""INSERT INTO city(name) - VALUE (%(name)s);""", item["city"]) - print("City inserted") - - cursor.execute("""INSERT INTO weather(cityid, weather_info, temp_in_celsius, wind_speed_kmph, dateadded) - VALUES (%(cityid)s, %(weather_info)s, %(temp_in_celsius)s, %(wind_speed_kmph)s, %(dateadded)s);""", item) + whole_news = LentaParser() + top_news = whole_news.get_top_news() + identifier_n += 2 + news = News() + news.id = identifier_n + news.country_id = country.id + for content in top_news: + news.title = content['title'] + news.body = content['body'] + session.add(news) + session.commit() + session.close() - cursor.close() - conn.close() - - except psycopg2.Error as e: - - print(type(e)) - - print(e) + @staticmethod + def insert_data_weather_api(): + engine = create_engine("postgresql://postgres:123QWEasd@localhost:5432/api_data_test") + session_maker = sessionmaker(bind=engine) + session = session_maker() + identifier_c = 0 + identifier_n = 0 + for c in formatted_capitals[0:10]: + identifier_c += 1 + city = City() + city.id = identifier_c + city.name = c + session.add(city) + time.sleep(1) + try: + new_weather = WeatherApiClient(c) + except ApiNotAvailableException: + new_weather = WeatherbitApiClient(c) + identifier_n += 2 + weather = Weather() + weather.id = identifier_n + weather.city_id = city.id + weather.weather_info = new_weather.get_weather_description() + weather.temp_in_c = new_weather.get_temperature()[0] + weather.wind_speed_kmph = new_weather.get_wind()[0] + session.add(weather) + session.commit() + session.close() diff --git a/news_api_client.py b/news_api_client.py index 1466b27..686efcd 100644 --- a/news_api_client.py +++ b/news_api_client.py @@ -20,7 +20,7 @@ def _send_request(self): def get_top_news(self): output_news = [] - for news in self.news_data['articles'][0:]: + for news in self.news_data['articles'][0:3]: formatted_news = { "title": news['title'], "body": news['content'] From c4fe2698dfa676eeb421d1c92d04f88848ffc50b Mon Sep 17 00:00:00 2001 From: Dima Date: Wed, 24 Feb 2021 22:04:11 +0600 Subject: [PATCH 14/16] Validation of the input argument city has been realised with marshmallow library. Also made a conversion of city into country, so there is no need to pass two arguments in request. --- GetValidator.py | 12 ++++++++++++ db_creation.py | 20 ++++++++++---------- db_insert_data.py | 22 ++++++++++++++-------- index.py | 22 +++++++++++++--------- news_api_client.py | 11 ++++++----- weatherbit_api_client.py | 3 +++ 6 files changed, 58 insertions(+), 32 deletions(-) create mode 100644 GetValidator.py diff --git a/GetValidator.py b/GetValidator.py new file mode 100644 index 0000000..69d6b6e --- /dev/null +++ b/GetValidator.py @@ -0,0 +1,12 @@ +from marshmallow import Schema, fields, validates, ValidationError +from allcities import cities + + +class RunRequestSchema(Schema): + + city = fields.Str(required=True) + + @validates('city') + def valid_city(self, value): + if len(cities.filter(name=value)) == 0: + raise ValidationError("Can't find this city!") \ No newline at end of file diff --git a/db_creation.py b/db_creation.py index fa5d639..3637e91 100644 --- a/db_creation.py +++ b/db_creation.py @@ -1,48 +1,48 @@ -from sqlalchemy import create_engine, func, Column, Integer, String, ForeignKey, DateTime +from sqlalchemy import create_engine, func, Column, Integer, String, ForeignKey, DateTime, CheckConstraint from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship Base = declarative_base() -engine = create_engine("postgresql://postgres:123QWEasd@localhost:5432/api_data_test") +engine = create_engine("postgresql://postgres:123QWEasd@localhost:5432/api_data_test_2") class Country(Base): __tablename__ = "country" - id = Column('id', Integer, primary_key=True) + id = Column('id', Integer, autoincrement=True, primary_key=True) name = Column('name', String, unique=True) - news = relationship("News", uselist=False, back_populates="country") + news = relationship("News", back_populates="country") class News(Base): __tablename__ = "news" - id = Column('id', Integer, primary_key=True) + id = Column('id', Integer, autoincrement=True, primary_key=True) country_id = Column(Integer, ForeignKey('country.id')) country = relationship("Country", back_populates="news") title = Column('title', String) body = Column('body', String) - date = Column('dateadded', DateTime, onupdate=func.now()) + date = Column('dateadded', DateTime, default=func.now()) class City(Base): __tablename__ = "city" - id = Column('id', Integer, primary_key=True) + id = Column('id', Integer, autoincrement=True, primary_key=True) name = Column('name', String, unique=True) - weather = relationship("Weather", uselist=False, back_populates="city") + weather = relationship("Weather", back_populates="city") class Weather(Base): __tablename__ = "weather" - id = Column('id', Integer, primary_key=True) + id = Column('id', Integer, autoincrement=True, primary_key=True) city_id = Column(Integer, ForeignKey('city.id')) city = relationship("City", back_populates="weather") weather_info = Column('weather_info', String) temp_in_c = Column('temp_in_c', Integer) wind_speed_kmph = Column('wind_speed_kmph', Integer) - date = Column('dateadded', DateTime, onupdate=func.now()) + date = Column('dateadded', DateTime, default=func.now()) Base.metadata.create_all(bind=engine) diff --git a/db_insert_data.py b/db_insert_data.py index 58465a6..2cc8a1b 100644 --- a/db_insert_data.py +++ b/db_insert_data.py @@ -10,6 +10,7 @@ import time import pycountry + with open('country-capitals.json') as capitals: data_capitals = json.load(capitals) formatted_capitals = [cap['CapitalName'] for cap in data_capitals if cap['CapitalName'] != "N/A"] @@ -19,13 +20,18 @@ class InsertData: @staticmethod def insert_data_news_api(): - engine = create_engine("postgresql://postgres:123QWEasd@localhost:5432/api_data_test") + engine = create_engine("postgresql://postgres:123QWEasd@localhost:5432/api_data_test_2") session_maker = sessionmaker(bind=engine) session = session_maker() - countries = [country.alpha_2 for country in list(pycountry.countries)] + main_countries = [] + for country in list(pycountry.countries): + if country.alpha_2 in ['US', 'CA', 'GB', 'DE', 'JP', 'CN', 'ES', 'GR', 'FR', 'IT']: + main_countries.append(country) + main_countries = [country.alpha_2 for country in main_countries] + # countries = [country.alpha_2 for country in list(pycountry.countries)] identifier_c = 0 identifier_n = 0 - for c in countries[0:10]: + for c in main_countries[0:4]: identifier_c += 1 country = Country() country.id = identifier_c @@ -37,14 +43,14 @@ def insert_data_news_api(): except ApiNotAvailableException: whole_news = LentaParser() top_news = whole_news.get_top_news() - identifier_n += 2 - news = News() - news.id = identifier_n - news.country_id = country.id for content in top_news: + identifier_n += 2 + news = News() + news.id = identifier_n + news.country_id = country.id news.title = content['title'] news.body = content['body'] - session.add(news) + session.add(news) session.commit() session.close() diff --git a/index.py b/index.py index 87539e3..c1a7bd6 100644 --- a/index.py +++ b/index.py @@ -4,26 +4,30 @@ from LentaParser import LentaParser from flask import Flask from flask import request -from flask import render_template +from GetValidator import RunRequestSchema from flask_restful import Api from flask import jsonify from api_not_available import ApiNotAvailableException +from allcities import cities +import pycountry app = Flask(__name__) api = Api(app) +run_request_schema = RunRequestSchema() -@app.route('/') -def index(): - return render_template('form.html') - -@app.route('/main', methods=['POST', 'GET']) -def main(): +@app.route('/current_data', methods=['GET']) +def current_data(): + errors = run_request_schema.validate(request.args) + if errors: + raise ValueError(("An error occurred with input: {}".format(errors))) city = request.args.get('city') - country = request.args.get('country') - if city and country: + filtered_city_set = cities.filter(name=city, population='>100000') + largest_city = next(iter(filtered_city_set)) + if largest_city.dict['country_code'] in [country.alpha_2 for country in list(pycountry.countries)]: + country = largest_city.dict['country_code'] try: new_weather = WeatherApiClient(city) except ApiNotAvailableException: diff --git a/news_api_client.py b/news_api_client.py index 686efcd..5062039 100644 --- a/news_api_client.py +++ b/news_api_client.py @@ -21,9 +21,10 @@ def _send_request(self): def get_top_news(self): output_news = [] for news in self.news_data['articles'][0:3]: - formatted_news = { - "title": news['title'], - "body": news['content'] - } - output_news.append(formatted_news) + if news['title'] and news['content']: + formatted_news = { + "title": news['title'], + "body": news['content'] + } + output_news.append(formatted_news) return output_news diff --git a/weatherbit_api_client.py b/weatherbit_api_client.py index 562a519..ec3f7b8 100644 --- a/weatherbit_api_client.py +++ b/weatherbit_api_client.py @@ -10,6 +10,9 @@ class WeatherbitApiClient(ParentWeatherApi): def _send_request(self): response = requests.get(self.BASE_URL.format(con_wb['url'], self.city, con_wb['api_key'])) if response.status_code != 200: + print(self.city) + print(response.text) + print(response.status_code) error_message = response.json()['error'] raise ApiNotAvailableException(f"{error_message} occurred in WeatherbitApiClient") else: From f9653d3280e266c8da1dbdf2974d479cea352b84 Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 1 Mar 2021 23:24:18 +0600 Subject: [PATCH 15/16] Cache implementation has been realized in cache_data_job.py, also made simple converter city_to_country.py. index.py was refactored to exclude direct calls to api-services and now it's working through the orm layer with db_insert_data.py --- cache_data_job.py | 13 ++++ city_to_country.py | 10 +++ conf.py | 5 +- country-capitals.json | 1 - db_insert_data.py | 172 +++++++++++++++++++++++++++--------------- index.py | 57 ++++++-------- 6 files changed, 159 insertions(+), 99 deletions(-) create mode 100644 cache_data_job.py create mode 100644 city_to_country.py delete mode 100644 country-capitals.json diff --git a/cache_data_job.py b/cache_data_job.py new file mode 100644 index 0000000..115cae8 --- /dev/null +++ b/cache_data_job.py @@ -0,0 +1,13 @@ +from db_insert_data import InsertData +from city_to_country import city_to_country + + +def cache_data_job(): + cities = InsertData.get_cities() + countries = (city_to_country(city) for city in cities) + city_ids = (InsertData.check_city_id(city) for city in cities) + country_ids = (InsertData.check_country_id(country) for country in countries) + for city, city_id in zip(cities, city_ids): + InsertData.insert_data_weather_api(city, city_id) + for country, country_id in zip(countries, country_ids): + InsertData.insert_data_news_api(country, country_id) diff --git a/city_to_country.py b/city_to_country.py new file mode 100644 index 0000000..cabe7ac --- /dev/null +++ b/city_to_country.py @@ -0,0 +1,10 @@ +from allcities import cities +import pycountry + + +def city_to_country(city): + filtered_city_set = cities.filter(name=city, population='>500000') + largest_city = next(iter(filtered_city_set)) + if largest_city.dict['country_code'] in [country.alpha_2 for country in list(pycountry.countries)]: + country_code = largest_city.dict['country_code'] + return country_code diff --git a/conf.py b/conf.py index 792a9aa..aa5d8b1 100644 --- a/conf.py +++ b/conf.py @@ -1,4 +1,3 @@ -import psycopg2 con = { "api_key": "ca6a19006afff952f0e5246316b1ff944", @@ -18,3 +17,7 @@ con_lenta = { "url": "https://lenta.ru/" } + +postgres_con = { + "c_str": "postgresql://postgres:123QWEasd@localhost:5432/api_data_test_2" +} \ No newline at end of file diff --git a/country-capitals.json b/country-capitals.json deleted file mode 100644 index 542c08c..0000000 --- a/country-capitals.json +++ /dev/null @@ -1 +0,0 @@ -[{"CountryName":"Somaliland","CapitalName":"Hargeisa","CapitalLatitude":"9.55","CapitalLongitude":"44.050000","CountryCode":"NULL","ContinentName":"Africa"},{"CountryName":"South Georgia and South Sandwich Islands","CapitalName":"King Edward Point","CapitalLatitude":"-54.283333","CapitalLongitude":"-36.500000","CountryCode":"GS","ContinentName":"Antarctica"},{"CountryName":"French Southern and Antarctic Lands","CapitalName":"Port-aux-Français","CapitalLatitude":"-49.35","CapitalLongitude":"70.216667","CountryCode":"TF","ContinentName":"Antarctica"},{"CountryName":"Palestine","CapitalName":"Jerusalem","CapitalLatitude":"31.766666666666666","CapitalLongitude":"35.233333","CountryCode":"PS","ContinentName":"Asia"},{"CountryName":"Aland Islands","CapitalName":"Mariehamn","CapitalLatitude":"60.116667","CapitalLongitude":"19.900000","CountryCode":"AX","ContinentName":"Europe"},{"CountryName":"Nauru","CapitalName":"Yaren","CapitalLatitude":"-0.5477","CapitalLongitude":"166.920867","CountryCode":"NR","ContinentName":"Australia"},{"CountryName":"Saint Martin","CapitalName":"Marigot","CapitalLatitude":"18.0731","CapitalLongitude":"-63.082200","CountryCode":"MF","ContinentName":"North America"},{"CountryName":"Tokelau","CapitalName":"Atafu","CapitalLatitude":"-9.166667","CapitalLongitude":"-171.833333","CountryCode":"TK","ContinentName":"Australia"},{"CountryName":"Western Sahara","CapitalName":"El-Aaiún","CapitalLatitude":"27.153611","CapitalLongitude":"-13.203333","CountryCode":"EH","ContinentName":"Africa"},{"CountryName":"Afghanistan","CapitalName":"Kabul","CapitalLatitude":"34.516666666666666","CapitalLongitude":"69.183333","CountryCode":"AF","ContinentName":"Asia"},{"CountryName":"Albania","CapitalName":"Tirana","CapitalLatitude":"41.31666666666667","CapitalLongitude":"19.816667","CountryCode":"AL","ContinentName":"Europe"},{"CountryName":"Algeria","CapitalName":"Algiers","CapitalLatitude":"36.75","CapitalLongitude":"3.050000","CountryCode":"DZ","ContinentName":"Africa"},{"CountryName":"American Samoa","CapitalName":"Pago Pago","CapitalLatitude":"-14.266666666666667","CapitalLongitude":"-170.700000","CountryCode":"AS","ContinentName":"Australia"},{"CountryName":"Andorra","CapitalName":"Andorra la Vella","CapitalLatitude":"42.5","CapitalLongitude":"1.516667","CountryCode":"AD","ContinentName":"Europe"},{"CountryName":"Angola","CapitalName":"Luanda","CapitalLatitude":"-8.833333333333334","CapitalLongitude":"13.216667","CountryCode":"AO","ContinentName":"Africa"},{"CountryName":"Anguilla","CapitalName":"The Valley","CapitalLatitude":"18.216666666666665","CapitalLongitude":"-63.050000","CountryCode":"AI","ContinentName":"North America"},{"CountryName":"Antigua and Barbuda","CapitalName":"Saint John's","CapitalLatitude":"17.116666666666667","CapitalLongitude":"-61.850000","CountryCode":"AG","ContinentName":"North America"},{"CountryName":"Argentina","CapitalName":"Buenos Aires","CapitalLatitude":"-34.583333333333336","CapitalLongitude":"-58.666667","CountryCode":"AR","ContinentName":"South America"},{"CountryName":"Armenia","CapitalName":"Yerevan","CapitalLatitude":"40.166666666666664","CapitalLongitude":"44.500000","CountryCode":"AM","ContinentName":"Europe"},{"CountryName":"Aruba","CapitalName":"Oranjestad","CapitalLatitude":"12.516666666666667","CapitalLongitude":"-70.033333","CountryCode":"AW","ContinentName":"North America"},{"CountryName":"Australia","CapitalName":"Canberra","CapitalLatitude":"-35.266666666666666","CapitalLongitude":"149.133333","CountryCode":"AU","ContinentName":"Australia"},{"CountryName":"Austria","CapitalName":"Vienna","CapitalLatitude":"48.2","CapitalLongitude":"16.366667","CountryCode":"AT","ContinentName":"Europe"},{"CountryName":"Azerbaijan","CapitalName":"Baku","CapitalLatitude":"40.38333333333333","CapitalLongitude":"49.866667","CountryCode":"AZ","ContinentName":"Europe"},{"CountryName":"Bahamas","CapitalName":"Nassau","CapitalLatitude":"25.083333333333332","CapitalLongitude":"-77.350000","CountryCode":"BS","ContinentName":"North America"},{"CountryName":"Bahrain","CapitalName":"Manama","CapitalLatitude":"26.233333333333334","CapitalLongitude":"50.566667","CountryCode":"BH","ContinentName":"Asia"},{"CountryName":"Bangladesh","CapitalName":"Dhaka","CapitalLatitude":"23.716666666666665","CapitalLongitude":"90.400000","CountryCode":"BD","ContinentName":"Asia"},{"CountryName":"Barbados","CapitalName":"Bridgetown","CapitalLatitude":"13.1","CapitalLongitude":"-59.616667","CountryCode":"BB","ContinentName":"North America"},{"CountryName":"Belarus","CapitalName":"Minsk","CapitalLatitude":"53.9","CapitalLongitude":"27.566667","CountryCode":"BY","ContinentName":"Europe"},{"CountryName":"Belgium","CapitalName":"Brussels","CapitalLatitude":"50.833333333333336","CapitalLongitude":"4.333333","CountryCode":"BE","ContinentName":"Europe"},{"CountryName":"Belize","CapitalName":"Belmopan","CapitalLatitude":"17.25","CapitalLongitude":"-88.766667","CountryCode":"BZ","ContinentName":"Central America"},{"CountryName":"Benin","CapitalName":"Porto-Novo","CapitalLatitude":"6.483333333333333","CapitalLongitude":"2.616667","CountryCode":"BJ","ContinentName":"Africa"},{"CountryName":"Bermuda","CapitalName":"Hamilton","CapitalLatitude":"32.28333333333333","CapitalLongitude":"-64.783333","CountryCode":"BM","ContinentName":"North America"},{"CountryName":"Bhutan","CapitalName":"Thimphu","CapitalLatitude":"27.466666666666665","CapitalLongitude":"89.633333","CountryCode":"BT","ContinentName":"Asia"},{"CountryName":"Bolivia","CapitalName":"La Paz","CapitalLatitude":"-16.5","CapitalLongitude":"-68.150000","CountryCode":"BO","ContinentName":"South America"},{"CountryName":"Bosnia and Herzegovina","CapitalName":"Sarajevo","CapitalLatitude":"43.86666666666667","CapitalLongitude":"18.416667","CountryCode":"BA","ContinentName":"Europe"},{"CountryName":"Botswana","CapitalName":"Gaborone","CapitalLatitude":"-24.633333333333333","CapitalLongitude":"25.900000","CountryCode":"BW","ContinentName":"Africa"},{"CountryName":"Brazil","CapitalName":"Brasilia","CapitalLatitude":"-15.783333333333333","CapitalLongitude":"-47.916667","CountryCode":"BR","ContinentName":"South America"},{"CountryName":"British Virgin Islands","CapitalName":"Road Town","CapitalLatitude":"18.416666666666668","CapitalLongitude":"-64.616667","CountryCode":"VG","ContinentName":"North America"},{"CountryName":"Brunei Darussalam","CapitalName":"Bandar Seri Begawan","CapitalLatitude":"4.883333333333333","CapitalLongitude":"114.933333","CountryCode":"BN","ContinentName":"Asia"},{"CountryName":"Bulgaria","CapitalName":"Sofia","CapitalLatitude":"42.68333333333333","CapitalLongitude":"23.316667","CountryCode":"BG","ContinentName":"Europe"},{"CountryName":"Burkina Faso","CapitalName":"Ouagadougou","CapitalLatitude":"12.366666666666667","CapitalLongitude":"-1.516667","CountryCode":"BF","ContinentName":"Africa"},{"CountryName":"Myanmar","CapitalName":"Rangoon","CapitalLatitude":"16.8","CapitalLongitude":"96.150000","CountryCode":"MM","ContinentName":"Asia"},{"CountryName":"Burundi","CapitalName":"Bujumbura","CapitalLatitude":"-3.3666666666666667","CapitalLongitude":"29.350000","CountryCode":"BI","ContinentName":"Africa"},{"CountryName":"Cambodia","CapitalName":"Phnom Penh","CapitalLatitude":"11.55","CapitalLongitude":"104.916667","CountryCode":"KH","ContinentName":"Asia"},{"CountryName":"Cameroon","CapitalName":"Yaounde","CapitalLatitude":"3.8666666666666667","CapitalLongitude":"11.516667","CountryCode":"CM","ContinentName":"Africa"},{"CountryName":"Canada","CapitalName":"Ottawa","CapitalLatitude":"45.416666666666664","CapitalLongitude":"-75.700000","CountryCode":"CA","ContinentName":"Central America"},{"CountryName":"Cape Verde","CapitalName":"Praia","CapitalLatitude":"14.916666666666666","CapitalLongitude":"-23.516667","CountryCode":"CV","ContinentName":"Africa"},{"CountryName":"Cayman Islands","CapitalName":"George Town","CapitalLatitude":"19.3","CapitalLongitude":"-81.383333","CountryCode":"KY","ContinentName":"North America"},{"CountryName":"Central African Republic","CapitalName":"Bangui","CapitalLatitude":"4.366666666666666","CapitalLongitude":"18.583333","CountryCode":"CF","ContinentName":"Africa"},{"CountryName":"Chad","CapitalName":"N'Djamena","CapitalLatitude":"12.1","CapitalLongitude":"15.033333","CountryCode":"TD","ContinentName":"Africa"},{"CountryName":"Chile","CapitalName":"Santiago","CapitalLatitude":"-33.45","CapitalLongitude":"-70.666667","CountryCode":"CL","ContinentName":"South America"},{"CountryName":"China","CapitalName":"Beijing","CapitalLatitude":"39.916666666666664","CapitalLongitude":"116.383333","CountryCode":"CN","ContinentName":"Asia"},{"CountryName":"Christmas Island","CapitalName":"The Settlement","CapitalLatitude":"-10.416666666666666","CapitalLongitude":"105.716667","CountryCode":"CX","ContinentName":"Australia"},{"CountryName":"Cocos Islands","CapitalName":"West Island","CapitalLatitude":"-12.166666666666666","CapitalLongitude":"96.833333","CountryCode":"CC","ContinentName":"Australia"},{"CountryName":"Colombia","CapitalName":"Bogota","CapitalLatitude":"4.6","CapitalLongitude":"-74.083333","CountryCode":"CO","ContinentName":"South America"},{"CountryName":"Comoros","CapitalName":"Moroni","CapitalLatitude":"-11.7","CapitalLongitude":"43.233333","CountryCode":"KM","ContinentName":"Africa"},{"CountryName":"Democratic Republic of the Congo","CapitalName":"Kinshasa","CapitalLatitude":"-4.316666666666666","CapitalLongitude":"15.300000","CountryCode":"CD","ContinentName":"Africa"},{"CountryName":"Republic of Congo","CapitalName":"Brazzaville","CapitalLatitude":"-4.25","CapitalLongitude":"15.283333","CountryCode":"CG","ContinentName":"Africa"},{"CountryName":"Cook Islands","CapitalName":"Avarua","CapitalLatitude":"-21.2","CapitalLongitude":"-159.766667","CountryCode":"CK","ContinentName":"Australia"},{"CountryName":"Costa Rica","CapitalName":"San Jose","CapitalLatitude":"9.933333333333334","CapitalLongitude":"-84.083333","CountryCode":"CR","ContinentName":"Central America"},{"CountryName":"Cote d'Ivoire","CapitalName":"Yamoussoukro","CapitalLatitude":"6.816666666666666","CapitalLongitude":"-5.266667","CountryCode":"CI","ContinentName":"Africa"},{"CountryName":"Croatia","CapitalName":"Zagreb","CapitalLatitude":"45.8","CapitalLongitude":"16.000000","CountryCode":"HR","ContinentName":"Europe"},{"CountryName":"Cuba","CapitalName":"Havana","CapitalLatitude":"23.116666666666667","CapitalLongitude":"-82.350000","CountryCode":"CU","ContinentName":"North America"},{"CountryName":"Curaçao","CapitalName":"Willemstad","CapitalLatitude":"12.1","CapitalLongitude":"-68.916667","CountryCode":"CW","ContinentName":"North America"},{"CountryName":"Cyprus","CapitalName":"Nicosia","CapitalLatitude":"35.166666666666664","CapitalLongitude":"33.366667","CountryCode":"CY","ContinentName":"Europe"},{"CountryName":"Czech Republic","CapitalName":"Prague","CapitalLatitude":"50.083333333333336","CapitalLongitude":"14.466667","CountryCode":"CZ","ContinentName":"Europe"},{"CountryName":"Denmark","CapitalName":"Copenhagen","CapitalLatitude":"55.666666666666664","CapitalLongitude":"12.583333","CountryCode":"DK","ContinentName":"Europe"},{"CountryName":"Djibouti","CapitalName":"Djibouti","CapitalLatitude":"11.583333333333334","CapitalLongitude":"43.150000","CountryCode":"DJ","ContinentName":"Africa"},{"CountryName":"Dominica","CapitalName":"Roseau","CapitalLatitude":"15.3","CapitalLongitude":"-61.400000","CountryCode":"DM","ContinentName":"North America"},{"CountryName":"Dominican Republic","CapitalName":"Santo Domingo","CapitalLatitude":"18.466666666666665","CapitalLongitude":"-69.900000","CountryCode":"DO","ContinentName":"North America"},{"CountryName":"Ecuador","CapitalName":"Quito","CapitalLatitude":"-0.21666666666666667","CapitalLongitude":"-78.500000","CountryCode":"EC","ContinentName":"South America"},{"CountryName":"Egypt","CapitalName":"Cairo","CapitalLatitude":"30.05","CapitalLongitude":"31.250000","CountryCode":"EG","ContinentName":"Africa"},{"CountryName":"El Salvador","CapitalName":"San Salvador","CapitalLatitude":"13.7","CapitalLongitude":"-89.200000","CountryCode":"SV","ContinentName":"Central America"},{"CountryName":"Equatorial Guinea","CapitalName":"Malabo","CapitalLatitude":"3.75","CapitalLongitude":"8.783333","CountryCode":"GQ","ContinentName":"Africa"},{"CountryName":"Eritrea","CapitalName":"Asmara","CapitalLatitude":"15.333333333333334","CapitalLongitude":"38.933333","CountryCode":"ER","ContinentName":"Africa"},{"CountryName":"Estonia","CapitalName":"Tallinn","CapitalLatitude":"59.43333333333333","CapitalLongitude":"24.716667","CountryCode":"EE","ContinentName":"Europe"},{"CountryName":"Ethiopia","CapitalName":"Addis Ababa","CapitalLatitude":"9.033333333333333","CapitalLongitude":"38.700000","CountryCode":"ET","ContinentName":"Africa"},{"CountryName":"Falkland Islands","CapitalName":"Stanley","CapitalLatitude":"-51.7","CapitalLongitude":"-57.850000","CountryCode":"FK","ContinentName":"South America"},{"CountryName":"Faroe Islands","CapitalName":"Torshavn","CapitalLatitude":"62","CapitalLongitude":"-6.766667","CountryCode":"FO","ContinentName":"Europe"},{"CountryName":"Fiji","CapitalName":"Suva","CapitalLatitude":"-18.133333333333333","CapitalLongitude":"178.416667","CountryCode":"FJ","ContinentName":"Australia"},{"CountryName":"Finland","CapitalName":"Helsinki","CapitalLatitude":"60.166666666666664","CapitalLongitude":"24.933333","CountryCode":"FI","ContinentName":"Europe"},{"CountryName":"France","CapitalName":"Paris","CapitalLatitude":"48.86666666666667","CapitalLongitude":"2.333333","CountryCode":"FR","ContinentName":"Europe"},{"CountryName":"French Polynesia","CapitalName":"Papeete","CapitalLatitude":"-17.533333333333335","CapitalLongitude":"-149.566667","CountryCode":"PF","ContinentName":"Australia"},{"CountryName":"Gabon","CapitalName":"Libreville","CapitalLatitude":"0.38333333333333336","CapitalLongitude":"9.450000","CountryCode":"GA","ContinentName":"Africa"},{"CountryName":"The Gambia","CapitalName":"Banjul","CapitalLatitude":"13.45","CapitalLongitude":"-16.566667","CountryCode":"GM","ContinentName":"Africa"},{"CountryName":"Georgia","CapitalName":"Tbilisi","CapitalLatitude":"41.68333333333333","CapitalLongitude":"44.833333","CountryCode":"GE","ContinentName":"Europe"},{"CountryName":"Germany","CapitalName":"Berlin","CapitalLatitude":"52.516666666666666","CapitalLongitude":"13.400000","CountryCode":"DE","ContinentName":"Europe"},{"CountryName":"Ghana","CapitalName":"Accra","CapitalLatitude":"5.55","CapitalLongitude":"-0.216667","CountryCode":"GH","ContinentName":"Africa"},{"CountryName":"Gibraltar","CapitalName":"Gibraltar","CapitalLatitude":"36.13333333333333","CapitalLongitude":"-5.350000","CountryCode":"GI","ContinentName":"Europe"},{"CountryName":"Greece","CapitalName":"Athens","CapitalLatitude":"37.983333333333334","CapitalLongitude":"23.733333","CountryCode":"GR","ContinentName":"Europe"},{"CountryName":"Greenland","CapitalName":"Nuuk","CapitalLatitude":"64.18333333333334","CapitalLongitude":"-51.750000","CountryCode":"GL","ContinentName":"Central America"},{"CountryName":"Grenada","CapitalName":"Saint George's","CapitalLatitude":"12.05","CapitalLongitude":"-61.750000","CountryCode":"GD","ContinentName":"North America"},{"CountryName":"Guam","CapitalName":"Hagatna","CapitalLatitude":"13.466666666666667","CapitalLongitude":"144.733333","CountryCode":"GU","ContinentName":"Australia"},{"CountryName":"Guatemala","CapitalName":"Guatemala City","CapitalLatitude":"14.616666666666667","CapitalLongitude":"-90.516667","CountryCode":"GT","ContinentName":"Central America"},{"CountryName":"Guernsey","CapitalName":"Saint Peter Port","CapitalLatitude":"49.45","CapitalLongitude":"-2.533333","CountryCode":"GG","ContinentName":"Europe"},{"CountryName":"Guinea","CapitalName":"Conakry","CapitalLatitude":"9.5","CapitalLongitude":"-13.700000","CountryCode":"GN","ContinentName":"Africa"},{"CountryName":"Guinea-Bissau","CapitalName":"Bissau","CapitalLatitude":"11.85","CapitalLongitude":"-15.583333","CountryCode":"GW","ContinentName":"Africa"},{"CountryName":"Guyana","CapitalName":"Georgetown","CapitalLatitude":"6.8","CapitalLongitude":"-58.150000","CountryCode":"GY","ContinentName":"South America"},{"CountryName":"Haiti","CapitalName":"Port-au-Prince","CapitalLatitude":"18.533333333333335","CapitalLongitude":"-72.333333","CountryCode":"HT","ContinentName":"North America"},{"CountryName":"Vatican City","CapitalName":"Vatican City","CapitalLatitude":"41.9","CapitalLongitude":"12.450000","CountryCode":"VA","ContinentName":"Europe"},{"CountryName":"Honduras","CapitalName":"Tegucigalpa","CapitalLatitude":"14.1","CapitalLongitude":"-87.216667","CountryCode":"HN","ContinentName":"Central America"},{"CountryName":"Hungary","CapitalName":"Budapest","CapitalLatitude":"47.5","CapitalLongitude":"19.083333","CountryCode":"HU","ContinentName":"Europe"},{"CountryName":"Iceland","CapitalName":"Reykjavik","CapitalLatitude":"64.15","CapitalLongitude":"-21.950000","CountryCode":"IS","ContinentName":"Europe"},{"CountryName":"India","CapitalName":"New Delhi","CapitalLatitude":"28.6","CapitalLongitude":"77.200000","CountryCode":"IN","ContinentName":"Asia"},{"CountryName":"Indonesia","CapitalName":"Jakarta","CapitalLatitude":"-6.166666666666667","CapitalLongitude":"106.816667","CountryCode":"ID","ContinentName":"Asia"},{"CountryName":"Iran","CapitalName":"Tehran","CapitalLatitude":"35.7","CapitalLongitude":"51.416667","CountryCode":"IR","ContinentName":"Asia"},{"CountryName":"Iraq","CapitalName":"Baghdad","CapitalLatitude":"33.333333333333336","CapitalLongitude":"44.400000","CountryCode":"IQ","ContinentName":"Asia"},{"CountryName":"Ireland","CapitalName":"Dublin","CapitalLatitude":"53.31666666666667","CapitalLongitude":"-6.233333","CountryCode":"IE","ContinentName":"Europe"},{"CountryName":"Isle of Man","CapitalName":"Douglas","CapitalLatitude":"54.15","CapitalLongitude":"-4.483333","CountryCode":"IM","ContinentName":"Europe"},{"CountryName":"Israel","CapitalName":"Jerusalem","CapitalLatitude":"31.766666666666666","CapitalLongitude":"35.233333","CountryCode":"IL","ContinentName":"Asia"},{"CountryName":"Italy","CapitalName":"Rome","CapitalLatitude":"41.9","CapitalLongitude":"12.483333","CountryCode":"IT","ContinentName":"Europe"},{"CountryName":"Jamaica","CapitalName":"Kingston","CapitalLatitude":"18","CapitalLongitude":"-76.800000","CountryCode":"JM","ContinentName":"North America"},{"CountryName":"Japan","CapitalName":"Tokyo","CapitalLatitude":"35.68333333333333","CapitalLongitude":"139.750000","CountryCode":"JP","ContinentName":"Asia"},{"CountryName":"Jersey","CapitalName":"Saint Helier","CapitalLatitude":"49.18333333333333","CapitalLongitude":"-2.100000","CountryCode":"JE","ContinentName":"Europe"},{"CountryName":"Jordan","CapitalName":"Amman","CapitalLatitude":"31.95","CapitalLongitude":"35.933333","CountryCode":"JO","ContinentName":"Asia"},{"CountryName":"Kazakhstan","CapitalName":"Astana","CapitalLatitude":"51.166666666666664","CapitalLongitude":"71.416667","CountryCode":"KZ","ContinentName":"Asia"},{"CountryName":"Kenya","CapitalName":"Nairobi","CapitalLatitude":"-1.2833333333333332","CapitalLongitude":"36.816667","CountryCode":"KE","ContinentName":"Africa"},{"CountryName":"Kiribati","CapitalName":"Tarawa","CapitalLatitude":"-0.8833333333333333","CapitalLongitude":"169.533333","CountryCode":"KI","ContinentName":"Australia"},{"CountryName":"North Korea","CapitalName":"Pyongyang","CapitalLatitude":"39.016666666666666","CapitalLongitude":"125.750000","CountryCode":"KP","ContinentName":"Asia"},{"CountryName":"South Korea","CapitalName":"Seoul","CapitalLatitude":"37.55","CapitalLongitude":"126.983333","CountryCode":"KR","ContinentName":"Asia"},{"CountryName":"Kosovo","CapitalName":"Pristina","CapitalLatitude":"42.666666666666664","CapitalLongitude":"21.166667","CountryCode":"KO","ContinentName":"Europe"},{"CountryName":"Kuwait","CapitalName":"Kuwait City","CapitalLatitude":"29.366666666666667","CapitalLongitude":"47.966667","CountryCode":"KW","ContinentName":"Asia"},{"CountryName":"Kyrgyzstan","CapitalName":"Bishkek","CapitalLatitude":"42.86666666666667","CapitalLongitude":"74.600000","CountryCode":"KG","ContinentName":"Asia"},{"CountryName":"Laos","CapitalName":"Vientiane","CapitalLatitude":"17.966666666666665","CapitalLongitude":"102.600000","CountryCode":"LA","ContinentName":"Asia"},{"CountryName":"Latvia","CapitalName":"Riga","CapitalLatitude":"56.95","CapitalLongitude":"24.100000","CountryCode":"LV","ContinentName":"Europe"},{"CountryName":"Lebanon","CapitalName":"Beirut","CapitalLatitude":"33.86666666666667","CapitalLongitude":"35.500000","CountryCode":"LB","ContinentName":"Asia"},{"CountryName":"Lesotho","CapitalName":"Maseru","CapitalLatitude":"-29.316666666666666","CapitalLongitude":"27.483333","CountryCode":"LS","ContinentName":"Africa"},{"CountryName":"Liberia","CapitalName":"Monrovia","CapitalLatitude":"6.3","CapitalLongitude":"-10.800000","CountryCode":"LR","ContinentName":"Africa"},{"CountryName":"Libya","CapitalName":"Tripoli","CapitalLatitude":"32.88333333333333","CapitalLongitude":"13.166667","CountryCode":"LY","ContinentName":"Africa"},{"CountryName":"Liechtenstein","CapitalName":"Vaduz","CapitalLatitude":"47.13333333333333","CapitalLongitude":"9.516667","CountryCode":"LI","ContinentName":"Europe"},{"CountryName":"Lithuania","CapitalName":"Vilnius","CapitalLatitude":"54.68333333333333","CapitalLongitude":"25.316667","CountryCode":"LT","ContinentName":"Europe"},{"CountryName":"Luxembourg","CapitalName":"Luxembourg","CapitalLatitude":"49.6","CapitalLongitude":"6.116667","CountryCode":"LU","ContinentName":"Europe"},{"CountryName":"Macedonia","CapitalName":"Skopje","CapitalLatitude":"42","CapitalLongitude":"21.433333","CountryCode":"MK","ContinentName":"Europe"},{"CountryName":"Madagascar","CapitalName":"Antananarivo","CapitalLatitude":"-18.916666666666668","CapitalLongitude":"47.516667","CountryCode":"MG","ContinentName":"Africa"},{"CountryName":"Malawi","CapitalName":"Lilongwe","CapitalLatitude":"-13.966666666666667","CapitalLongitude":"33.783333","CountryCode":"MW","ContinentName":"Africa"},{"CountryName":"Malaysia","CapitalName":"Kuala Lumpur","CapitalLatitude":"3.1666666666666665","CapitalLongitude":"101.700000","CountryCode":"MY","ContinentName":"Asia"},{"CountryName":"Maldives","CapitalName":"Male","CapitalLatitude":"4.166666666666667","CapitalLongitude":"73.500000","CountryCode":"MV","ContinentName":"Asia"},{"CountryName":"Mali","CapitalName":"Bamako","CapitalLatitude":"12.65","CapitalLongitude":"-8.000000","CountryCode":"ML","ContinentName":"Africa"},{"CountryName":"Malta","CapitalName":"Valletta","CapitalLatitude":"35.88333333333333","CapitalLongitude":"14.500000","CountryCode":"MT","ContinentName":"Europe"},{"CountryName":"Marshall Islands","CapitalName":"Majuro","CapitalLatitude":"7.1","CapitalLongitude":"171.383333","CountryCode":"MH","ContinentName":"Australia"},{"CountryName":"Mauritania","CapitalName":"Nouakchott","CapitalLatitude":"18.066666666666666","CapitalLongitude":"-15.966667","CountryCode":"MR","ContinentName":"Africa"},{"CountryName":"Mauritius","CapitalName":"Port Louis","CapitalLatitude":"-20.15","CapitalLongitude":"57.483333","CountryCode":"MU","ContinentName":"Africa"},{"CountryName":"Mexico","CapitalName":"Mexico City","CapitalLatitude":"19.433333333333334","CapitalLongitude":"-99.133333","CountryCode":"MX","ContinentName":"Central America"},{"CountryName":"Federated States of Micronesia","CapitalName":"Palikir","CapitalLatitude":"6.916666666666667","CapitalLongitude":"158.150000","CountryCode":"FM","ContinentName":"Australia"},{"CountryName":"Moldova","CapitalName":"Chisinau","CapitalLatitude":"47","CapitalLongitude":"28.850000","CountryCode":"MD","ContinentName":"Europe"},{"CountryName":"Monaco","CapitalName":"Monaco","CapitalLatitude":"43.733333333333334","CapitalLongitude":"7.416667","CountryCode":"MC","ContinentName":"Europe"},{"CountryName":"Mongolia","CapitalName":"Ulaanbaatar","CapitalLatitude":"47.916666666666664","CapitalLongitude":"106.916667","CountryCode":"MN","ContinentName":"Asia"},{"CountryName":"Montenegro","CapitalName":"Podgorica","CapitalLatitude":"42.43333333333333","CapitalLongitude":"19.266667","CountryCode":"ME","ContinentName":"Europe"},{"CountryName":"Montserrat","CapitalName":"Plymouth","CapitalLatitude":"16.7","CapitalLongitude":"-62.216667","CountryCode":"MS","ContinentName":"North America"},{"CountryName":"Morocco","CapitalName":"Rabat","CapitalLatitude":"34.016666666666666","CapitalLongitude":"-6.816667","CountryCode":"MA","ContinentName":"Africa"},{"CountryName":"Mozambique","CapitalName":"Maputo","CapitalLatitude":"-25.95","CapitalLongitude":"32.583333","CountryCode":"MZ","ContinentName":"Africa"},{"CountryName":"Namibia","CapitalName":"Windhoek","CapitalLatitude":"-22.566666666666666","CapitalLongitude":"17.083333","CountryCode":"NA","ContinentName":"Africa"},{"CountryName":"Nepal","CapitalName":"Kathmandu","CapitalLatitude":"27.716666666666665","CapitalLongitude":"85.316667","CountryCode":"NP","ContinentName":"Asia"},{"CountryName":"Netherlands","CapitalName":"Amsterdam","CapitalLatitude":"52.35","CapitalLongitude":"4.916667","CountryCode":"NL","ContinentName":"Europe"},{"CountryName":"New Caledonia","CapitalName":"Noumea","CapitalLatitude":"-22.266666666666666","CapitalLongitude":"166.450000","CountryCode":"NC","ContinentName":"Australia"},{"CountryName":"New Zealand","CapitalName":"Wellington","CapitalLatitude":"-41.3","CapitalLongitude":"174.783333","CountryCode":"NZ","ContinentName":"Australia"},{"CountryName":"Nicaragua","CapitalName":"Managua","CapitalLatitude":"12.133333333333333","CapitalLongitude":"-86.250000","CountryCode":"NI","ContinentName":"Central America"},{"CountryName":"Niger","CapitalName":"Niamey","CapitalLatitude":"13.516666666666667","CapitalLongitude":"2.116667","CountryCode":"NE","ContinentName":"Africa"},{"CountryName":"Nigeria","CapitalName":"Abuja","CapitalLatitude":"9.083333333333334","CapitalLongitude":"7.533333","CountryCode":"NG","ContinentName":"Africa"},{"CountryName":"Niue","CapitalName":"Alofi","CapitalLatitude":"-19.016666666666666","CapitalLongitude":"-169.916667","CountryCode":"NU","ContinentName":"Australia"},{"CountryName":"Norfolk Island","CapitalName":"Kingston","CapitalLatitude":"-29.05","CapitalLongitude":"167.966667","CountryCode":"NF","ContinentName":"Australia"},{"CountryName":"Northern Mariana Islands","CapitalName":"Saipan","CapitalLatitude":"15.2","CapitalLongitude":"145.750000","CountryCode":"MP","ContinentName":"Australia"},{"CountryName":"Norway","CapitalName":"Oslo","CapitalLatitude":"59.916666666666664","CapitalLongitude":"10.750000","CountryCode":"NO","ContinentName":"Europe"},{"CountryName":"Oman","CapitalName":"Muscat","CapitalLatitude":"23.616666666666667","CapitalLongitude":"58.583333","CountryCode":"OM","ContinentName":"Asia"},{"CountryName":"Pakistan","CapitalName":"Islamabad","CapitalLatitude":"33.68333333333333","CapitalLongitude":"73.050000","CountryCode":"PK","ContinentName":"Asia"},{"CountryName":"Palau","CapitalName":"Melekeok","CapitalLatitude":"7.483333333333333","CapitalLongitude":"134.633333","CountryCode":"PW","ContinentName":"Australia"},{"CountryName":"Panama","CapitalName":"Panama City","CapitalLatitude":"8.966666666666667","CapitalLongitude":"-79.533333","CountryCode":"PA","ContinentName":"Central America"},{"CountryName":"Papua New Guinea","CapitalName":"Port Moresby","CapitalLatitude":"-9.45","CapitalLongitude":"147.183333","CountryCode":"PG","ContinentName":"Australia"},{"CountryName":"Paraguay","CapitalName":"Asuncion","CapitalLatitude":"-25.266666666666666","CapitalLongitude":"-57.666667","CountryCode":"PY","ContinentName":"South America"},{"CountryName":"Peru","CapitalName":"Lima","CapitalLatitude":"-12.05","CapitalLongitude":"-77.050000","CountryCode":"PE","ContinentName":"South America"},{"CountryName":"Philippines","CapitalName":"Manila","CapitalLatitude":"14.6","CapitalLongitude":"120.966667","CountryCode":"PH","ContinentName":"Asia"},{"CountryName":"Pitcairn Islands","CapitalName":"Adamstown","CapitalLatitude":"-25.066666666666666","CapitalLongitude":"-130.083333","CountryCode":"PN","ContinentName":"Australia"},{"CountryName":"Poland","CapitalName":"Warsaw","CapitalLatitude":"52.25","CapitalLongitude":"21.000000","CountryCode":"PL","ContinentName":"Europe"},{"CountryName":"Portugal","CapitalName":"Lisbon","CapitalLatitude":"38.71666666666667","CapitalLongitude":"-9.133333","CountryCode":"PT","ContinentName":"Europe"},{"CountryName":"Puerto Rico","CapitalName":"San Juan","CapitalLatitude":"18.466666666666665","CapitalLongitude":"-66.116667","CountryCode":"PR","ContinentName":"North America"},{"CountryName":"Qatar","CapitalName":"Doha","CapitalLatitude":"25.283333333333335","CapitalLongitude":"51.533333","CountryCode":"QA","ContinentName":"Asia"},{"CountryName":"Romania","CapitalName":"Bucharest","CapitalLatitude":"44.43333333333333","CapitalLongitude":"26.100000","CountryCode":"RO","ContinentName":"Europe"},{"CountryName":"Russia","CapitalName":"Moscow","CapitalLatitude":"55.75","CapitalLongitude":"37.600000","CountryCode":"RU","ContinentName":"Europe"},{"CountryName":"Rwanda","CapitalName":"Kigali","CapitalLatitude":"-1.95","CapitalLongitude":"30.050000","CountryCode":"RW","ContinentName":"Africa"},{"CountryName":"Saint Barthelemy","CapitalName":"Gustavia","CapitalLatitude":"17.883333333333333","CapitalLongitude":"-62.850000","CountryCode":"BL","ContinentName":"North America"},{"CountryName":"Saint Helena","CapitalName":"Jamestown","CapitalLatitude":"-15.933333333333334","CapitalLongitude":"-5.716667","CountryCode":"SH","ContinentName":"Africa"},{"CountryName":"Saint Kitts and Nevis","CapitalName":"Basseterre","CapitalLatitude":"17.3","CapitalLongitude":"-62.716667","CountryCode":"KN","ContinentName":"North America"},{"CountryName":"Saint Lucia","CapitalName":"Castries","CapitalLatitude":"14","CapitalLongitude":"-61.000000","CountryCode":"LC","ContinentName":"North America"},{"CountryName":"Saint Pierre and Miquelon","CapitalName":"Saint-Pierre","CapitalLatitude":"46.766666666666666","CapitalLongitude":"-56.183333","CountryCode":"PM","ContinentName":"Central America"},{"CountryName":"Saint Vincent and the Grenadines","CapitalName":"Kingstown","CapitalLatitude":"13.133333333333333","CapitalLongitude":"-61.216667","CountryCode":"VC","ContinentName":"Central America"},{"CountryName":"Samoa","CapitalName":"Apia","CapitalLatitude":"-13.816666666666666","CapitalLongitude":"-171.766667","CountryCode":"WS","ContinentName":"Australia"},{"CountryName":"San Marino","CapitalName":"San Marino","CapitalLatitude":"43.93333333333333","CapitalLongitude":"12.416667","CountryCode":"SM","ContinentName":"Europe"},{"CountryName":"Sao Tome and Principe","CapitalName":"Sao Tome","CapitalLatitude":"0.3333333333333333","CapitalLongitude":"6.733333","CountryCode":"ST","ContinentName":"Africa"},{"CountryName":"Saudi Arabia","CapitalName":"Riyadh","CapitalLatitude":"24.65","CapitalLongitude":"46.700000","CountryCode":"SA","ContinentName":"Asia"},{"CountryName":"Senegal","CapitalName":"Dakar","CapitalLatitude":"14.733333333333333","CapitalLongitude":"-17.633333","CountryCode":"SN","ContinentName":"Africa"},{"CountryName":"Serbia","CapitalName":"Belgrade","CapitalLatitude":"44.833333333333336","CapitalLongitude":"20.500000","CountryCode":"RS","ContinentName":"Europe"},{"CountryName":"Seychelles","CapitalName":"Victoria","CapitalLatitude":"-4.616666666666667","CapitalLongitude":"55.450000","CountryCode":"SC","ContinentName":"Africa"},{"CountryName":"Sierra Leone","CapitalName":"Freetown","CapitalLatitude":"8.483333333333333","CapitalLongitude":"-13.233333","CountryCode":"SL","ContinentName":"Africa"},{"CountryName":"Singapore","CapitalName":"Singapore","CapitalLatitude":"1.2833333333333332","CapitalLongitude":"103.850000","CountryCode":"SG","ContinentName":"Asia"},{"CountryName":"Sint Maarten","CapitalName":"Philipsburg","CapitalLatitude":"18.016666666666666","CapitalLongitude":"-63.033333","CountryCode":"SX","ContinentName":"North America"},{"CountryName":"Slovakia","CapitalName":"Bratislava","CapitalLatitude":"48.15","CapitalLongitude":"17.116667","CountryCode":"SK","ContinentName":"Europe"},{"CountryName":"Slovenia","CapitalName":"Ljubljana","CapitalLatitude":"46.05","CapitalLongitude":"14.516667","CountryCode":"SI","ContinentName":"Europe"},{"CountryName":"Solomon Islands","CapitalName":"Honiara","CapitalLatitude":"-9.433333333333334","CapitalLongitude":"159.950000","CountryCode":"SB","ContinentName":"Australia"},{"CountryName":"Somalia","CapitalName":"Mogadishu","CapitalLatitude":"2.066666666666667","CapitalLongitude":"45.333333","CountryCode":"SO","ContinentName":"Africa"},{"CountryName":"South Africa","CapitalName":"Pretoria","CapitalLatitude":"-25.7","CapitalLongitude":"28.216667","CountryCode":"ZA","ContinentName":"Africa"},{"CountryName":"South Sudan","CapitalName":"Juba","CapitalLatitude":"4.85","CapitalLongitude":"31.616667","CountryCode":"SS","ContinentName":"Africa"},{"CountryName":"Spain","CapitalName":"Madrid","CapitalLatitude":"40.4","CapitalLongitude":"-3.683333","CountryCode":"ES","ContinentName":"Europe"},{"CountryName":"Sri Lanka","CapitalName":"Colombo","CapitalLatitude":"6.916666666666667","CapitalLongitude":"79.833333","CountryCode":"LK","ContinentName":"Asia"},{"CountryName":"Sudan","CapitalName":"Khartoum","CapitalLatitude":"15.6","CapitalLongitude":"32.533333","CountryCode":"SD","ContinentName":"Africa"},{"CountryName":"Suriname","CapitalName":"Paramaribo","CapitalLatitude":"5.833333333333333","CapitalLongitude":"-55.166667","CountryCode":"SR","ContinentName":"South America"},{"CountryName":"Svalbard","CapitalName":"Longyearbyen","CapitalLatitude":"78.21666666666667","CapitalLongitude":"15.633333","CountryCode":"SJ","ContinentName":"Europe"},{"CountryName":"Swaziland","CapitalName":"Mbabane","CapitalLatitude":"-26.316666666666666","CapitalLongitude":"31.133333","CountryCode":"SZ","ContinentName":"Africa"},{"CountryName":"Sweden","CapitalName":"Stockholm","CapitalLatitude":"59.333333333333336","CapitalLongitude":"18.050000","CountryCode":"SE","ContinentName":"Europe"},{"CountryName":"Switzerland","CapitalName":"Bern","CapitalLatitude":"46.916666666666664","CapitalLongitude":"7.466667","CountryCode":"CH","ContinentName":"Europe"},{"CountryName":"Syria","CapitalName":"Damascus","CapitalLatitude":"33.5","CapitalLongitude":"36.300000","CountryCode":"SY","ContinentName":"Asia"},{"CountryName":"Taiwan","CapitalName":"Taipei","CapitalLatitude":"25.033333333333335","CapitalLongitude":"121.516667","CountryCode":"TW","ContinentName":"Asia"},{"CountryName":"Tajikistan","CapitalName":"Dushanbe","CapitalLatitude":"38.55","CapitalLongitude":"68.766667","CountryCode":"TJ","ContinentName":"Asia"},{"CountryName":"Tanzania","CapitalName":"Dar es Salaam","CapitalLatitude":"-6.8","CapitalLongitude":"39.283333","CountryCode":"TZ","ContinentName":"Africa"},{"CountryName":"Thailand","CapitalName":"Bangkok","CapitalLatitude":"13.75","CapitalLongitude":"100.516667","CountryCode":"TH","ContinentName":"Asia"},{"CountryName":"Timor-Leste","CapitalName":"Dili","CapitalLatitude":"-8.583333333333334","CapitalLongitude":"125.600000","CountryCode":"TL","ContinentName":"Asia"},{"CountryName":"Togo","CapitalName":"Lome","CapitalLatitude":"6.116666666666666","CapitalLongitude":"1.216667","CountryCode":"TG","ContinentName":"Africa"},{"CountryName":"Tonga","CapitalName":"Nuku'alofa","CapitalLatitude":"-21.133333333333333","CapitalLongitude":"-175.200000","CountryCode":"TO","ContinentName":"Australia"},{"CountryName":"Trinidad and Tobago","CapitalName":"Port of Spain","CapitalLatitude":"10.65","CapitalLongitude":"-61.516667","CountryCode":"TT","ContinentName":"North America"},{"CountryName":"Tunisia","CapitalName":"Tunis","CapitalLatitude":"36.8","CapitalLongitude":"10.183333","CountryCode":"TN","ContinentName":"Africa"},{"CountryName":"Turkey","CapitalName":"Ankara","CapitalLatitude":"39.93333333333333","CapitalLongitude":"32.866667","CountryCode":"TR","ContinentName":"Europe"},{"CountryName":"Turkmenistan","CapitalName":"Ashgabat","CapitalLatitude":"37.95","CapitalLongitude":"58.383333","CountryCode":"TM","ContinentName":"Asia"},{"CountryName":"Turks and Caicos Islands","CapitalName":"Grand Turk","CapitalLatitude":"21.466666666666665","CapitalLongitude":"-71.133333","CountryCode":"TC","ContinentName":"North America"},{"CountryName":"Tuvalu","CapitalName":"Funafuti","CapitalLatitude":"-8.516666666666667","CapitalLongitude":"179.216667","CountryCode":"TV","ContinentName":"Australia"},{"CountryName":"Uganda","CapitalName":"Kampala","CapitalLatitude":"0.31666666666666665","CapitalLongitude":"32.550000","CountryCode":"UG","ContinentName":"Africa"},{"CountryName":"Ukraine","CapitalName":"Kyiv","CapitalLatitude":"50.43333333333333","CapitalLongitude":"30.516667","CountryCode":"UA","ContinentName":"Europe"},{"CountryName":"United Arab Emirates","CapitalName":"Abu Dhabi","CapitalLatitude":"24.466666666666665","CapitalLongitude":"54.366667","CountryCode":"AE","ContinentName":"Asia"},{"CountryName":"United Kingdom","CapitalName":"London","CapitalLatitude":"51.5","CapitalLongitude":"-0.083333","CountryCode":"GB","ContinentName":"Europe"},{"CountryName":"United States","CapitalName":"Washington","CapitalLatitude":" D.C.","CapitalLongitude":"38.883333","CountryCode":"-77.000000","ContinentName":"US"},{"CountryName":"Uruguay","CapitalName":"Montevideo","CapitalLatitude":"-34.85","CapitalLongitude":"-56.166667","CountryCode":"UY","ContinentName":"South America"},{"CountryName":"Uzbekistan","CapitalName":"Tashkent","CapitalLatitude":"41.31666666666667","CapitalLongitude":"69.250000","CountryCode":"UZ","ContinentName":"Asia"},{"CountryName":"Vanuatu","CapitalName":"Port-Vila","CapitalLatitude":"-17.733333333333334","CapitalLongitude":"168.316667","CountryCode":"VU","ContinentName":"Australia"},{"CountryName":"Venezuela","CapitalName":"Caracas","CapitalLatitude":"10.483333333333333","CapitalLongitude":"-66.866667","CountryCode":"VE","ContinentName":"South America"},{"CountryName":"Vietnam","CapitalName":"Hanoi","CapitalLatitude":"21.033333333333335","CapitalLongitude":"105.850000","CountryCode":"VN","ContinentName":"Asia"},{"CountryName":"US Virgin Islands","CapitalName":"Charlotte Amalie","CapitalLatitude":"18.35","CapitalLongitude":"-64.933333","CountryCode":"VI","ContinentName":"North America"},{"CountryName":"Wallis and Futuna","CapitalName":"Mata-Utu","CapitalLatitude":"-13.95","CapitalLongitude":"-171.933333","CountryCode":"WF","ContinentName":"Australia"},{"CountryName":"Yemen","CapitalName":"Sanaa","CapitalLatitude":"15.35","CapitalLongitude":"44.200000","CountryCode":"YE","ContinentName":"Asia"},{"CountryName":"Zambia","CapitalName":"Lusaka","CapitalLatitude":"-15.416666666666666","CapitalLongitude":"28.283333","CountryCode":"ZM","ContinentName":"Africa"},{"CountryName":"Zimbabwe","CapitalName":"Harare","CapitalLatitude":"-17.816666666666666","CapitalLongitude":"31.033333","CountryCode":"ZW","ContinentName":"Africa"},{"CountryName":"US Minor Outlying Islands","CapitalName":"Washington","CapitalLatitude":" D.C.","CapitalLongitude":"38.883333","CountryCode":"-77.000000","ContinentName":"UM"},{"CountryName":"Antarctica","CapitalName":"N/A","CapitalLatitude":"0","CapitalLongitude":"0.000000","CountryCode":"AQ","ContinentName":"Antarctica"},{"CountryName":"Northern Cyprus","CapitalName":"North Nicosia","CapitalLatitude":"35.183333","CapitalLongitude":"33.366667","CountryCode":"NULL","ContinentName":"Europe"},{"CountryName":"Hong Kong","CapitalName":"N/A","CapitalLatitude":"0","CapitalLongitude":"0.000000","CountryCode":"HK","ContinentName":"Asia"},{"CountryName":"Heard Island and McDonald Islands","CapitalName":"N/A","CapitalLatitude":"0","CapitalLongitude":"0.000000","CountryCode":"HM","ContinentName":"Antarctica"},{"CountryName":"British Indian Ocean Territory","CapitalName":"Diego Garcia","CapitalLatitude":"-7.3","CapitalLongitude":"72.400000","CountryCode":"IO","ContinentName":"Africa"},{"CountryName":"Macau","CapitalName":"N/A","CapitalLatitude":"0","CapitalLongitude":"0.000000","CountryCode":"MO","ContinentName":"Asia"}] \ No newline at end of file diff --git a/db_insert_data.py b/db_insert_data.py index 2cc8a1b..5982a54 100644 --- a/db_insert_data.py +++ b/db_insert_data.py @@ -1,3 +1,4 @@ +from conf import postgres_con from weather_api_client import WeatherApiClient from news_api_client import NewsApiClient from weatherbit_api_client import WeatherbitApiClient @@ -6,79 +7,126 @@ from db_creation import Country, City, News, Weather from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker -import json import time -import pycountry -with open('country-capitals.json') as capitals: - data_capitals = json.load(capitals) - formatted_capitals = [cap['CapitalName'] for cap in data_capitals if cap['CapitalName'] != "N/A"] +class InsertData: + engine = create_engine(postgres_con['c_str']) + @staticmethod + def check_country_id(country_name): + session = sessionmaker(bind=InsertData.engine)() + country_object = session.query(Country).filter(Country.name == country_name).first() + session.close() + if country_object: + return country_object.id + return None -class InsertData: + @staticmethod + def check_news(country_id): + session = sessionmaker(bind=InsertData.engine)() + actual_news = [] + for instance in session.query(News).filter(News.country_id == country_id).order_by(News.date.desc()).limit(3): + actual_news.append({'title': instance.title, 'body': instance.body}) + session.close() + return actual_news @staticmethod - def insert_data_news_api(): - engine = create_engine("postgresql://postgres:123QWEasd@localhost:5432/api_data_test_2") - session_maker = sessionmaker(bind=engine) - session = session_maker() - main_countries = [] - for country in list(pycountry.countries): - if country.alpha_2 in ['US', 'CA', 'GB', 'DE', 'JP', 'CN', 'ES', 'GR', 'FR', 'IT']: - main_countries.append(country) - main_countries = [country.alpha_2 for country in main_countries] - # countries = [country.alpha_2 for country in list(pycountry.countries)] - identifier_c = 0 - identifier_n = 0 - for c in main_countries[0:4]: - identifier_c += 1 - country = Country() - country.id = identifier_c - country.name = c - session.add(country) - time.sleep(1) - try: - whole_news = NewsApiClient(c) - except ApiNotAvailableException: - whole_news = LentaParser() - top_news = whole_news.get_top_news() - for content in top_news: - identifier_n += 2 - news = News() - news.id = identifier_n - news.country_id = country.id - news.title = content['title'] - news.body = content['body'] - session.add(news) + def insert_country(country_name): + session = sessionmaker(bind=InsertData.engine)() + country = Country() + country.name = country_name + session.add(country) + session.flush() + country_id = country.id session.commit() session.close() + return country_id @staticmethod - def insert_data_weather_api(): - engine = create_engine("postgresql://postgres:123QWEasd@localhost:5432/api_data_test") - session_maker = sessionmaker(bind=engine) - session = session_maker() - identifier_c = 0 - identifier_n = 0 - for c in formatted_capitals[0:10]: - identifier_c += 1 - city = City() - city.id = identifier_c - city.name = c - session.add(city) + def insert_data_news_api(country, country_id): + session = sessionmaker(bind=InsertData.engine)() + try: + whole_news = NewsApiClient(country) + except ApiNotAvailableException: time.sleep(1) - try: - new_weather = WeatherApiClient(c) - except ApiNotAvailableException: - new_weather = WeatherbitApiClient(c) - identifier_n += 2 - weather = Weather() - weather.id = identifier_n - weather.city_id = city.id - weather.weather_info = new_weather.get_weather_description() - weather.temp_in_c = new_weather.get_temperature()[0] - weather.wind_speed_kmph = new_weather.get_wind()[0] - session.add(weather) + whole_news = LentaParser() + top_news = whole_news.get_top_news() + actual_news = [] + for content in top_news: + news = News() + news.country_id = country_id + news.title = content['title'] + news.body = content['body'] + actual_news.append({'title': news.title, 'body': news.body}) + session.add(news) session.commit() session.close() + return actual_news + + @staticmethod + def check_city_id(city_name): + session = sessionmaker(bind=InsertData.engine)() + city_object = session.query(City).filter(City.name == city_name).first() + session.close() + if city_object: + return city_object.id + return None + + @staticmethod + def check_weather(city_id): + session = sessionmaker(bind=InsertData.engine)() + actual_weather = [] + for instance in session.query(Weather).filter(Weather.city_id == city_id)\ + .order_by(Weather.date.desc())\ + .limit(1): + actual_weather.append({ + 'temperature_info': [instance.temp_in_c, 'celsius'], + 'weather_info': instance.weather_info, + 'wind_info': [instance.wind_speed_kmph, 'km/h'] + }) + session.close() + return actual_weather + + @staticmethod + def insert_city(city_name): + session = sessionmaker(bind=InsertData.engine)() + city = City() + city.name = city_name + session.add(city) + session.flush() + city_id = city.id + session.commit() + session.close() + return city_id + + @staticmethod + def insert_data_weather_api(city, city_id): + session = sessionmaker(bind=InsertData.engine)() + try: + new_weather = WeatherApiClient(city) + except ApiNotAvailableException: + new_weather = WeatherbitApiClient(city) + weather = Weather() + weather.city_id = city_id + weather.weather_info = new_weather.get_weather_description() + weather.temp_in_c = new_weather.get_temperature()[0] + weather.wind_speed_kmph = new_weather.get_wind()[0] + session.add(weather) + actual_weather = { + "wind_info": [weather.wind_speed_kmph, 'km/h'], + "weather_info": weather.weather_info, + "temperature_info": [weather.temp_in_c, "celsius"] + } + session.commit() + session.close() + return actual_weather + + @staticmethod + def get_cities(): + actual_city = [] + session = sessionmaker(bind=InsertData.engine)() + city_objects = session.query.with_entities(City.name).distinct() + for city in city_objects: + actual_city.append(city) + return actual_city diff --git a/index.py b/index.py index c1a7bd6..590722a 100644 --- a/index.py +++ b/index.py @@ -1,15 +1,8 @@ -from weather_api_client import WeatherApiClient -from news_api_client import NewsApiClient -from weatherbit_api_client import WeatherbitApiClient -from LentaParser import LentaParser -from flask import Flask -from flask import request +from flask import Flask, request, jsonify from GetValidator import RunRequestSchema from flask_restful import Api -from flask import jsonify -from api_not_available import ApiNotAvailableException -from allcities import cities -import pycountry +from city_to_country import city_to_country +from db_insert_data import InsertData app = Flask(__name__) @@ -24,31 +17,25 @@ def current_data(): if errors: raise ValueError(("An error occurred with input: {}".format(errors))) city = request.args.get('city') - filtered_city_set = cities.filter(name=city, population='>100000') - largest_city = next(iter(filtered_city_set)) - if largest_city.dict['country_code'] in [country.alpha_2 for country in list(pycountry.countries)]: - country = largest_city.dict['country_code'] - try: - new_weather = WeatherApiClient(city) - except ApiNotAvailableException: - new_weather = WeatherbitApiClient(city) - try: - news = NewsApiClient(country) - except ApiNotAvailableException: - news = LentaParser() - wind_info = new_weather.get_wind() - weather_info = new_weather.get_weather_description() - temperature_info = new_weather.get_temperature() - data = { - "city": city, - "country": country, - "hot_news": news.get_top_news(), - "local_weather": {"wind_info": wind_info, - "weather_info": weather_info, - "temperature_info": temperature_info - } - } - return jsonify(data) + country = city_to_country(city) + country_id = InsertData.check_country_id(country) + city_id = InsertData.check_city_id(city) + if not country_id and not city_id: + country_id = InsertData.insert_country(country) + city_id = InsertData.insert_city(city) + actual_weather = InsertData.insert_data_weather_api(city, city_id) + actual_news = InsertData.insert_data_news_api(country, country_id) + else: + actual_weather = InsertData.check_weather(city_id) + actual_news = InsertData.check_news(country_id) + print(actual_news) + data = { + "city": city, + "country": country, + "hot_news": actual_news, + "local_weather": actual_weather + } + return jsonify(data) if __name__ == '__main__': From 9922ea94c0cd3ad7f15f36af051c1842b676bde6 Mon Sep 17 00:00:00 2001 From: Dima Date: Tue, 2 Mar 2021 22:24:04 +0600 Subject: [PATCH 16/16] Cache_data_job.py has been refactored, a runner with the same name also has been made. --- cache_data_job.py | 9 ++++++--- cache_data_job_runner.bat | 1 + db_creation.py | 2 +- db_insert_data.py | 13 +++++++++---- index.py | 1 + 5 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 cache_data_job_runner.bat diff --git a/cache_data_job.py b/cache_data_job.py index 115cae8..6796081 100644 --- a/cache_data_job.py +++ b/cache_data_job.py @@ -4,10 +4,13 @@ def cache_data_job(): cities = InsertData.get_cities() - countries = (city_to_country(city) for city in cities) - city_ids = (InsertData.check_city_id(city) for city in cities) - country_ids = (InsertData.check_country_id(country) for country in countries) + countries = [city_to_country(city) for city in cities] + city_ids = [InsertData.check_city_id(city) for city in cities] + country_ids = [InsertData.check_country_id(country) for country in countries] for city, city_id in zip(cities, city_ids): InsertData.insert_data_weather_api(city, city_id) for country, country_id in zip(countries, country_ids): InsertData.insert_data_news_api(country, country_id) + + +cache_data_job() diff --git a/cache_data_job_runner.bat b/cache_data_job_runner.bat new file mode 100644 index 0000000..0614793 --- /dev/null +++ b/cache_data_job_runner.bat @@ -0,0 +1 @@ +C:\Users\Admin\anaconda3\python.exe "f:/HDD2/projects_py/get_weather/cache_data_job.py" \ No newline at end of file diff --git a/db_creation.py b/db_creation.py index 3637e91..75ef644 100644 --- a/db_creation.py +++ b/db_creation.py @@ -1,4 +1,4 @@ -from sqlalchemy import create_engine, func, Column, Integer, String, ForeignKey, DateTime, CheckConstraint +from sqlalchemy import create_engine, func, Column, Integer, String, ForeignKey, DateTime from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship diff --git a/db_insert_data.py b/db_insert_data.py index 5982a54..1c6a64a 100644 --- a/db_insert_data.py +++ b/db_insert_data.py @@ -62,7 +62,10 @@ def insert_data_news_api(country, country_id): session.add(news) session.commit() session.close() - return actual_news + if actual_news: + return actual_news + raise RuntimeError('Error during the data processing') + @staticmethod def check_city_id(city_name): @@ -120,13 +123,15 @@ def insert_data_weather_api(city, city_id): } session.commit() session.close() - return actual_weather + if actual_weather: + return actual_weather + raise RuntimeError('Error during the data processing') @staticmethod def get_cities(): actual_city = [] session = sessionmaker(bind=InsertData.engine)() - city_objects = session.query.with_entities(City.name).distinct() + city_objects = session.query(City).order_by(City.name).distinct() for city in city_objects: - actual_city.append(city) + actual_city.append(city.name) return actual_city diff --git a/index.py b/index.py index 590722a..f4296d5 100644 --- a/index.py +++ b/index.py @@ -22,6 +22,7 @@ def current_data(): city_id = InsertData.check_city_id(city) if not country_id and not city_id: country_id = InsertData.insert_country(country) + print(country_id) city_id = InsertData.insert_city(city) actual_weather = InsertData.insert_data_weather_api(city, city_id) actual_news = InsertData.insert_data_news_api(country, country_id)