71 lines
2.5 KiB
Python
71 lines
2.5 KiB
Python
"""
|
|
collectors/social_fallback_collector.py
|
|
Resolves missing Instagram handles via the official MusicBrainz REST API.
|
|
Extracts verified url-rel claims without scraping search engines.
|
|
"""
|
|
|
|
import re
|
|
import time
|
|
import requests
|
|
from typing import Optional, Dict, List
|
|
|
|
MB_BASE_URL = "https://musicbrainz.org/ws/2/artist/"
|
|
HEADERS = {
|
|
"User-Agent": "HIFFIArtistIntelligence/1.0 (sri@superlabs.ai)",
|
|
"Accept": "application/json"
|
|
}
|
|
|
|
def resolve_musicbrainz_instagram(artist_name: str) -> Optional[str]:
|
|
"""
|
|
Searches MusicBrainz for the artist and inspects url-rels for Instagram profiles.
|
|
"""
|
|
search_url = f"{MB_BASE_URL}?query=artist:{requests.utils.quote(artist_name)}&fmt=json&limit=3"
|
|
try:
|
|
res = requests.get(search_url, headers=HEADERS, timeout=8)
|
|
if res.status_code != 200:
|
|
return None
|
|
|
|
artists = res.json().get("artists", [])
|
|
if not artists:
|
|
return None
|
|
|
|
# Check top matches
|
|
for artist in artists:
|
|
mbid = artist.get("id")
|
|
if not mbid:
|
|
continue
|
|
|
|
rel_url = f"{MB_BASE_URL}{mbid}?inc=url-rels&fmt=json"
|
|
time.sleep(1.0) # MusicBrainz rate limit compliance: 1 req/sec
|
|
rel_res = requests.get(rel_url, headers=HEADERS, timeout=8)
|
|
if rel_res.status_code == 200:
|
|
relations = rel_res.json().get("relations", [])
|
|
for rel in relations:
|
|
target = rel.get("url", {}).get("resource", "")
|
|
if "instagram.com" in target:
|
|
match = re.search(r"instagram\.com/([A-Za-z0-9_.]+)", target)
|
|
if match:
|
|
handle = match.group(1).lower().rstrip("/.")
|
|
if handle not in {"p", "reel", "explore"}:
|
|
return handle
|
|
except Exception:
|
|
return None
|
|
|
|
return None
|
|
|
|
|
|
class SocialFallbackResolver:
|
|
def resolve_handles(self, artist_names: List[str]) -> Dict[str, Optional[str]]:
|
|
results = {}
|
|
for name in artist_names:
|
|
results[name] = resolve_musicbrainz_instagram(name)
|
|
return results
|
|
|
|
|
|
if __name__ == "__main__":
|
|
resolver = SocialFallbackResolver()
|
|
test_cohort = ["Rylo Rodriguez", "Q Da Fool", "Flatbush Zombies"]
|
|
print("Testing MusicBrainz Entity Fallback Resolver:")
|
|
for artist in test_cohort:
|
|
h = resolve_musicbrainz_instagram(artist)
|
|
print(f" {artist} -> @{h}") |