Web Scraping, Mapas e Petiscos: Construindo um Roteirizador Dinâmico para o Comida di Buteco com R…
Quem acompanha o circuito gastronômico sabe que o Comida di Buteco é um dos eventos mais aguardados do ano. Em 2026, a edição de Ribeirão…
Web Scraping, Mapas e Petiscos: Construindo um Roteirizador Dinâmico para o Comida di Buteco com R e Shiny

Imagem exemplo do dashboard para roteirização do Comida di Buteco 2026
Quem acompanha o circuito gastronômico sabe que o **Comida di Buteco** é um dos eventos mais aguardados do ano. Em 2026, a edição de Ribeirão Preto contou com dezenas de bares participantes — e, como de costume, despertou aquela vontade de conhecer o máximo possível.
Com isso, um problema clássico ressurgiu: como visitar o maior número de bares sem perder tempo cruzando a cidade à toa?
Ao tentar montar um roteiro, esbarrei em um problema comum: a lista oficial estava presa em um formato pouco estruturado (texto paginado), e os mapas disponíveis não eram práticos para exploração. Não bastava saber o nome do bar ou o petisco, mas também seria relevante transformar o conteúdo em inteligência geográfica.
Foi aí que decidi aplicar conceitos de Data Science para resolver o problema.
O objetivo era claro: extrair os dados, geolocalizá-los e construir uma aplicação interativa onde o usuário pudesse clicar em qualquer ponto do mapa e receber um roteiro ordenado por proximidade. Tudo isso usando o meu amado R.
Assim, neste artigo, mostro alguns caminhos e decisões técnicas tomadas por trás desse projeto para construção da resposta ao problema principal.
1. O Desafio dos Dados: Web Scraping com rvest
O primeiro passo foi construir um pipeline de extração (ETL). A lista oficial dos participantes estava publicada no portal ACidade ON. Utilizei o pacote rvest para varrer o DOM da página e extrair os blocos de texto usando XPath.
Como os dados estavam em formato bruto (texto corrido), apliquei expressões regulares (stringr) para separar inteligentemente o Nome do bar, o Endereço e a descrição do Petisco.
# construindo a lógica de extração da identidade do bar
endereco <- str_match(texto_bruto, paste0(nome, "\\s*(.*?)\\s*Petisco:"))[,2]
endereco <- str_remove(endereco, "(?i)Endereço:\\s*") |> str_remove("^[[:punct:]\\s]+")
petisco <- str_split(texto_bruto, "Petisco:")[[1]][2] |> str_trim()
2. Dando Coordenadas aos Bares: Geolocalização
Com os endereços organizados em um dataframe, o próximo passo foi convertê-los em coordenadas geográficas (latitude e longitude). Para isso, utilizei o pacote tidygeocoder, que permite consumir APIs de geocodificação. Neste caso, a do ArcGIS.
Um cuidado importante aqui foi evitar chamadas desnecessárias à API. Para isso, implementei um sistema simples de cache:
- Os dados geocodificados são salvos em um arquivo
.rds - Se o arquivo já existir e for do dia atual, ele é reutilizado
- Caso contrário, o processo de scraping + geocodificação roda novamente
Esse detalhe melhora bastante a performance e evita problemas com limite de requisições.
3. Espacialidade: Calculando Distâncias
A principal funcionalidade do dashboard é o de apoiar na “roteirização”. Quando o usuário clica em um ponto no mapa ou digita um endereço, o app captura essa coordenada e calcula a distância exata em linha reta para todos os bares filtrados. Aqui, é importante pontuar que trabalhei uma versão mais detalhada para calculo com maior precisão de espacialidade, direcionamento e outros itens relevantes na navegação na cidade, porém, o projeto não performou tanto. Por isso, decidi retomar para o formato original.
Para garantir precisão esférica, utilizei a Fórmula de Haversine através do pacote geosphere.
# calculando as distâncias entre pontos usando o método Haversine
dists <- distHaversine(
matrix(c(coords_usuario$lon, coords_usuario$lat), ncol = 2),
matrix(c(df_bares$long, df_bares$lat), ncol = 2)
)
4. Transformando em produto: frontend com Shiny
Aplicações Shiny tendem a ter um visual padrão que rapidamente denuncia a ferramenta utilizada. Para entregar uma experiência de “app”, reconstruí a interface utilizando a função fillPage() combinada com o uso de um pouco de CSS.
- Responsividade: Substituí os layouts rígidos por uma arquitetura CSS baseada em Flexbox e Media Queries dentro do
fluidPage. O mapa e os filtros agora se adaptam nativamente calculando o espaço restante da tela, garantindo uma experiência fluida de aplicativo real, seja no desktop ou na tela de um celular. - Facilitação do UX: Implementei painéis flutuantes (com
position: absolute) e substituí os popups estáticos do Leaflet por labels em HTML puro, permitindo que o usuário visualize o nome, o endereço e o petisco do bar instantaneamente apenas ao passar o mouse (hover).

Exemplo de utilização dos rótulos de dados aplicados para facilitar o consumo do mapa
Considerações Finais
No fim, o projeto nasceu de uma necessidade simples: decidir onde comer, mas acabou se tornando um exercício completo de transformação de dados: da extração de informação não estruturada até a construção de uma aplicação interativa.
É exatamente esse tipo de aplicação prática que evidencia o valor das ciências dos dados: não apenas analisar dados, mas transformá-los em algo útil no mundo real.
Se você estiver na região de Ribeirão Preto, vale testar o app na prática e montar seu próprio roteiro.
🔗 Dashboard: https://ojeancarlo.shinyapps.io/LocalizaDiButecoRP/ 💻 Código: https://github.com/ojeancarlo/appDiButeco/
Gostou do projeto? Vamos nos conectar! Sinta-se à vontade para me adicionar no LinkedIn para trocarmos ideias sobre Data Science, Analytics e soluções orientadas a dados.
메타데이터
- post_id
- 26c6b4754232
- slug
- web-scraping-mapas-e-petiscos-construindo-um-roteirizador-dinâmico-para-o-comida-di-buteco-com-r-26c6b4754232
- url
- https://medium.com/@ojeancarlo/web-scraping-mapas-e-petiscos-construindo-um-roteirizador-din%C3%A2mico-para-o-comida-di-buteco-com-r-26c6b4754232
- canonical_url
- https://medium.com/@ojeancarlo/web-scraping-mapas-e-petiscos-construindo-um-roteirizador-din%C3%A2mico-para-o-comida-di-buteco-com-r-26c6b4754232
- author_url
- https://medium.com/@ojeancarlo
- status
- ok
- fetched_at
- 2026-07-10 21:34:04