Skip to content

renanbirck/gasolina

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

200 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gasolina: raspagem e processamento dos preços dos combustíveis disponibilizados pelo PROCON de Joinville/SC

Introdução

O PROCON de Joinville/SC, disponibiliza, por meio do seu site, o preço dos combustíveis em todos os postos de gasolina do município.

Assim, o objetivo deste projeto é coletar esses dados e alimentar um banco de dados, a partir do qual é gerado um dashboard e tabelas nas quais é possível fazer a filtragem por bairro.

O back-end do projeto é estruturado em:

  • scraper: faz a raspagem do site do PROCON e determina o arquivo PDF a ser baixado.
  • parser: processa o arquivo PDF, carregando os valores dele no banco de dados.
  • api: uma API utilizando o fastapi, com um front-end simples.

O front-end é implemetado no diretório templates dentro de api, usando Bootstrap, bootstrap-table e chart.js.

Requisitos

  • Para o scraper:
    • Python 3.11 ou mais recente;
    • requests;
    • BeautifulSoup.
  • Para o parser:
  • Para a API:
    • FastAPI
  • Para o front-end:
    • não há nenhuma dependência em específico
  • TODO: ver o uso de um ORM, substituindo o uso de SQL puro.

Execução

  • Para rodar o scraper dentro de um container:

    • Construir o container - usei o podman, mas é igual para o Docker - a partir da raiz: podman build -t docker-scraper -f scraper/Dockerfile .
    • Como o scraper escreve para um diretório, é preciso executar o container indicando onde gravar os dados. podman run -d -v [local onde gravar os dados]:/app/data docker-scraper:latest É ideal que o local seja um caminho absoluto, para evitar ambiguidades.
  • Para rodar o parser:

    • No diretório parser, rodar o script run_parser.sh, fornecendo um arquivo adequado como parâmetro.
  • Para rodar a api durante o desenvolvimento:

    • No diretório api, rodar fastapi dev main.py para o modo de desenvolvedor.
  • Para rodar em ambiente de desenvolvimento, com um BD separado:

    • Setar a variável de ambiente DB_PATH para o nome do BD a ser utilizado. Se essa variável não estiver setada, presume-se que estamos usando o BD completo.

Deploy

Primeiramente, é preciso construir o container: podman build -t gasolina-api -f api/Dockerfile ..

Para facilitar o deploy, adicionei a máquina remota no podman system connection add REMOTE [ENDEREÇO DA MÁQUINA]:22/usr/lib/systemd/user/podman.socket e, então, basta executar o comando podman image scp gasolina-api:latest REMOTE::. É preciso que o acesso via ssh a essa máquina remota esteja sendo feito por chave e não por senha.

Em seguida, na máquina remota, é preciso executar o comando podman run -dt -v [LOCAL ONDE FICA O BD]:/data:Z --name gasolina-api -p 8000:8000 --replace gasolina-api para subir o servidor. O local onde fica o BD deve ser configurado conforme o servidor.

No servidor já deverá existir um proxy reverso, como o Apache ou o nginx, operacional. Ele irá receber as requisições na porta 80 e encaminhar para a porta 8000.

Um mínimo exemplo de configuração do nginx é:

server {

        server_name [URL DA APLICAÇÃO];

        listen 80;
        listen [::]:80;

        location / {
                proxy_pass http://localhost:8000;
                include uwsgi_params;
        }

}

sendo preciso, também, gerar um certificado (se estivermos usando o Let's Encrypt, por exemplo) e configurar o nginx corretamente. Não vou entrar em detalhes aqui, porque cada configuração do nginx será diferente.

Para gerenciar a execução do container, temos duas opções:

  • A forma "manual", usando o podman run, como visto acima. Normalmente é usável em desenvolvimento.

  • Escrever um arquivo .container, para uso com quadlet, o equivalente ao Docker Compose no podman. Isso pode ser obtido criando-se um arquivo gasolina.container no diretório home do usuário sob o qual a aplicação irá executar, cujo conteúdo poderá ser, minimamente:

    [Container]
    Image=localhost/gasolina-api:latest
    AutoUpdate=registry
    PublishPort=8000:8000
    Network=host
    Volume=/home/renan/gasolina/data:/data:Z
    
    [Service]
    Restart=always
    
    [Install]
    WantedBy=default.target
    

Novamente, as configurações irão variar conforme o caso de uso. Feito o deploy, é preciso reiniciar o container (no caso de usarmos quadlet, basta reiniciar o serviço).

Coisas a fazer:

(em nenhuma ordem)

Scraper e parser:

  • Automatizar o scraping.
  • Fazer a raspagem comunicar via API em vez de chamadas SQL diretamente no BD. Já funciona, mas ainda falta simplificar o código e fazer em batch em vez de uma entrada por vez.
  • Elaborar uma forma de, do zero, criar uma carga inicial de dados (talvez usando os PDFs de 2023 a 2025) e construir o BD sem precisar fornecer um binário no repositório. Parcialmente resolvido, com "dump" do BD.

API:

  • Atualmente, a imagem está muito grande. Ver se eu consigo reduzir o tamanho dela. Resolvido usando Alpine, e não Debian.
  • Integrar os testes com o container.
  • Configurar Actions para rodar os testes e fazer o deploy automaticamente.
  • Adicionar autenticação e logging.
  • Fazer com que seja possível usar outro BD (ex. PostgreSQL) no back-end.
  • Documentar os endpoints da API.

Front-end:

  • Integração com o Google Maps ou OpenStreetMap.
  • Usar TypeScript e algum framework, como React ou vue, no front-end; ou explorar outras bibliotecas para geração de tabelas.
  • Mais análises (preço médio, máximo, mínimo, etc...).

Problemas encontrados

  • A tabela fornecida pela prefeitura é inconsistente, com postos repetidos ou que mudaram de nome. Isso irá influenciar na estrutura do BD.

Licença

Licenciado sob a licença MIT; ver o arquivo LICENSE para mais detalhes.

About

Raspagem/coleta dos preços de combustíveis em Joinville/SC

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors