Skip to main content

text/noplaylist.py

1#!/usr/bin/env python3
2"""
3This script receives a YouTube URL on stdin, and removes the `list`
4query parameter.
6I use this in conjunction with `furl` and `youtube-dl`. Sometimes
7I want to download a single video from YouTube, but youtube-dl tries
8to download an entire playlist. This lets me grab just the first video.
9"""
11import sys
12import urllib.parse
14import pytest
17def noplaylist(url: str) -> str:
18 """
19 Remove the playlist query parameters from a URL.
20 """
21 u = urllib.parse.urlsplit(url)
23 query = urllib.parse.parse_qs(u.query)
24 for name in ("list", "index", "pp"):
25 try:
26 del query[name]
27 except KeyError:
28 pass
30 return urllib.parse.urlunsplit(
31 (
32 u.scheme,
33 u.netloc,
34 u.path,
35 urllib.parse.urlencode(query, doseq=True),
36 u.fragment,
37 )
38 )
41@pytest.mark.parametrize(
42 "original_url, url",
43 [
44 (
45 "https://www.youtube.com/watch?v=wrhDXOZoQ74&list=PL7lRfPsqWBLZ9HK6t-BBaVBgRlkLg_FNI&index=4&pp=iAQB",
46 "https://www.youtube.com/watch?v=wrhDXOZoQ74",
47 ),
48 (
49 "https://www.youtube.com/watch?v=wrhDXOZoQ74",
50 "https://www.youtube.com/watch?v=wrhDXOZoQ74",
51 ),
52 ],
54def test_noplaylist(original_url: str, url: str) -> None:
55 """
56 Tests for `noplaylist()`.
57 """
58 assert noplaylist(original_url) == url
61if __name__ == "__main__":
62 url = sys.stdin.read()
63 url = noplaylist(url)
64 sys.stdout.write(url)