Inicio Apuntes FPApuntes DAMAcceso a Datos Gasoliprecio, busca las estaciones de servicio con el mejor precio

Gasoliprecio, busca las estaciones de servicio con el mejor precio

Creado con Python y Flet

Publicado por entreunosyceros

Una vez más aquí. Después de algunas semanas sin tiempo para nada, ahora que me he puesto con un curso de programación de sistemas, me encuentro con algo más de tiempo. Y por eso vengo a dejar algo que la semana pasada me vino a la cabeza cuando me dirigía al curso y tuve que buscar una estación de servicio para repostar combustible. En ese momento me acordé de la funcionalidad que tiene google maps de buscar gasolineras y precios de combustible, y me pregunté por qué no hacer algo así con Python, que es lo primero que estamos viendo en el curso que estoy haciendo. Y de ahí me vino la idea de escribir el código de Gasoliprecio.

Si alguna vez has necesitado encontrar una estación de servicio cerca de tu ubicación, probablemente te habrás llevado una sorpresa al ver el precio del combustible que necesitas. En este contexto, Gasoliprecio es una aplicación desarrollada con Python y Flet que te permite buscar estaciones de servicio en España de forma rápida y sencilla, filtrando por ciudad y tipo de combustible. Y que termina ofreciendo la dirección de la gasolinera, el precio del combustible buscado, y te permite abrir su ubicación en google maps.

¿Qué es Gasoliprecio?

Acerca de gasoliprecio ... búsqueda de estaciones de servicio en España

Gasoliprecio es una aplicación básica y sencilla diseñada para facilitar la búsqueda de estaciones de servicio en España. A través de la interfaz de usuario creada con Flet, los usuarios pueden ingresar el nombre de una ciudad y seleccionar el tipo de combustible que necesitan, como gasolina, gasóleo, GLP, o bioetanol. Luego, la aplicación se conecta a una API pública del gobierno español que proporciona datos actualizados sobre las estaciones de servicio en todo el país.

Funcionalidades de Gasoliprecio

La aplicación es muy sencilla. Básicamente tan solo toma los datos de la API y los presenta al usuario teniendo en cuenta sus preferencias de búsqueda. Por eso en la aplicación solo encontraremos:

  1. Búsqueda personalizada: Los usuarios pueden escribir el nombre de una ciudad y seleccionar el tipo de combustible para encontrar estaciones que se ajusten a sus preferencias.
  2. Precios actualizados: La aplicación se conecta a una API en tiempo real para mostrar los precios más recientes de los combustibles disponibles en cada estación de servicio. Se supone que los precios se actualizan cada media hora.
  3. Filtros avanzados: Puedes buscar estaciones según el tipo de combustible (Gasóleo A, Gasolina 95 E5, Gasóleo Premium, Bioetanol, GLP, etc.), y la aplicación se encargará de filtrar las estaciones que ofrecen el combustible seleccionado.
  4. Integración con Google Maps: ¿No sabes cómo llegar a una estación? Gasoliprecio te permite abrir la estación seleccionada directamente en Google Maps con un solo clic.
  5. Interfaz sencilla y funcional: Usando la biblioteca Flet de Python, la interfaz de Gasoliprecio es moderna, ligera y fácil de usar, adaptándose tanto a temas claros como oscuros para una mejor experiencia visual.

¿Cómo funciona Gasoliprecio?

1. Requisitos previos:

Gasoliprecio está basado en Python, por lo que necesitarás tener Python instalado en tu sistema. Además, el proyecto utiliza las siguientes bibliotecas de Python:

  • Flet: Para crear interfaces gráficas y aplicaciones web interactivas.
  • Requests: Para realizar solicitudes HTTP a la API que proporciona los datos sobre las estaciones de servicio.

2. Instalación y ejecución:

El proceso para ejecutar Gasoliprecio es bastante sencillo. Solo tienes que ejecutar el archivo run_app.py. Desde este archivo se realizarán de forma automática los siguientes pasos:

  1. Se ve a crear un entorno virtual para aislar las dependencias del proyecto y ejecutar en este la aplicación.
  2. Instalar las dependencias necesarias desde el archivo requirements.txt.
  3. Ejecutar el archivo principal, main.py, que lanza la aplicación.

Gasoliprecio se conecta automáticamente a la API del Ministerio de Industria, Comercio y Turismo de España para obtener la información más actualizada sobre los precios de los combustibles en las estaciones de servicio.

3. Interacción con la aplicación:

Una vez que ejecutes la aplicación, puedes empezar a usarla de inmediato:

Gasoliprecio buscando estaciones de servicio en España para ver el precio de la Gasolina 95
  • Introduce el nombre de la ciudad donde deseas buscar las estaciones de servicio.
  • Selecciona el tipo de combustible que estás buscando.
  • Haz clic en «Buscar» y la aplicación te mostrará una lista de las estaciones de servicio disponibles, junto con sus precios, direcciones y ubicación mediante google maps.

4. Características adicionales:

Como esto es una aplicación producto de un momento puntual, no tiene muchas más características. Tan solo tendremos disponibles:

  • Cambio de tema: Puedes cambiar entre modo claro y oscuro para personalizar la interfaz según tus preferencias.
  • Acerca de: Accede a una ventana con información sobre el proyecto y un enlace directo al repositorio de GitHub para contribuir o obtener más detalles.

El código de Gasoliprecio

Este proyecto tiene pocos archivos. Tan solo se divide en tres archivos. El primero de ellos, que será el que necesitaremos ejecutar para levantar la aplicación, será el run_app.py, y el código que tendremos en este será:

Código de run_app.py

import os
import subprocess
import sys

def crear_entorno_virtual():
    print("Creando entorno virtual...")
    subprocess.run([sys.executable, "-m", "venv", "venv"], check=True)

def activar_entorno_virtual():
    if os.name == "nt":  # Windows
        activate_script = os.path.join("venv", "Scripts", "activate.bat")
    else:  # Linux/Unix/Mac
        activate_script = os.path.join("venv", "bin", "activate")
    print(f"Activando entorno virtual: {activate_script}")
    return activate_script

def instalar_dependencias():
    print("Instalando dependencias desde requirements.txt...")
    pip_path = os.path.join("venv", "Scripts", "pip") if os.name == "nt" else os.path.join("venv", "bin", "pip")
    if not os.path.exists("requirements.txt"):
        print("Error: No se encontró el archivo requirements.txt")
        sys.exit(1)
    subprocess.run([pip_path, "install", "-r", "requirements.txt"], check=True)

def ejecutar_main():
    print("Ejecutando main.py...")
    python_path = os.path.join("venv", "Scripts", "python") if os.name == "nt" else os.path.join("venv", "bin", "python")
    subprocess.run([python_path, "main.py"], check=True)

if __name__ == "__main__":
    # Verificar si el entorno virtual ya existe
    if not os.path.exists("venv"):
        crear_entorno_virtual()
    
    # Activar entorno virtual (opcional, pero útil para confirmación visual en entornos manuales)
    activar_entorno_virtual()

    # Instalar dependencias
    instalar_dependencias()
    
    # Ejecutar la aplicación
    ejecutar_main()

Código main.py

El archivo main.py es en el que vamos a colocar toda la lógica e interfaz del programa, con el código:

import flet as ft
import requests
import webbrowser


def obtener_datos(url):
    try:
        response = requests.get(url, timeout=10)
        response.raise_for_status()
        return response.json()
    except requests.RequestException:
        return None


def filtrar_estaciones(estaciones, ciudad, tipo_combustible):
    ciudad = ciudad.lower()
    estaciones_filtradas = [
        estacion for estacion in estaciones
        if ciudad in estacion.get("Municipio", "").lower()
    ]
    if tipo_combustible:
        estaciones_filtradas = [
            estacion for estacion in estaciones_filtradas
            if estacion.get(tipo_combustible) not in (None, "N/A", "")
        ]
    return estaciones_filtradas


def main(page: ft.Page):
    page.title = "Gasoliprecio: Búsqueda de Estaciones de Servicio"
    page.theme_mode = ft.ThemeMode.LIGHT
    page.padding = 20

    # URLs
    url_api = "https://sedeaplicaciones.minetur.gob.es/ServiciosRESTCarburantes/PreciosCarburantes/EstacionesTerrestres/"
    url_github = "https://github.com/sapoclay/gasoliprecio"

    # Controles principales
    ciudad_input = ft.TextField(label="Introduce la ciudad", expand=True)
    tipo_combustible_dropdown = ft.Dropdown(
        label="Seleccione el tipo de combustible",
        options=[
            ft.dropdown.Option("Precio Gasoleo A"),
            ft.dropdown.Option("Precio Gasolina 95 E5"),
            ft.dropdown.Option("Precio Gasoleo Premium"),
            ft.dropdown.Option("Precio Bioetanol"),
            ft.dropdown.Option("Precio GLP"),
        ],
        expand=True,
    )
    resultados_listview = ft.ListView(expand=True, spacing=10, padding=10)

    def mostrar_snackbar(mensaje):
        snackbar = ft.SnackBar(content=ft.Text(mensaje))
        page.overlay.append(snackbar)
        snackbar.open = True
        page.update()

    def abrir_google_maps(nombre, direccion):
        if direccion and nombre:
            consulta = f"{nombre}, {direccion}".replace(" ", "+")
            url = f"https://www.google.com/maps/search/?api=1&query={consulta}"
            webbrowser.open(url)
        else:
            mostrar_snackbar("No se puede abrir Google Maps para esta estación.")

    def buscar_estaciones(e):
        ciudad = ciudad_input.value.strip()
        tipo_combustible = tipo_combustible_dropdown.value

        if not ciudad:
            mostrar_snackbar("Por favor, introduzca una ciudad.")
            return

        resultados_listview.controls.clear()
        resultados_listview.controls.append(
            ft.Container(ft.Text("Cargando...", size=20, color="blue"), alignment=ft.alignment.center, expand=True)
        )
        page.update()

        datos = obtener_datos(url_api)
        if not datos:
            mostrar_snackbar("Error al obtener datos de la API.")
            resultados_listview.controls.clear()
            page.update()
            return

        estaciones = datos.get("ListaEESSPrecio", [])
        estaciones_filtradas = filtrar_estaciones(estaciones, ciudad, tipo_combustible)

        if not estaciones_filtradas:
            mostrar_snackbar(f"No se encontraron estaciones en {ciudad}.")
            resultados_listview.controls.clear()
            page.update()
            return

        resultados_listview.controls.clear()
        for estacion in estaciones_filtradas:
            nombre = estacion.get("Rótulo", "N/A")
            direccion = estacion.get("Dirección", "N/A")
            precio = estacion.get(tipo_combustible, "N/A") if tipo_combustible else "No disponible"
            resultados_listview.controls.append(
                ft.Row(
                    [
                        ft.Container(
                            ft.Column(
                                [
                                    ft.Text(f"Nombre: {nombre}", weight=ft.FontWeight.BOLD),
                                    ft.Text(f"Dirección: {direccion}"),
                                    ft.Text(f"Precio: {precio} €/L"),
                                ],
                                spacing=5,
                            ),
                            padding=10,
                            border=ft.border.all(1),
                            border_radius=5,
                            margin=5,
                            expand=True,
                        ),
                        ft.IconButton(
                            icon=ft.Icons.MAP,
                            tooltip="Ver en Google Maps",
                            on_click=lambda e, n=nombre, d=direccion: abrir_google_maps(n, d),
                        ),
                    ],
                    spacing=10,
                )
            )
        mostrar_snackbar(f"Se encontraron {len(estaciones_filtradas)} estaciones en {ciudad}.")
        page.update()

    def abrir_github(e):
        webbrowser.open(url_github)

    def cambiar_tema(e):
        page.theme_mode = ft.ThemeMode.DARK if page.theme_mode == ft.ThemeMode.LIGHT else ft.ThemeMode.LIGHT
        page.update()

    def mostrar_acerca_de(e):
        """Muestra una ventana con información sobre la aplicación."""
        # Crear una instancia del diálogo
        acerca_de_dialog = ft.AlertDialog(
            modal=True,
            title=ft.Text("Acerca de gasoliprecio"),
            content=ft.Container(
                content=ft.Column(
                    [
                        ft.Image(src="assets/img/logo.jpeg", width=150, height=150),
                        ft.Text(
                            "Esta aplicación permite buscar estaciones de servicio en España, "
                            "filtrando por ciudad y tipo de combustible. Desarrollado con Flet y Python."
                            "\nLa actualización de precios se realiza cada media hora, con los precios en vigor en ese momento.",
                            text_align=ft.TextAlign.CENTER,
                        ),
                        ft.ElevatedButton(
                            "Abrir repositorio en GitHub",
                            icon=ft.Icons.CODE,
                            on_click=abrir_github,
                        ),
                        ft.ElevatedButton(
                            "Cambiar tema",
                            icon=ft.Icons.LIGHT_MODE,
                            on_click=cambiar_tema,
                        ),
                    ],
                    spacing=20,
                    alignment=ft.MainAxisAlignment.CENTER,
                    horizontal_alignment=ft.CrossAxisAlignment.CENTER,
                ),
                padding=20,
                alignment=ft.alignment.center,
                width=400,  # Ancho de la ventana
                height=400,  # Alto de la ventana
            ),
            actions=[
                ft.TextButton(
                    "Cerrar",
                    on_click=lambda e: close_dialog(acerca_de_dialog),  # Cerrar el diálogo correctamente
                ),
            ],
            actions_alignment=ft.MainAxisAlignment.END,
        )

        # Agregar el diálogo al overlay de la página
        page.overlay.append(acerca_de_dialog)
        acerca_de_dialog.open = True
        page.update()

    def close_dialog(dialog):
        """Cierra el diálogo correctamente."""
        dialog.open = False  # Establecer open a False para cerrarlo
        page.update()  # Actualizar la página para reflejar el cambio



    opciones_button = ft.ElevatedButton(text="Opciones", icon=ft.Icons.MENU, on_click=mostrar_acerca_de)

    page.add(
        ft.Column(
            [
                opciones_button,
                ft.Row([ciudad_input, tipo_combustible_dropdown], alignment=ft.MainAxisAlignment.SPACE_BETWEEN),
                ft.ElevatedButton("Buscar", icon=ft.Icons.SEARCH, on_click=buscar_estaciones),
                resultados_listview,
            ],
            expand=True,
        )
    )


ft.app(target=main)

Código requirements.txt

Y también necesitaremos el archivo requirements.txt, en el que añadiremos todo lo que necesitamos para poder crear la aplicación Gasoliprecio:

flet
requests

Además de estos archivo será necesario tener la carpeta assets y dentro de ella otra carpeta llamada img, que debe contener un archivo de imagen llamado logo.jpeg.

Conclusión

Si eres un conductor habitual, saber dónde encontrar la gasolina o el gasóleo más barato puede significar un ahorro considerable. Con Gasoliprecio, tienes la ventaja de conocer los precios actualizados al instante y las estaciones más cercanas, todo desde una plataforma sencilla y sin complicaciones.

Gasoliprecio es la herramienta que puede resultar útil a cualquier conductor en España que quiera ahorrar tiempo y dinero al encontrar estaciones de servicio con los precios más bajos para el combustible. Ya sea que estés buscando una estación cerca de tu ciudad o necesites conocer los precios de diferentes tipos de combustible, Gasoliprecio te ofrece la información que necesitas de manera rápida y precisa.

Esto no es nada nuevo, pero es una busca forma de practicar la programación con Python y Flet y el tratamiento de datos y presentación obtenidos desde una API.

Si te interesa, puedes encontrar el código fuente completo en en repositorio de GitHub en el que he alojado el proyecto

También te puede interesar ...

Deja un comentario

* Al utilizar este formulario, aceptas que este sitio web almacene y maneje tus datos.

Resumen de privacidad
cookies entreunosyceros

Esta web utiliza cookies para que podamos ofrecerte la mejor experiencia de usuario posible.

La información de las cookies se almacena en tu navegador y realiza funciones tales como reconocerte cuando vuelves a nuestra web o ayudarnos a comprender qué secciones de la web encuentras más interesantes y útiles.

Nunca almacenamos información personal de ningún tipo.

Tienes toda la información sobre privacidad, derechos legales y cookies en nuestra página sobre la política de privacidad o en la página sobre nuestra política de cookies.

Cookies necesarias

Las cookies estrictamente necesarias tiene que activarse siempre para que podamos guardar tus preferencias de ajustes de cookies.

Si desactivas esta cookie no podremos guardar tus preferencias. Esto significa que cada vez que visites esta web tendrás que activar o desactivar las cookies de nuevo.

Cookies de terceros

Esta web utiliza las siguientes cookies adicionales:

- Mailchimp: Recordar si ya estás suscrito al boletín de noticias y sino ofrecértelo al salir.

- Accesibilidad: Para saber tus ajustes de accesibilidad en cada visita.

- Comentarios: Saber si has leído y aceptado nuestra política de privacidad a la hora de dejar un comentario en la web.

- Google Analytics: Localización para recopilar información anónima tal como el número de visitantes del sitio, o las páginas más populares.

- Goggle Adsense: Anuncios personalizados según tu geolocalización y preferencias.

Dejar estas cookies activadas nos permite mejorar nuestra web.

Adblock Detectado!!

Ayúdanos deshabilitando la extensión AdBlocker de tu navegador para visitar esta web.
Si no sabes hacerlo en Chrome, consulta el siguiente enlace. Si utilizas Firefox, puedes consultar este otro enlace.
Esto mejorará tu experiencia en este sitio web.