Podczas pandemii jedną z form spędzania czasu było jeżdżenie samochodem po mieście. Wszystko było zamykane, straż miejska robiła łapanki ludzi spacerujących w odległości mniejszej niż 5 metrów - samochód był enklawą wolności w perspektywie domowego więzienia. W tym też czasie zdarzało mi się słuchać dużo radia ChilliZet, które raz na czas serwowało muzykę, która naprawdę mi się podobała. Dużo takich inspiracji wylądowało finalnie w mojej bibliotece, np. Kinnship:
Ale do rzeczy.
W radiu było na tyle dużo fajnych piosenek, że pomyślałem, że może bym sobie skombinował ich całą playlistę, i słuchał na własnych warunkach? Bo tam czasami leciała też średnia muzyka, a w swojej biblitece miałbym pełną kontrolę nad moderacją. Wbiłem do internetu, i okazuje się, że na stronie Sprawdź co graliśmy jest dokładna playlista. Pierwsze zwycięstwo.
Strona podaje piosenki w godzinowych iteracjach, żeby zmieniać godziny, wystarczy zmienić cyfrę w adresie, np. dla godziny 14:00 jest to
https://player.chillizet.pl/Sprawdz-co-gralismy/(godzina)/14
Co prawda przez to mam dostęp do muzyki tylko z ostatniej doby, ale zawsze coś, można puścić jakieś cykliczne zadanie, i niech się akumulują dane. "Napisałem" (bo tak naprawdę to Cursor napisał) super prosty skrypt w Pythonie, który pobiera wszystkie strony, parsuje HTML, i wyciąga dane. Odpalam... i klops. Dane są ładowane dynamicznie, za pomocą JavaScriptu.
Dobra, to dajcie mi ten skrypt Javy. Inspekcja strony, i cyk:
https://gfx-player.chillizet.pl/design/player/javascript/played-history.js
Otwieram plik, no i wiadomo: obfuskacja, minimalizacja, masturbacja. Przekopiowałem kod do Cursora, i sformatowałem go. Nadal koszmar. No to wklepałem do promptera: "convert this to Python script". Dwie minuty później, mam gigantyczny projekt z chyba 15 plikami, dokumentacją, testami, plikiem README mówiącym mi, jak mam żyć. Ugh, do kosza. Jeszcze raz: "analyze this JS code, understand it, and create minimal Python script to fetch data about played songs". Kolejne dwie minuty... i tym razem się udało. Nadal dużo bigosu, ale już tylko jeden plik, no i nawet elegancki interfejs:
% python3 minimal_radio.py -h
usage: minimal_radio.py [-h] [--station STATION] [--date DATE] [--time TIME] [--csv CSV]
[--print] [--count COUNT]
Fetch radio station history
options:
-h, --help show this help message and exit
--station, -s STATION
Radio station (default: radiozet)
--date, -d DATE Date in YYYY-MM-DD format (default: current date)
--time, -t TIME Time in HH:MM format (default: current time)
--csv, -c CSV Save tracks to CSV file (default: tracks.csv)
--print, -p Print tracks to console
--count, -n COUNT Maximum number of tracks to fetch (default: unlimited)
No i tak się bawię tym, testuję sobie, ale coś mi nie gra. Wbijam konkretną stację, datę, godzinę, count
, i dostaję wyniki z wybranej godziny, ale też późniejsze. Hmm. A co się stanie, jak wpiszę do count
np. 1000? No proszę. Dostanę 1000 kolejnych wpisów, zaczynając od wpisanej daty i godziny. A jak wpiszę 999999? To dostanę wszystkie. Doskonale - bo teraz już nie będę musiał robić ani żadnych cron
ów, fetch
ów, scrape
ów, tylko sobie ugotuję dosłownie jeden skrypt w Bashu, i dostanę wszystkie dane, jakie tylko są mi potrzebne.
Po chwili testów okazało się, że pierwszy wpis w bazie jest z dnia 5 maja 2022, z godziny 4:00. Nie należy też przesadzać z liczbą pobieranych ścieżek. Liczba, która u mnie działała to 110000, to mniej więcej liczba ścieżek odgrywanych w ciągu jednego roku, więc skrypt wystarczy ustawić na 1 stycznia na godzinę 00:00, i uruchomić dosłownie 4 razy (dla lat 2022-25), żeby mieć całą historię piosenek (i nie tylko) z Chilli Zet. Oczywiście przetworzenie tych danych to osobna bajka, ale już nie na ten wpis.
Oto finalny skrypt dla potomnych:
#!/usr/bin/env zsh
DATE=2022-05-04
TIME=10:00:00
TIMESTAMP=$(date -j -f '%Y-%m-%dT%H:%M:%SZ' "${DATE}T${TIME}Z" +%s)
EMITTER=chilli
TRACK_COUNT=20
URL="https://rds.eurozet.pl/reader/history.php?true=jsonData"
[[ -n "$TIMESTAMP" ]] && URL="$URL&startDate=$TIMESTAMP"
[[ -n "$EMITTER" ]] && URL="$URL&emitter=$EMITTER"
[[ -n "$TRACK_COUNT" ]] && URL="$URL&trackCount=$TRACK_COUNT"
curl -s "$URL" | sed 's/^jsonData(//;s/)$//' | jq . >output.json
Dobra, jeszcze na szybkości skrypt w Pythonie (wygenerowany przez Cursora oczywiście), do wyeksportowania unikalnych piosenek do pliku CSV:
#!/usr/bin/env python3
import json
import csv
import glob
# Read all JSON files and aggregate data
all_songs = []
seen_ids = set()
for file in glob.glob("*.json"):
with open(file) as f:
data = json.load(f)
for song in data["messages"][0]:
if (
song["rds_song_id"] not in seen_ids
and song.get("rds_title")
and song.get("rds_artist")
):
all_songs.append(song)
seen_ids.add(song["rds_song_id"])
# Export to CSV
with open("aggregated_songs.csv", "w", newline="") as f:
if all_songs:
writer = csv.DictWriter(f, fieldnames=all_songs[0].keys())
writer.writeheader()
writer.writerows(all_songs)
print(f"Exported {len(all_songs)} unique songs to aggregated_songs.csv")