From 2c57cc762fd8578ce849c36a4819c8700de5489a Mon Sep 17 00:00:00 2001 From: Jesus Galindez Date: Wed, 28 Aug 2024 23:34:11 -0500 Subject: [PATCH] Fix script para data desde Exchange Monitor --- pyDolarVenezuela/pages.py | 2 +- pyDolarVenezuela/providers/exchangemonitor.py | 102 +++++++++--------- pyDolarVenezuela/utils/common.py | 23 ++++ 3 files changed, 75 insertions(+), 52 deletions(-) create mode 100644 pyDolarVenezuela/utils/common.py diff --git a/pyDolarVenezuela/pages.py b/pyDolarVenezuela/pages.py index faec0b8..2910adb 100644 --- a/pyDolarVenezuela/pages.py +++ b/pyDolarVenezuela/pages.py @@ -14,7 +14,7 @@ ExchangeMonitor = Page( name="Exchange Monitor", - provider="https://exchangemonitor.net/", + provider="https://exchangemonitor.net", currencies=['usd', 'eur'] ) diff --git a/pyDolarVenezuela/providers/exchangemonitor.py b/pyDolarVenezuela/providers/exchangemonitor.py index c7e5a41..bc79bf9 100644 --- a/pyDolarVenezuela/providers/exchangemonitor.py +++ b/pyDolarVenezuela/providers/exchangemonitor.py @@ -1,62 +1,62 @@ from typing import Any, Dict, List -from bs4 import BeautifulSoup +from datetime import datetime +import requests +import pytz + +from ..network import _headers +from ..utils.common import _convert_specific_format, _parse_price, _parse_percent +from ..utils.time import get_formatted_date -from .. import network -from ..utils import time -from ..utils.extras import list_monitors_images from ._base import Base from ..pages import ExchangeMonitor as ExchangeMonitorPage -def _convert_specific_format(text: str, character: str = '_') -> str: - acentos = {'á': 'a', 'é': 'e', 'í': 'i', 'ó': 'o', 'ú': 'u'} - for acento, sin_acento in acentos.items(): - text = text.lower().replace(acento, sin_acento).replace(' ', character) - return text - -def _get_values_monitors(soup: BeautifulSoup): - return [value for value in soup] class ExchangeMonitor(Base): PAGE = ExchangeMonitorPage @classmethod def _load(cls, **kwargs) -> List[Dict[str, Any]]: - url = f'{cls.PAGE.provider}dolar-venezuela' if not kwargs.get('currency') == 'usd' else f'{cls.PAGE.provider}dolar-venezuela/EUR' - response = network.curl('GET', url) - soup = BeautifulSoup(response, 'html.parser') - - section_dolar_venezuela = soup.find_all("div", "col-xs-12 col-sm-6 col-md-4 col-tabla") - _scraping_monitors = _get_values_monitors(section_dolar_venezuela) - data = [] - - for scraping_monitor in _scraping_monitors: - result = scraping_monitor.find("div", "module-table module-table-fecha") - - name = result.find("h6", "nombre").text - key = _convert_specific_format(name) - price = str(result.find('p', "precio").text).replace(',', '.') - - if price.count('.') == 2: - price = price.replace('.', '', 1) - - price = float(price) - last_update = time.get_formatted_time(' '.join(str(result.find('p', "fecha").text).split(' ')[1:]).capitalize()) - symbol = str(result.find('p', "cambio-por").text)[0] if not str(result.find('p', "cambio-por").text)[0] == ' ' else '' - color = "red" if symbol == '▼' else "green" if symbol == '▲' else "neutral" - percent = float(str(result.find('p', "cambio-por").text)[1:].strip().replace(',', '.').replace('%', '')) - change = float(str(result.find('p', "cambio-num").text).replace(',', '.')) - image = next((image.image for image in list_monitors_images if image.provider == 'exchangemonitor' and image.title == _convert_specific_format(name)), None) - - data.append({ - 'key': key, - 'title': name, - 'price': price, - 'last_update': last_update, - 'percent': percent, - 'change': change, - 'color': color, - 'symbol': symbol, - 'image': image - }) - - return data \ No newline at end of file + tz = pytz.timezone('America/Caracas') + + url = f'{cls.PAGE.provider}/data/data-rates/ve' + + # Realizar la solicitud GET a la API + response = requests.get(url, headers=_headers) + + # Verificar que la solicitud fue exitosa + if response.status_code == 200: + data_json = response.json() + + # Extraer los datos requeridos + result = [] + for item in data_json["data"]: + # Parsear la fecha y hora (sin zona horaria) + date_naive = datetime.strptime(item.get("date"), "%d-%m-%Y %I:%M %p") + + # Asignar y formatear valores + date_aware = str(tz.localize(date_naive)) + logo = item.get("logo") + net_change = _parse_percent(item.get("change_rate")) + net_chg = str(item.get("change_rate")) + color = "red" if "-" in net_chg else "green" if "+" in net_chg else "" + symbol = "▼" if "-" in net_chg else "▲" if "+" in net_chg else "neutral" + + extracted_data = { + "key": _convert_specific_format(item.get("id")), + "title": _convert_specific_format(item.get("name")), + "price": _parse_price(item.get("rate")), + "price_old": _parse_price(item.get("last_rate")), + "last_update":get_formatted_date(date_aware), + "percent": _parse_percent(item.get("change_perc")), + "change": net_change, + "color": color, + "symbol": symbol, + "image": f'{cls.PAGE.provider}{logo}' + } + result.append(extracted_data) + + return result + + else: + print(f"Error retrieving data from API: {response.status_code}") + return [] diff --git a/pyDolarVenezuela/utils/common.py b/pyDolarVenezuela/utils/common.py new file mode 100644 index 0000000..9aeb7c3 --- /dev/null +++ b/pyDolarVenezuela/utils/common.py @@ -0,0 +1,23 @@ +def _convert_specific_format(text: str, character: str = '_') -> str: + """ + Formatea el nombre de moneda para omologar todas las salidas de los datos de un monitor específico. + """ + acentos = {'á': 'a', 'é': 'e', 'í': 'i', 'ó': 'o', 'ú': 'u'} + for acento, sin_acento in acentos.items(): + text = text.lower().replace(acento, sin_acento).replace(' ', character) + return text + +def _parse_price(price: str) -> float: + """ + Convierte el formato de una moneda a de "," al uso del "." (Formato standard). + """ + price = price.replace(',', '.') + if price.count('.') == 2: + price = price.replace('.', '', 1) + return float(price) + +def _parse_percent(percent: str) -> float: + """ + Convierte el formato del cambio porcentual de "," al uso del "." y agrega el simbolo "%". + """ + return float(percent.strip().replace(',', '.').replace('%', ''))