Check-in [026af5c9fb]
Overview
| Comment: | Fix xiph search URL and by_format mapping. |
|---|---|
| Downloads: | Tarball | ZIP archive | SQL archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
026af5c9fb5dda5d427a234f79144afe |
| User & Date: | mario on 2015-05-02 23:44:06 |
| Other Links: | manifest | tags |
Context
|
2015-05-02
| ||
| 23:44 | Better plugin comments for user interface. check-in: 85c2fd4f56 user: mario tags: trunk | |
| 23:44 | Fix xiph search URL and by_format mapping. check-in: 026af5c9fb user: mario tags: trunk | |
| 20:03 | Add combined unhtml() utility function for raw page extractors. check-in: 6f314952b9 user: mario tags: trunk | |
Changes
Modified channels/xiph.py from [10274b4d66] to [e7ab9f6f02].
1 2 3 | # encoding: UTF-8 # api: streamtuner2 # title: Xiph.org | | | | | | | > < | > | | > | | > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# encoding: UTF-8
# api: streamtuner2
# title: Xiph.org
# description: ICEcast radios. Scans per JSON API, slow XML, or raw directory.
# type: channel
# url: http://dir.xiph.org/
# version: 0.5
# category: radio
# config:
# { name: xiph_min_bitrate, value: 64, type: int, description: "Minimum bitrate; filter lesser quality streams.", category: filter }
# { name: xiph_source, value: cache, type: select, select: "cache=JSON cache srv|xml=Clunky XML blob|web=Forbidden fruits", description: "Source for station list extraction." }
# priority: standard
# png:
# iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAg5JREFUOI2lk1tIE2AUx3+7CG1tlmlG1rSEHrKgEUF7yO40taQiRj10I4qKkOaT4hIUItuTkC8hpJAQtJCICrFpzEKw
# h61eQorGNBOTzbEt16ZrnR5Wq3mZD/3heziX//983znngyyov+eSbHEA5WKBhs4BKVy9gsqajqwiCwo0dA5IQX5u2s4moliMPPV1nCeDzxgNBFDHE2wsKMPzsGVefobjcnO7RMfeMuL341ZBrNEGRmPqqjdvsbbf
# w7irO4Oj+rdywNNNucmERsLUVndR8uYRU13PCew6hpgP8W02xMpIsik++qk5oweW6y3yob8WnXacZDKJWh1Cp4OtRUHsh19TUlUGViv09RGqKAenU5QnLKm+rK88LjgcUnxmr/h8iNO5XYJBRAQZ/qiVeptGWjty
# 5cClDWLwugQRIRiU5UdPCoD6S89jhV6pks9WG6fuwtBtF5v72vC1v+B86SsM+jD56hjnyiM0lRrAbofeXjQJLdE/78jbXSU5166I6f5VeeDdKdq6GtlSd0QkVU+8XsQhlt9W6izbZ5aMKWgtp2WT/yUHd0xSYU7i
# dsPQ+1WMKIsJD08wEV2HGLeRyNMjawqRxhuKBfdgz1m7fI/4mVX+ZGxmgniOoJv+QZHGAMC7p60ZnHkC8HfzZmLTBCd9af9ccnqMc9HTdmFe4kLkJbH/4h0xVtcu+SP/C78AL6btab6woPcAAAAASUVORK5CYII=
#
# Xiph.org maintains the Ogg streaming standard and Vorbis,
# Opus, FLAC audio, and Theora video compression formats.
# The ICEcast server is a modern alternative to SHOUTcast.
#
# It also provides a directory listing of known internet
# radio stations, only a handful of them using Ogg though.
# The category list is hardwired in this plugin. And there
# are three station fetching modes now:
#
# → "JSON cache" retrieves a refurbished JSON station list,
# both sliceable genres and searchable.
#
# → "Clunky XML" fetches the olden YP.XML, which is really
# slow, then slices out genres. No search.
#
# → "Forbidden Fruits" extracts from dir.xiph.org HTML pages,
# with homepages and listener/max infos available. Search
# is also possible.
#
from config import *
from uikit import uikit
import ahttp
from channels import *
import xml.dom.minidom
|
| ︙ | ︙ | |||
174 175 176 177 178 179 180 181 |
# Fetch directly from website. Which Xiph does not approve of; but
# hey, it's a fallback option here. And the only way to actually
# uncover station homepages.
#@use_rx
def from_raw_html(self, cat, search=None, use_rx=False):
# Build request URL
if search:
| > < > > | | > > | 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# Fetch directly from website. Which Xiph does not approve of; but
# hey, it's a fallback option here. And the only way to actually
# uncover station homepages.
#@use_rx
def from_raw_html(self, cat, search=None, use_rx=False):
# Build request URL
by_format = {t.lower(): t for t in self.categories[-1]}
if search:
url = "http://dir.xiph.org/search?search={}".format(search)
cat = "search"
elif by_format.get(cat):
url = "http://dir.xiph.org/by_format/{}".format(by_format[cat])
elif cat:
url = "http://dir.xiph.org/by_genre/{}".format(cat.title())
# Collect all result pages
html = ahttp.get(url)
for i in range(1,4):
if html.find('page={}">{}</a></li>'.format(i, i+1)) < 0:
break
self.status(i/5.1)
html += ahttp.get(url, {"search": cat.title(), "page": i})
try: html = html.encode("raw_unicode_escape").decode("utf-8")
except: pass
# Find streams
r = []
|
| ︙ | ︙ | |||
205 206 207 208 209 210 211 |
.*? "listeners">\[(\d+)
.*? "stream-description">(.*?)<
.*? Tags: (.*?) </div>
.*? href="(/listen/\d+/listen.xspf)"
.*? class="format"\s+title="([^"]+)"
.*? /by_format/([^"]+)
""", html, re.X|re.S)
| > | | 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
.*? "listeners">\[(\d+)
.*? "stream-description">(.*?)<
.*? Tags: (.*?) </div>
.*? href="(/listen/\d+/listen.xspf)"
.*? class="format"\s+title="([^"]+)"
.*? /by_format/([^"]+)
""", html, re.X|re.S)
print ls
# Assemble
for homepage, title, listeners, playing, tags, url, bits, fmt in ls:
r.append(dict(
genre = unhtml(tags),
title = unhtml(title),
homepage = ahttp.fix_url(homepage),
playing = unhtml(playing),
|
| ︙ | ︙ | |||
483 484 485 486 487 488 489 |
],
"ska",
[
"punkrock",
"oi"
],
"darkwave",
| > | | 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 |
],
"ska",
[
"punkrock",
"oi"
],
"darkwave",
"/FORMAT",
["Ogg_Vorbis", "Ogg_Theora", "Opus", "NSV", "WebM"],
]
# Helper functions for XML extraction mode
# Shortcut to get text content from XML subnode by name
|
| ︙ | ︙ |