Files
hiffi-artist-intelligence/collectors/kworb_spotify_collector.py
T

74 lines
3.0 KiB
Python
Raw Normal View History

"""
collectors/kworb_spotify_collector.py
Audited alternative streaming telemetry collector.
Parses verified public Spotify Monthly Listeners from Kworb.net aggregator tables.
Enforces strict provenance attribution.
"""
import requests
from bs4 import BeautifulSoup
from typing import Dict, Optional
KWORB_LISTENERS_URLS = [
"https://kworb.net/spotify/listeners.html",
"https://kworb.net/spotify/listeners2.html"
]
HEADERS = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
)
}
class KworbStreamingCollector:
def __init__(self):
self.cached_listeners: Dict[str, int] = {}
self.is_loaded = False
def load_aggregator_tables(self, max_pages: int = 2):
"""Scrapes and indexes artist listener counts from public HTML tables using BeautifulSoup."""
print(f"[KworbCollector] Indexing public streaming metrics across {max_pages} tables...")
for url in KWORB_LISTENERS_URLS[:max_pages]:
try:
res = requests.get(url, headers=HEADERS, timeout=12)
if res.status_code == 200:
soup = BeautifulSoup(res.text, "html.parser")
rows = soup.find_all("tr")
for row in rows:
cols = row.find_all("td")
if len(cols) >= 3:
# Col 0: Rank, Col 1: Artist (nested inside div > a), Col 2: Monthly Listeners
artist_cell = cols[1]
artist_name = artist_cell.get_text(strip=True).lower()
raw_listeners = cols[2].get_text(strip=True).replace(",", "")
try:
listeners = int(raw_listeners)
self.cached_listeners[artist_name] = listeners
except ValueError:
continue
except Exception as e:
print(f"[KworbCollector] Error reading {url}: {e}")
continue
self.is_loaded = True
print(f"[KworbCollector] Loaded {len(self.cached_listeners):,} artist records into memory.")
def get_monthly_listeners(self, artist_name: str) -> Optional[int]:
if not self.is_loaded:
self.load_aggregator_tables(max_pages=2)
return self.cached_listeners.get(artist_name.strip().lower())
if __name__ == "__main__":
collector = KworbStreamingCollector()
test_cohort = [
"Drake", "Kendrick Lamar", "SZA", "Future", "Latto",
"Russ Millions", "Cash Cobain", "Larry June", "Big Boogie", "Rylo Rodriguez"
]
print("\nTesting Kworb Streaming Telemetry Extraction:")
for artist in test_cohort:
listeners = collector.get_monthly_listeners(artist)
formatted = f"{listeners:,}" if listeners else "Not Listed (< Top 5000)"
print(f" {artist:20} -> {formatted}")