90 lines
2.7 KiB
Python
Executable file
90 lines
2.7 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
"""Download tracklists from djtracklists.com."""
|
|
|
|
import argparse
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
import requests
|
|
from bs4 import BeautifulSoup
|
|
|
|
|
|
@dataclass
|
|
class Track:
|
|
title: str
|
|
artists: list[str]
|
|
mix: Optional[str]
|
|
mix_artists: Optional[list[str]]
|
|
timestamp: str
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("-s", "--series", help="download this series")
|
|
parser.add_argument("-t", "--tracklist", help="download this tracklist")
|
|
args = parser.parse_args()
|
|
|
|
if tracklist_url := args.tracklist:
|
|
tracklist = download_tracklist(tracklist_url)
|
|
name = tracklist_url.rstrip("/").rsplit("/", maxsplit=1)[-1]
|
|
file_name = Path.cwd() / (name + ".txt")
|
|
save_tracklist(tracklist, file_name)
|
|
|
|
|
|
def is_track_row(css_class: str) -> bool:
|
|
return css_class in ("on", "off")
|
|
|
|
|
|
def download_tracklist(url: str) -> list[Track]:
|
|
response = requests.get(url, timeout=10)
|
|
response.raise_for_status()
|
|
soup = BeautifulSoup(response.text, "html.parser")
|
|
tracklist = []
|
|
for row in soup.find_all("div", class_=is_track_row):
|
|
artists = []
|
|
mix_artists = []
|
|
try:
|
|
title = row.find("a", class_="track").string
|
|
mix = row.find("a", class_="release").string
|
|
except AttributeError:
|
|
title = row.find("b").string
|
|
mix = None
|
|
timestamp = row.find("span", class_="index_time").string
|
|
for artist in row.find_all("a", class_="artist"):
|
|
prev_tag = artist.previous_sibling.string
|
|
if getattr(prev_tag, "string", "").strip() == "remixed by":
|
|
mix_artists.append(artist.string)
|
|
else:
|
|
artists.append(artist.string)
|
|
tracklist.append(
|
|
Track(
|
|
title=title,
|
|
mix=mix,
|
|
artists=artists,
|
|
mix_artists=mix_artists or None,
|
|
timestamp=timestamp,
|
|
)
|
|
)
|
|
return tracklist
|
|
|
|
|
|
def save_tracklist(tracklist: list[Track], file_name: Path):
|
|
try:
|
|
with open(file_name, "wt", encoding="utf8") as file:
|
|
for track in tracklist:
|
|
artists = " & ".join(track.artists)
|
|
line = f"{track.timestamp} — {artists} — {track.title}"
|
|
if track.mix:
|
|
line += f" ({track.mix})"
|
|
if track.mix_artists:
|
|
mix_artists = " & ".join(track.mix_artists)
|
|
line += f" remixed by {mix_artists}"
|
|
file.write(line + "\n")
|
|
except OSError as exc:
|
|
print(f"Can't save tracklist: {exc}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|