정적 사이트 Estaciones de Servicio

El Ministerio de Industria y Consumo publica de forma diaria 유엔 데이터 집합 con los precios de todas las Gasolinerade España. En este post voy a explicar cómo, de forma auto noma, se ejecuta un scriptque lo descargay crea un sitepara poder navegar enter las m ás de 14.000estaciones y consultar los precios del a.
El resultado final lo puedes ver Aquií:https://estaciones-de-servicio.netlify.app/main/final/index.html
메모
Tal vez te pueda Interestar el postestaciones-servicio-bot.htmldonde detallo cómo hacer un bot de Telegram
para consumir dichos datos.

데이터 열기


El site se basa en un concentto de datos abiertos del Ministerio de Industria y Consumo donde se muestran los preciosde las estaciones de servicio de España:https://sedeaplicaciones.minetur.gob.es/ServiciosRESTCarburantes/PreciosCarburantes/EstacionesTerrestres/
Eneste xml(o json)se listan todas las estaciones con su nombre,dirección,marca,geoposición as ícomo losdiferentes precios para gasolina 95,98,los diferentes tipos de diesel,bios 등.
Estos precios se Realizan al menos una vez al día(realmente no recurdo donde leícuando se realiza,ni la periodiciad)
<PreciosEESSTerrestres xmlns="http://schemas.datacontract.org/2004/07/ServiciosCarburantes" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Fecha>06/08/2020 21:31:14</Fecha>
<ListaEESSPrecio>
    <EESSPrecio>
        <C.P.>02250</C.P.>
        <Dirección>AVENIDA CASTILLA LA MANCHA, 26</Dirección>
        <Horario>L-D: 07:00-22:00</Horario>
        <Latitud>39,211417</Latitud>
        <Localidad>ABENGIBRE</Localidad>
        <Longitud_x0020 __x0028_WGS84_x0029_>-1,539167</Longitud_x0020__ x0028_WGS84_x0029_>
        <Margen>D</Margen>
        <Municipio>Abengibre</Municipio>
        <Precio_x0020_Biodiesel/>
        <Precio_x0020_Bioetanol/>
        <Precio_x0020_Gas_x0020_Natural_x0020_Comprimido/>
        <Precio_x0020_Gas_x0020_Natural_x0020_Licuado/>
        <Precio_x0020_Gases_x0020_licuados_x0020_del_x0020_petróleo/>
        <Precio_x0020_Gasoleo_x0020_A>1,039</Precio_x0020_Gasoleo_x0020_A>
        <Precio_x0020_Gasoleo_x0020_B>0,569</Precio_x0020_Gasoleo_x0020_B>
        <Precio_x0020_Gasoleo_x0020_Premium/>
        <Precio_x0020_Gasolina_x0020_95_x0020_E10/>
        <Precio_x0020_Gasolina_x0020_95_x0020_E5>1,149</Precio_x0020_Gasolina_x0020_95_x0020_E5>
        <Precio_x0020_Gasolina_x0020_95_x0020_E5_x0020_Premium i:nil="true"/>
        <Precio_x0020_Gasolina_x0020_98_x0020_E10/>
        <Precio_x0020_Gasolina_x0020_98_x0020_E5/>
        <Precio_x0020_Hidrogeno/>
        <Provincia>ALBACETE</Provincia>
        <Remisión>dm</Remisión>
        <Rótulo>Nº 10.935</Rótulo>
        <Tipo_x0020_Venta>P</Tipo_x0020_Venta>
        <_x0025 __x0020_BioEtanol>0,0</_x0025__ x0020_BioEtanol>
        <_x0025 __x0020_Éster_x0020_metílico>0,0</_x0025__ x0020_Éster_x0020_metílico>
        <IDEESS>4375</IDEESS>
        <IDMunicipio>52</IDMunicipio>
        <IDProvincia>02</IDProvincia>
        <IDCCAA>07</IDCCAA>
    </EESSPrecio>

    <!-- más estaciones-->
</ListaEESSPrecio>
다른 로봇이 este caso lo que nos interesta es organizator todas las estaciones por provincias y municipiosy para cada una de ellas mostrar la dirección, un enlace A suubicación y los differentes precios que tiene(todastinenen dos los tipos de carbonte 없음)에 있습니다.
El objetivo va a ser generar un site de“puro HTML”de tal forma que pueda ser publicado en alguno de los numeriosesservicios que of recn de forma retera su publicación,en nuestro caso Gitlab/Netlify(Github es otra opción pero nolo uso)

도구


Para tener listo el site vamos a utilizar las siguientes herramientas.De todas ellas la que puede varíar en tu casoes la que te ayude a generar los ficheros partiendo De los datos,en mi caso un script De groovy.

Groovy 스크립트


Gracias a que con Groovy es muy fácil descargar e interpretar un XML(o un JSON)asícomo trabajar con ficheros de texto,lo usaremos para particional y generar los ficheros

Antora/Asciidoctor 회사


El script va a generar ficherosadoc(asciidoctor)que no es más que ficheros planos con un lenguaje de marcado queseráinterpretado por Antora para generar la version HTML correspondente
Baśicamente serán ficheros muy sencillos con un t ítulo para el nombre de la provincia,subtitulo para los municipios,apartados para las gasolineras,enlaces 등.
Esta es la pieza basical para que function el sistema y la que nos va a marcar quéestrustructure de ficheros tenemosque generar asícomo una serie de configuración

Gitlab 회사


El proyecto va a estar alojado en mi cuenta returna de Gitlab como repositorio git.Una de las características de Gitlabes que te permite ejecutar código en sus sistemas include unda forma recurrente mediante jobs programmados lo cual nosva a servir para tener actualizado el site todos los días.

Netlify 회사


Gitlab nos permite publicar el contenido estático generado en el paso front pero para este post vamos a integrarel repositorio con otra herramienta con capa returna que permite de igual forma publicar contenido estático más algunaotra functionalidad,que es Netlify(este paso te lo puedes saltar y utilizar Gitlab.Laúnica diferencea es que Netlifya mi parecer tiene mejor velocidad de descarga)

준비


En primer lugar es IMPORTANT entender la ESTRUCTURALA de directorios que require Antora asícomo alguno de los ficherosnecesarios.
Antora espera una estrustructure a similar a la que se muestra en la imagen:

En primer lugar crearemos esta estructura de directorios y los ficheros excepto los que van En el directoriopagesque serán creados por el script.Por ello este directorio se encuentra excluido en el.gitignore pues no hace faltaversionarlos al cambiar cada vez que ejecutemos el script).Por la misma razónnav.adoctampoco se versiona pues elscript se encargaráde crear la navegación.
name: maintitle: Estaciones de Servicioversion: finalnav: - modules/ROOT/nav.adoc
Este fichero le indica a Antora quémodulos queremos cargar,en nuestro casoúnicamente el ROOT
site: title: Estaciones de Servicio url: https://estaciones-de-servicio.netlify.com start\_page: main::index.adoc keys: google\_analytics: 'UA-XXXXX-XX'content: sources: - url: ./ branches: HEAD start\_path: docsui: bundle: url: ui/ui.zip supplemental\_files: antora-lunr/supplemental\_uioutput: clean: true dir: ./build destinations: - provider: archiveasciidoc: extensions: - ./lib/tabs-block/extension.js
Este fichero es lo que en Antora se conoce como un 극본 y sirve para indicalle de donde obtener los repositorios(Antora puede unir m últiples repositorios para generar un único site), la presentaci ón a usar(ui.zip), extensiones 등
En nuestro caso le estamos indicatando que entre otras características utility el directoriodocscomo origen para ladocumentación junto con una serie de extras que nos van a ayudar a que nuestro site sea más functional como unaextensión para mostrar multiples tabs,un buscador incluido(lunr)

시나리오


Para generar las páginas que va a usar Antora como fuente,el script simplemente va a:

  • XML y parsearlo를 설명합니다.Con groovy esto se puede hacer Con una simple lineanew XmlParser().parseText(new InputStreamReader(url.toURL().openStream(), 'UTF-8').text).ListaEESSPrecio

  • 기록cadaestación, extraer la información de interés de cada una e ir a ñadiendolas a un "mapa de mapas"porprovincia, municipios y localidades tal formaque al terminar tenemos en memoria todas las estaciones agrupadas[Albacete : [Abengibre: [ [ Estacion1:[ precio95:1.23, precio98:1.33] ] ] ] ]

  • utilizando este mapa,el script Generas el fichero de navegación:
    nav = new File('docs/modules/ROOT/nav.adoc')
    nav.text = ""
    map.each{ kvp ->
        provincia = kvp.value
        nav << "* xref:${kvp.key}.adoc[$provincia.name]\n"
        provincia.municipios.each{ kvm ->
            municipio = kvm.value
            nav << "** xref:${kvp.key}.adoc#${municipio.name.toLowerCase().replaceAll(' ','_')}[$municipio.name]\n"
        }
    }
    
    메모
    Añadir líneas A un fichero de texto en groovy es tan fácil comofile << "una cadena"Básicamente indicamos que tendremos un fichero por cada provincia(01.adoc,02.adoc…​) y que dentro deél tendromessecciones con el nombre de cada municipio.Para facilitar la navegación usaremos el nombre del municipio en minúsculasy cambiaremos los espacios en blanco por guiones bajos
    Lo que nos generas un fichero parecido a:
    내비게이션adoc 회사
    \* xref:02.adoc[ALBACETE]\*\* xref:02.adoc#abengibre[Abengibre]\*\* xref:02.adoc#albacete[Albacete] ...\*\* xref:50.adoc#villarroya\_de\_la\_sierra[Villarroya de la Sierra]\*\* xref:50.adoc#zaragoza[Zaragoza]\*\* xref:50.adoc#zuera[Zuera]
    

  • después el script vuelve a recorrer el mapa para ir generando los ficheros de cada provincia:
    map.each{ kvp ->
        provincia = kvp.value
        file = new File("docs/modules/ROOT/pages/${kvp.key}.adoc") (1)
        file.parentFile.mkdirs()
        file.text ="= $provincia.name\n:tabs:\n\n" (2)
    
        ...
    }
    
    |1 | Creamos un fichero por provincia|
    |2 | Lo inicializamos con una cabecera asciidoctor con su titulo y el atributo: 태그: |
    Para cada provincia Recrremos sus municipios y localidades
    map.each{ kvp ->
        ...
        provincia.municipios.each{ kvm ->
            municipio = kvm.value
            file << "[#${municipio.name.toLowerCase().replaceAll(' ','_')}]\n"
            file << "== $municipio.name \n\n"
            municipio.localidades.each{ kvl ->
                kvl.value.sort{it.direccion}.each{ estacion ->
                    file << "=== $estacion.direccion \n\n"
                    file << "*$estacion.rotulo* $estacion.horario \n\n"
                    file << "https://www.openstreetmap.org/?mlat=$estacion.latitud&mlon=$estacion.longitud#map=17/$estacion.latitud/$estacion.longitud[Ver en mapa,window=_blank]\n\n"
                    file << "[TIP]\n====\n"
                    estacion.precios.findAll{ it.value }.each{
                        file << "* _${it.key}_ a *${it.value}* €\n"
                    }
                    file << "====\n\n"
                }
            }
        }
        ...
    }
    
    Como se puede adivinar,Simplement vamos concatenando al fichero de la provincia texto en formato Asciido hastaque llegamos a una estación donde volcamos sus datos.
    Para cada provincia se generas un fichero 유사:
    = ARABA/ÁLAVA
    :tabs:
    
    [#alegría-dulantzi]
    == Alegría-Dulantzi
    
    === CALLE GASTEIZBIDEA 59
    
    *ES DULANTZI REPSOL* L-D: 07:00-22:00
    
    https://www.openstreetmap.org/?mlat=42.842917&mlon=-2.519194#map=17/42.842917/-2.519194[Ver en mapa,window=_blank]
    
    [TIP]
    ====
    * _95 E5_ a *1.239* €
    * _Gasoleo A_ a *1.139* €
    ====
    
    (más estaciones)
    
    경고
    El script 실제 속algo más de có digo por cada provincia como una serie de tabs con las estaciones
    más baratas al-inicio del fichero.이 글은 voy a explicarlo pero si te INTEREA es muy fácil de seguir가 없습니다.

  • porúltimo el script copia un ficheroindex.adocque se encuentra en el raiz del proyecto al raiz del pages del
    모돌로.De esta forma puedo cambiar la página principal sin liar más el script.
  • las p á ginas Simplement ejecuto 씨:groovy dump.groovy메모
    Este script seráejecutado por el pipeline de Gitlab por lo que al final no necesitarías ni tener Groovy instalado
    현지에서aunque sería bueno tenerlo para probarlo primero antes de pasara publicarlo.

    유니버설 엘 사이트


    Una vez ejecutado el script y las páginas generadas podemos proceder a ejecutar Antora para que nos genre el site.Puedes instalarlo y ejecutarlo desde una consola o utilizar un docker compose como el siguiente para evitarlo:
    docker 작성.yml 회사
    version: "2.1"
    services:
      antora:
        image: "antora/antora"
        volumes:
          - .:/antora
    
    y ejecutarlo mediantedocker-compose run antora estaciones.ymlEste docker usaría la imagen Official de antora,básica pero suficiente para generar un site en el directoriobuildque podrías revisar con un navegador.
    Sin금수esta imagen no incluye ciertas extensiones que me interest an como el buscador javascript por lo quehabr í a que instalarlo y configurarlo, as íque yo me he creado mi propia imagen donde ya se encuentra instalado y estes el docker compose que utilizo:
    version: "2.1"
    services:
      antora:
        image: "jagedn/antora-with-extensions"
        environment:
          - DOCSEARCH_ENABLED=true
          - DOCSEARCH_ENGINE=lunr
          - NODE_PATH="$$(yarn global dir)/node_modules"
        volumes:
          - .:/antora
    

    Ejeucción diaria 회사


    Como he comentado,una de las características de Gitlab es que puedes program ar la ejeucción de pipeline,no sólocando realizas cambios en el código y los subes al repositorio sino de forma programmada.
    Nuestro 파이프 consistir á en 3 pasos 연속:
    gitlab ci.yml 회사
    stages:
      - build
      - staging
      - deploy
    
    groovy:
      stage: build
      image:
        name: groovy:2.5.9
      script:
        - groovy dump.groovy
      artifacts:
        paths:
          - docs
    
    antora:
      stage: staging
      image:
        name: jagedn/antora-with-extensions
        entrypoint: [/bin/sh, -c]
      variables:
        ASCIIDOC_COPY_TO_CLIPBOARD: "true"
        DOCSEARCH_ENABLED: "true"
        DOCSEARCH_ENGINE: "lunr"
        NODE_PATH: "$$(yarn global dir)/node_modules"
      dependencies:
        - groovy
      script:
        - antora --generator antora-site-generator-lunr estaciones.yml
      artifacts:
        paths:
          - build
    
    pages:
      stage: deploy
      dependencies:
        - antora
      script:
        - mkdir -p public
        - cp -R build/* public/
      artifacts:
        paths:
          - public
    
    Si todo va bien,Gitlab nos of ceráuna url donde publicaráel site generado por antora.En este caso Enhttps://jorge-aguilera.gitlab.io/estaciones-de-servicio

    Netlify 회사


    Netlify es otro servicio de hosting con características muy interestantes que integra fácilmente con Gitlab(y otros)de tal forma que podemos delegar en este segundo la ejeucción de nuestro pipeline mientras que utilizamos a Netlifycomo plataforma donde desplegarlo.
    단락 ello 단순화:
  • crearemos un proyecto en Netlify
  • obtendremos su NETLIFY\u SITE\u ID
  • desde la página del perfil crearemos un NETLIFY\u AUTH\u TOKEN
  • crearemos en Gitlab dos variables de entorno nuevas en la seccion CD/CI con estos valores
  • sustituiremos elúltimo paso del fichero.gitlab ci.yml por este otro(o si quieres publicar en los dos sitios lopuedes mantener,simplement estarás publicando en los dos url a la vez)
  • netlify:
      stage: deploy
      image: node:10.15.3
      script:
        - npm i -g netlify-cli
        - netlify deploy --site $NETLIFY_SITE_ID --auth $NETLIFY_AUTH_TOKEN --prod
      dependencies:
        - antora
      only:
        - master
    

    좋은 웹페이지 즐겨찾기