Internet radio browser GUI for music/video streams from various directory services.

โŒˆโŒ‹ โŽ‡ branch:  streamtuner2


Check-in [b6d88bcd1f]

Overview
Comment:Document more interna of radio.net extraction
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:b6d88bcd1f9fc688519407e7ecf1cdc84c66da76
User & Date: mario on 2017-02-16 16:56:59
Other Links: manifest | tags
Context
2017-02-20
19:54
Add stub parameter -w (used by pydoc) check-in: ff61e15d6a user: mario tags: trunk
2017-02-16
16:56
Document more interna of radio.net extraction check-in: b6d88bcd1f user: mario tags: trunk
2017-02-15
21:38
document recent channel/feature plugins check-in: 7eb6bd6410 user: mario tags: trunk
Changes

Modified contrib/radionet.py from [29c966c64c] to [460ab10c07].

40
41
42
43
44
45
46
47
48













49
50
51
52
53
54
55
..
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

101
102
103
104
105
106
107
108
109
110
111
112
113
action.extract_playlist.extr_urls["rnjs"] = dict(
    url   = r" (?x) \"streamUrl\" \s*:\s* \"(\w+:\\?/\\?/[^\"]+)\" ",
    title = r" (?x) \"(?:description|seoTitle)\" \s*:\s* \"([^\"]+)\" ",
    unesc = "json",
)


# Radio.net extraction relies on HTML grepping, finding an api key required for station details,
# and letting the action module extract the station/stream URL from that JSON format.













#
class radionet (ChannelPlugin):

    # control flags
    has_search = False
    audioformat = "audio/mpeg"
    listformat = "rnjs"
................................................................................
        # category page, get key
        html = ahttp.get(self.genre_url.format(cat))
        for p in range(2, 4):
            if html.find('"?p={}">'.format(p)) >= 0:
                html += ahttp.get(self.genre_url.format(cat) + "?p={}".format(p))
        self.set_key(html)
        r = []
        """
        <div class="stationinfo-content">Fresh pop music, R&#039;n&#039;B, the newest chart hits and the Top 40 can all be found on this Internet radio station, ANTENNE BAYERN.</div>
        </div><div class="stationinfo   stationinfo-extended  "  expandable ng-cloak >
        <a href="http://antennefrankfurt.radio.net/" class="stationinfo-link" id="">
        <svg class="icon icon-play" id=""><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-play" id=""></use></svg>
        <img src="http://static.radio.net/images/broadcasts/60/cf/19304/c44.png" onError="this.src=window.stationLogo;" alt="ANTENNE FRANKFURT 95.1 " id="">
        <strong id="">
        <svg class="icon icon-podcast"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-podcast"></use></svg>
        <span highlight-text="Top 40" highlight-class="highlight-tags" id="">antenne frankfurt 95.1 </span>
        </strong>
        <small highlight-text="Top 40" highlight-class="highlight-tags" id="">
        Frankfurt am Main, Germany / Charts, News, Pop, Top 40, News, Weather</small>
        <em now-playing="19304" searched-term="Top 40" id=""></em>
        </a>
        <a class="stationinfo-info-toggle" href="" ng-click="toggle()">
        <svg class="icon icon-arrow-up"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-arrow-up"></use></svg>
        <svg class="icon icon-arrow-down"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-arrow-down"></use></svg>
        </a>
        """

        # split station blocks
        for row in re.split("""<div class="stationinfo""", html)[1:]:
        
            # extract text fields
            d = re.findall("""
              <a\s+href="(?:http:)?(//([\w-]+)\.radio\.net/?)" .*?
              <img\s+src="([^<">]+)" .*?
              <strong[^>]*>(.*?)</strong> .*?
              <small[^>]*>\s*(.*?)\s*</small> .*?
            """, row, re.X|re.S)
            
            # refurbish extracted strings
            if d and len(d) and len(d[0]) == 5:







|
<
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>





|







40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
..
87
88
89
90
91
92
93



















94
95
96
97
98
99
100
101
102
103
104
105
106
107
action.extract_playlist.extr_urls["rnjs"] = dict(
    url   = r" (?x) \"streamUrl\" \s*:\s* \"(\w+:\\?/\\?/[^\"]+)\" ",
    title = r" (?x) \"(?:description|seoTitle)\" \s*:\s* \"([^\"]+)\" ",
    unesc = "json",
)


# Radio.net

#
# ยท Uses HTML block-wise regex extraction.
#   โ†’ <a href="stationname.radio.net"> <imgโ€ฆ> <strong>โ€ฆ</strong> <small>โ€ฆ</small>
#
# ยท There's an API key in each page listing, contained in a script block
#   as `apiKey: 'โ€ฆ'?`
#
# ยท Which is needed for generating the station info JSON urls:
#   โ†’ https://api.radio.net/info/v2/search/station?apikey=โ€ฆ&pageindex=1&station=STNAME
#
# ยท To extract these JSON info targets, a custom extraction recipie is injected
#   into the action module.
#   โ†’ "streamUrl": and "description": are scanned for.
#
class radionet (ChannelPlugin):

    # control flags
    has_search = False
    audioformat = "audio/mpeg"
    listformat = "rnjs"
................................................................................
        # category page, get key
        html = ahttp.get(self.genre_url.format(cat))
        for p in range(2, 4):
            if html.find('"?p={}">'.format(p)) >= 0:
                html += ahttp.get(self.genre_url.format(cat) + "?p={}".format(p))
        self.set_key(html)
        r = []




















        # split station blocks
        for row in re.split("""<div class="stationinfo""", html)[1:]:
        
            # extract text fields
            d = re.findall("""
              <a\s+href="(?:https?:)?(//([\w-]+)\.radio\.net/?)" .*?
              <img\s+src="([^<">]+)" .*?
              <strong[^>]*>(.*?)</strong> .*?
              <small[^>]*>\s*(.*?)\s*</small> .*?
            """, row, re.X|re.S)
            
            # refurbish extracted strings
            if d and len(d) and len(d[0]) == 5: