Created
July 28, 2025 17:44
-
-
Save benmarwick/cce254383645067a066ecfc42c30fad9 to your computer and use it in GitHub Desktop.
Scrape K5EM's skimmer and plot the number of spots in each band so I can see which bands are open near me
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Load necessary libraries | |
library(selenider) | |
library(dplyr) | |
library(ggplot2) | |
library(purrr) | |
library(tidyr) | |
# --- 1. Setup the Selenider Session --- | |
# The timeout here is important: find_elements() will wait up to 20 seconds. | |
selenider_session <- selenider_session( | |
"chromote", | |
timeout = 20, | |
options = chromote_options(headless = FALSE) | |
) | |
# --- 2. Define HF Bands in kHz --- | |
hf_bands <- tibble( | |
band = factor( | |
c("160m", "80m", "60m", "40m", "30m", "20m", "17m", "15m", "12m", "10m"), | |
levels = c("160m", "80m", "60m", "40m", "30m", "20m", "17m", "15m", "12m", "10m") | |
), | |
low = c(1800, 3500, 5330, 7000, 10100, 14000, 18068, 21000, 24890, 28000), | |
high = c(2000, 4000, 5406, 7300, 10150, 14350, 18168, 21450, 24990, 29700) | |
) | |
# --- 3. Define the Target URL --- | |
url <- "https://www.reversebeacon.net/main.php?zoom=47.76,-117.73,5.90&rows=100&spotters=1&max_age=10,minutes&spotter_call=k5em&hide=distance_km" | |
# --- 4. Define Functions --- | |
#' Scrape Frequencies from RBN | |
get_frequencies <- function() { | |
open_url(url) | |
# This is the correct, idiomatic way to find elements in selenider. | |
# It will implicitly wait for the elements to appear. | |
elements <- selenider_session %>% | |
find_elements(".freq_show_hide.qrg") | |
if (length(elements) == 0) { | |
return(numeric(0)) | |
} | |
freqs <- elements %>% | |
map_chr(elem_text) %>% | |
as.numeric() | |
return(freqs[!is.na(freqs)]) | |
} | |
#' Bin Frequencies into HF Bands | |
bin_to_bands <- function(freqs) { | |
if (length(freqs) == 0) { | |
return(hf_bands %>% select(band) %>% mutate(n = 0)) | |
} | |
tibble(freq = freqs) %>% | |
left_join(hf_bands, by = join_by(between(freq, low, high))) %>% | |
count(band) %>% | |
right_join(hf_bands %>% select(band), by = "band") %>% | |
replace_na(list(n = 0)) %>% | |
arrange(band) | |
} | |
# --- 5. Live Update Loop --- | |
repeat { | |
tryCatch({ | |
cat("Scraping for new spots...\n") | |
freqs <- get_frequencies() | |
counts <- bin_to_bands(freqs) | |
p <- ggplot(counts, aes(x = band, y = n, fill = band)) + | |
geom_col() + | |
coord_cartesian(ylim = c(0, max(5, max(counts$n, na.rm = TRUE) + 1))) + | |
labs( | |
title = paste("Live RBN Spots for K5EM (Last 10 Mins)"), | |
subtitle = paste("Last Updated:", Sys.time()), | |
x = "HF Band", | |
y = "Number of Spots" | |
) + | |
theme_minimal(base_size = 14) + | |
theme(legend.position = "none") | |
print(p) | |
cat("Update complete. Waiting 30 seconds...\n") | |
}, error = function(e) { | |
cat("An error occurred:", e$message, "\n") | |
cat("Retrying in 30 seconds...\n") | |
}) | |
Sys.sleep(30) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment