def fetch_content(self, start_date, coin): """ Ingresa al navegador utilizando la fecha y la moneda que recibe. La fecha por default es hoy, en caso de pasarle otra fecha va a traer el contenido desde esa fecha hasta hoy. Retorna un string que contiene el html obtenido. Parameters ---------- start_date : date fecha de inicio que va a tomar como referencia el scraper coin: str Nombre de cada moneda """ content = '' counter = 1 tries = self.tries while counter <= tries: try: browser_driver = self.get_browser_driver() browser_driver.get(self.url) element_present = EC.presence_of_element_located( (By.NAME, 'Fecha')) elem = WebDriverWait(browser_driver, 0).until(element_present) elem.send_keys(start_date.strftime("%d/%m/%Y")) element = browser_driver.find_element_by_name('Moneda') options = element.find_elements_by_tag_name('option') valid = self.validate_coin_in_configuration_file(coin, options) if valid: element.send_keys(coin) submit_button = browser_driver.find_element_by_class_name( 'btn-primary') submit_button.click() content = browser_driver.page_source except TimeoutException: if counter < tries: logging.warning( f'La conexion de internet ha fallado para la fecha {start_date}. Reintentando...' ) counter = counter + 1 else: logging.warning( f'La conexion de internet ha fallado para la fecha {start_date}' ) raise InvalidConfigurationError( f'La conexion de internet ha fallado para la fecha {start_date}' ) except NoSuchElementException: raise InvalidConfigurationError( f'La conexion de internet ha fallado para la fecha {start_date}' ) break return content
def validate_dates(start_date, end_date): if start_date > end_date: raise InvalidConfigurationError( "La fecha de inicio no debe ser mayor a la de fin") elif end_date > datetime.today(): raise InvalidConfigurationError( "La fecha de fin no puede ser mayor a la fecha actual")
def validate_refetch_dates(start_date, end_date, refetch_start_date, refetch_end_date): if refetch_start_date < start_date: raise InvalidConfigurationError( "La fecha de refetch_start_date no debe ser menor a la fecha de inicio" ) elif refetch_end_date > end_date: raise InvalidConfigurationError( "La fecha de refetch_end_date no puede ser mayor a la fecha de fin" )
def fetch_content(self, coin): """ Ingresa al navegador y utiliza la moneda regresando el contenido que pertenece a la misma. Parameters ---------- coins : String String que contiene el nombre de la moneda """ content = '' counter = 1 tries = self.tries while counter <= tries: try: browser_driver = self.get_browser_driver() browser_driver.get(self.url) element_present = EC.presence_of_element_located( (By.NAME, 'moneda')) element = WebDriverWait(browser_driver, 0).until(element_present) options = element.find_elements_by_tag_name('option') valid = self.validate_coin_in_configuration_file(coin, options) if valid: element.send_keys(coin) content = browser_driver.page_source except NoSuchElementException: raise InvalidConfigurationError( f'La conexion de internet ha fallado para la moneda {coin}' ) except (TimeoutException, WebDriverException): if counter < tries: logging.warning( f'La conexion de internet ha fallado para la moneda {coin}. Reintentando...' ) counter = counter + 1 else: logging.warning( f'La conexion de internet ha fallado para la moneda {coin}' ) raise InvalidConfigurationError( f'La conexion de internet ha fallado para la moneda {coin}' ) break return content
def fetch_day_content(self, single_date): """ Ingresa al navegador y retorna un html correspondiente a la fecha que recibe Parameters ---------- single_date : date fecha que va a tomar como referencia el scraper """ content_dict = {} content = '' counter = 1 tries = self.tries while counter <= tries: try: browser_driver = self.get_browser_driver() browser_driver.get(self.url) element_present = EC.presence_of_element_located( (By.NAME, 'fecha')) element = WebDriverWait(browser_driver, 0).until(element_present) element.send_keys( single_date.strftime("%d/%m/%Y") + Keys.RETURN) content = browser_driver.page_source content_dict[f'{single_date.strftime("%Y-%m-%d")}'] = content except NoSuchElementException: raise InvalidConfigurationError( f'La conexion de internet ha fallado para la fecha {single_date}' ) except (TimeoutException, WebDriverException): if counter < tries: logging.warning( f'La conexion de internet ha fallado para la fecha {single_date}. Reintentando...' ) counter = counter + 1 else: logging.warning( f'La conexion de internet ha fallado para la fecha {single_date}' ) raise InvalidConfigurationError( f'La conexion de internet ha fallado para la fecha {single_date}' ) break return content_dict
def read_config(file_path, command): try: with open(file_path) as config_data: return json.load(config_data)[command] except JSONDecodeError: raise InvalidConfigurationError( "El formato del archivo de configuración es inválido")
def preprocess_start_date(self, start_date, end_date): counter = 1 tries = self.tries while counter <= tries: try: browser_driver = self.get_browser_driver() browser_driver.get(self.url) element_present = EC.presence_of_element_located( (By.NAME, 'Fecha')) elem = WebDriverWait(browser_driver, 0).until(element_present) if not start_date.strftime("%d/%m/%Y") in elem.text: logging.warning( f'La fecha {start_date.strftime("%d/%m/%Y")} no existe' ) if start_date < end_date: start_date = start_date + timedelta(days=1) logging.warning( f'La nueva fecha de inicio es {start_date}') else: raise InvalidConfigurationError( 'La fecha de inicio no puede ser mayor a la fecha de fin' ) return start_date except (TimeoutException, WebDriverException): if counter <= tries: logging.warning( f'La conexion de internet ha fallado para la fecha {start_date}. Reintentando...' ) counter = counter + 1
def validate_file_path(file_path, config, file_path_key): try: file_path = file_path or config.get(file_path_key) file_path = (file_path if file_path.startswith('/') else os.path.join( ROOT_DIR, file_path)) except Exception: raise InvalidConfigurationError( f"Error: No hay configuración para {file_path_key}") return file_path
def rates_config_validator(self, parsed, rates): """Valida que parsed exista dentro de los valores de rates en el archivo de configuración Parameters ---------- parsed : String String con la clave correspondiente al plazo en días rates : Dict Diccionario que contiene los plazos en días de la tasa Libor """ if f'libor_{parsed}_dias' in rates.values(): return True else: raise InvalidConfigurationError( f'La clave libor_{parsed}_dias ' + 'no se encuentra en el archivo de config')
def read_intermediate_panel_dataframe(self): """ Lee el dataframe """ intermediate_panel_dataframe = None try: intermediate_panel_dataframe = pd.read_csv( 'libor-intermediate-panel.csv', converters={ 'serie_tiempo': lambda _: _, 'type': lambda _: str(_), 'value': lambda _: Decimal(_) if _ else None }) except FileNotFoundError: raise InvalidConfigurationError("El archivo panel no existe") return intermediate_panel_dataframe
def fetch_content(self, single_date, coin): """ Ingresa al navegador y utiliza la moneda regresando el contenido que pertenece a la misma. Parameters ---------- single_date : date Fecha de inicio que toma como referencia el scraper coin : String String que contiene el nombre de la moneda """ content_dict = {} content = '' counter = 1 tries = self.tries while counter <= tries: try: browser_driver = self.get_browser_driver() browser_driver.get(self.url) element_present = EC.presence_of_element_located( (By.NAME, 'moneda')) element = WebDriverWait(browser_driver, 0).until(element_present) options = element.find_elements_by_tag_name('option') valid = self.validate_coin_in_configuration_file(coin, options) if valid: element.send_keys(coin) browser_driver.execute_script( 'document.getElementsByName("fecha")\ [0].removeAttribute("readonly")') elem = browser_driver.find_element_by_name('fecha') elem.send_keys(single_date.strftime("%d/%m/%Y")) submit_button = browser_driver.find_element_by_class_name( 'btn-primary') submit_button.click() content = browser_driver.page_source content_dict[ 'indice_tiempo'] = f'{single_date.strftime("%Y-%m-%d")}' content_dict['content'] = content except NoSuchElementException: raise InvalidConfigurationError( f'La conexion de internet ha fallado para la fecha {single_date}' ) except (TimeoutException, WebDriverException): if counter < tries: logging.warning( f'La conexion de internet ha fallado para la fecha {single_date}. Reintentando...' ) counter = counter + 1 else: logging.warning( f'La conexion de internet ha fallado para la fecha {single_date}' ) raise InvalidConfigurationError( f'La conexion de internet ha fallado para la fecha {single_date}' ) break return content_dict
def validate_entities_key_config(config): if 'entities' not in config: raise InvalidConfigurationError("La clave entities no existe")
def validate_coins_key_config(config): if 'coins' not in config: raise InvalidConfigurationError("La clave coins no existe")
def validate_coins_key_has_values(config): coins = config.get('coins', {}) if coins == {}: raise InvalidConfigurationError("No existen valores para coins")
def validate_libor_rates_has_values(config): rates = config.get('rates', {}) if rates == {}: raise InvalidConfigurationError("No existen valores para rates")
def validate_libor_rates_config(config): if 'rates' not in config: raise InvalidConfigurationError("La clave rates no existe")
def validate_url_has_value(config): if config['url'] == '': raise InvalidConfigurationError("La url no es válida")
def validate_url_config(config): if 'url' not in config: raise InvalidConfigurationError("La clave url no existe")
def validate_entities_key_has_values(config): entities = config.get('entities', {}) if entities == {}: raise InvalidConfigurationError("No existen valores para entities")