예제 #1
0
 def _get_streams(self):
     if "eltrecetv.com.ar/vivo" in self.url.lower():
         try:
             self.session.http.headers = {
                 'Referer': self.url,
                 'User-Agent': useragents.ANDROID
             }
             res = self.session.http.get('https://api.iamat.com/metadata/atcodes/eltrece')
             yt_id = parse_json(res.text)["atcodes"][0]["context"]["ahora"]["vivo"]["youtubeVideo"]
             yt_url = "https://www.youtube.com/watch?v={0}".format(yt_id)
             return self.session.streams(yt_url)
         except BaseException:
             log.info("Live content is temporarily unavailable. Please try again later.")
     else:
         try:
             self.session.http.headers = {
                 'Referer': self.url,
                 'User-Agent': useragents.CHROME
             }
             res = self.session.http.get(self.url)
             _player_re = re.compile(r'''data-kaltura="([^"]+)"''')
             match = _player_re.search(res.text)
             if not match:
                 return
             entry_id = parse_json(match.group(1).replace(""", '"'))["entryId"]
             hls_url = "https://vodgc.com/p/111/sp/11100/playManifest/entryId/" \
                       "{0}/format/applehttp/protocol/https/a.m3u8".format(entry_id)
             return HLSStream.parse_variant_playlist(self.session, hls_url)
         except BaseException:
             log.error("The requested VOD content is unavailable.")
예제 #2
0
 def test_parse_json(self):
     self.assertEqual({}, parse_json("{}"))
     self.assertEqual({"test": 1}, parse_json("""{"test": 1}"""))
     self.assertEqual({"test": 1}, parse_json("""{"test": 1}""", schema=validate.Schema({"test": 1})))
     self.assertRaises(PluginError, parse_json, """{"test: 1}""")
     self.assertRaises(IOError, parse_json, """{"test: 1}""", exception=IOError)
     self.assertRaises(PluginError, parse_json, """{"test: 1}""" * 10)
예제 #3
0
파일: steam.py 프로젝트: mp107/streamlink
    def _get_streams(self):
        streamdata = None
        if self.get_option("email"):
            if self.login(self.get_option("email"), self.get_option("password")):
                log.info("Logged in as {0}".format(self.get_option("email")))
                self.save_cookies(lambda c: "steamMachineAuth" in c.name)

        # Handle steam.tv URLs
        if self.matches[1] is not None:
            # extract the steam ID from the page
            res = self.session.http.get(self.url)
            for div in itertags(res.text, 'div'):
                if div.attributes.get("id") == "webui_config":
                    broadcast_data = html_unescape(div.attributes.get("data-broadcast"))
                    steamid = parse_json(broadcast_data).get("steamid")
                    self.url = self._watch_broadcast_url + steamid

        # extract the steam ID from the URL
        steamid = self.match.group(1)
        res = self.session.http.get(self.url)  # get the page to set some cookies
        sessionid = res.cookies.get('sessionid')

        while streamdata is None or streamdata["success"] in ("waiting", "waiting_for_start"):
            streamdata = self._get_broadcast_stream(steamid,
                                                    sessionid=sessionid)

            if streamdata["success"] == "ready":
                return DASHStream.parse_manifest(self.session, streamdata["url"])
            elif streamdata["success"] == "unavailable":
                log.error("This stream is currently unavailable")
                return
            else:
                r = streamdata["retry"] / 1000.0
                log.info("Waiting for stream, will retry again in {} seconds...".format(r))
                time.sleep(r)
예제 #4
0
    def _get_streams(self):
        res = self.session.http.get(self.url)
        m = self._re_channel_id.search(res.text)
        if not m:
            return

        res = self.session.http.get(
            "https://www.rtvs.sk/json/live5f.json",
            params={
                "c": m.group(1),
                "b": "mozilla",
                "p": "win",
                "f": "0",
                "d": "1",
            }
        )
        videos = parse_json(res.text, schema=validate.Schema({
            "clip": {
                "sources": [{
                    "src": validate.url(),
                    "type": str,
                }],
            }},
            validate.get(("clip", "sources")),
            validate.filter(lambda n: n["type"] == "application/x-mpegurl"),
        ))
        for video in videos:
            yield from HLSStream.parse_variant_playlist(self.session, video["src"]).items()
예제 #5
0
    def _get_streams(self):
        headers = {"Referer": self.url}
        res = self.session.http.get(self.url, headers=headers)

        match = _ddos_re.search(res.text)
        if match:
            log.debug("Anti-DDOS bypass...")
            headers["Cookie"] = match.group(1)
            res = self.session.http.get(self.url, headers=headers)

        match = _apidata_re.search(res.text)
        channel_info = match and parse_json(match.group("data"))
        if not channel_info:
            log.error("Could not find channel info")
            return

        log.debug(
            "Found channel info: id={id} channelkey={channelkey} pid={streamkey} online={status}"
            .format(**channel_info))
        if not channel_info['status']:
            log.debug("Channel appears to be offline")

        streams = {}
        for name, url_suffix in QUALITIES.items():
            url = HLS_URL_FORMAT.format(channel_info['streamkey'], url_suffix)
            if not self._check_stream(url):
                continue

            streams[name] = HLSStream(self.session, url)

        return streams
예제 #6
0
파일: webtv.py 프로젝트: tnira/streamlink
    def _get_streams(self):
        """
        Find the streams for web.tv
        :return:
        """
        headers = {}
        res = self.session.http.get(self.url, headers=headers)
        headers["Referer"] = self.url

        sources = self._sources_re.findall(res.text)
        if len(sources):
            sdata = parse_json(sources[0], schema=self._sources_schema)
            for source in sdata:
                log.debug(f"Found stream of type: {source['type']}")
                if source["type"] == "application/vnd.apple.mpegurl":
                    url = update_scheme("https://", source["src"], force=False)

                    try:
                        # try to parse the stream as a variant playlist
                        variant = HLSStream.parse_variant_playlist(
                            self.session, url, headers=headers)
                        if variant:
                            yield from variant.items()
                        else:
                            # and if that fails, try it as a plain HLS stream
                            yield 'live', HLSStream(self.session,
                                                    url,
                                                    headers=headers)
                    except OSError:
                        log.warning(
                            "Could not open the stream, perhaps the channel is offline"
                        )
예제 #7
0
 def parse_token(tokenstr):
     return parse_json(tokenstr, schema=validate.Schema(
         {"chansub": {"restricted_bitrates": validate.all(
             [str],
             validate.filter(lambda n: not re.match(r"(.+_)?archives|live|chunked", n))
         )}},
         validate.get(("chansub", "restricted_bitrates"))
     ))
예제 #8
0
 def find_tvip(self, url, master=False):
     log.debug("Looking for {0} tvip on {1}".format("master" if master else "", url))
     res = self.session.http.get(url)
     m = self.state_re.search(res.text)
     data = m and parse_json(m.group(1))
     if data:
         channel = data.get("channel")
         if master:
             return channel.get("masterBrand")
         return channel.get("id")
예제 #9
0
    def _get_stream_data(self, id):
        res = self.session.http.get(self.url)
        m = self.json_data_re.search(res.text)
        if m and m.group(1):
            streams = parse_json(m.group(1), schema=self._stream_data_schema)
        else:
            raise PluginError("Failed to get json_data")

        for stream in streams:
            if 'id' in stream:
                if id == stream['id'] and 'stream' in stream:
                    return stream['stream']
예제 #10
0
    def get_stream(self, slug, js_data):
        token_data = {}
        token_data['token'] = self.cache.get('token')
        token_data['token_type'] = self.cache.get('token_type')

        if token_data['token'] and token_data['token_type']:
            log.debug('Using cached token')
        else:
            log.debug('Getting new token')

            res = self.session.http.post(
                self.login_url,
                json=js_data['credentials'],
            )
            token_data = self.session.http.json(res, schema=self.token_schema)
            log.debug('Token={0}'.format(token_data["token"]))

            self.cache.set('token',
                           token_data['token'],
                           expires=token_data['expires_in'])
            self.cache.set('token_type',
                           token_data['token_type'],
                           expires=token_data['expires_in'])

        headers = {
            'Authorization':
            '{0} {1}'.format(token_data["token_type"], token_data["token"])
        }
        data = {
            'slug': slug,
            'type': js_data['type'],
        }
        res = self.session.http.post(
            self.stream_url,
            headers=headers,
            json=data,
        )
        encrypted_data = self.session.http.json(
            res, schema=self.encrypted_data_schema)

        stream_data = parse_json(
            self.decrypt_data(js_data['cipher_data'], encrypted_data),
            schema=self.stream_schema,
        )

        self.author = stream_data['channel_name']
        self.category = stream_data['genres']
        self.title = stream_data['meta_title']

        return stream_data['live_stream_url']
예제 #11
0
    def _get_streams(self):
        room_id = self.match.group("room_id")
        res = self.session.http.get(self.api_url.format(room_id))

        data = self._data_re.search(res.text)
        if not data:
            return

        try:
            hls_url = parse_json(data.group("data"), schema=self._data_schema)
        except Exception:
            raise NoStreamsError(self.url)

        log.debug("URL={0}".format(hls_url))
        return {"live": HLSStream(self.session, hls_url)}
예제 #12
0
    def _parse_streams(self, res):
        stream_url = validate.Schema(
            validate.parse_html(),
            validate.xml_xpath_string(
                ".//head/meta[@property='og:video:url'][@content][1]/@content")
        ).validate(res.text)
        if not stream_url:
            log.debug("No meta og:video:url")
        else:
            if ".mpd" in stream_url:
                for s in DASHStream.parse_manifest(self.session,
                                                   stream_url).items():
                    yield s
                return
            elif ".mp4" in stream_url:
                yield "vod", HTTPStream(self.session, stream_url)
                return

        for match in self._src_re.finditer(res.text):
            stream_url = match.group("url")
            if "\\/" in stream_url:
                # if the URL is json encoded, decode it
                stream_url = parse_json("\"{}\"".format(stream_url))
            if ".mpd" in stream_url:
                for s in DASHStream.parse_manifest(self.session,
                                                   stream_url).items():
                    yield s
            elif ".mp4" in stream_url:
                yield match.group(1), HTTPStream(self.session, stream_url)
            else:
                log.debug("Non-dash/mp4 stream: {0}".format(stream_url))

        match = self._dash_manifest_re.search(res.text)
        if match:
            # facebook replaces "<" characters with the substring "\\x3C"
            manifest = match.group("manifest").replace("\\/", "/")
            if is_py3:
                manifest = bytes(unquote_plus(manifest),
                                 "utf-8").decode("unicode_escape")
            else:
                manifest = unquote_plus(manifest).decode("string_escape")
            # Ignore unsupported manifests until DASH SegmentBase support is implemented
            if "SegmentBase" in manifest:
                log.error("Skipped DASH manifest with SegmentBase streams")
            else:
                for s in DASHStream.parse_manifest(self.session,
                                                   manifest).items():
                    yield s
예제 #13
0
파일: youtube.py 프로젝트: tnira/streamlink
    def _get_data_from_api(self, res):
        _i_video_id = self.match.group("video_id")
        if _i_video_id is None:
            try:
                _i_video_id = self._schema_canonical(res.text)
            except (PluginError, TypeError):
                return

        try:
            _i_api_key = re.search(r'"INNERTUBE_API_KEY":\s*"([^"]+)"',
                                   res.text).group(1)
        except AttributeError:
            _i_api_key = "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8"

        try:
            _i_version = re.search(
                r'"INNERTUBE_CLIENT_VERSION":\s*"([\d\.]+)"',
                res.text).group(1)
        except AttributeError:
            _i_version = "1.20210616.1.0"

        res = self.session.http.post(
            "https://www.youtube.com/youtubei/v1/player",
            headers={"Content-Type": "application/json"},
            params={"key": _i_api_key},
            data=json.dumps({
                "videoId": _i_video_id,
                "contentCheckOk": True,
                "racyCheckOk": True,
                "context": {
                    "client": {
                        "clientName": "WEB",
                        "clientVersion": _i_version,
                        "platform": "DESKTOP",
                        "clientScreen": "EMBED",
                        "clientFormFactor": "UNKNOWN_FORM_FACTOR",
                        "browserName": "Chrome",
                    },
                    "user": {
                        "lockedSafetyMode": "false"
                    },
                    "request": {
                        "useSsl": "true"
                    },
                }
            }),
        )
        return parse_json(res.text)
예제 #14
0
파일: huya.py 프로젝트: tnira/streamlink
    def _get_streams(self):
        res = self.session.http.get(self.url)
        data = self._re_stream.search(res.text)

        if not data:
            return

        data = parse_json(base64.b64decode(data.group(1)), schema=self._schema_data)
        for info in data:
            log.trace(f'{info!r}')
            flv_url = f'{info["sFlvUrl"]}/{info["sStreamName"]}.{info["sFlvUrlSuffix"]}?{info["sFlvAntiCode"]}'
            name = f'source_{info["sCdnType"].lower()}'
            self.QUALITY_WEIGHTS[name] = info['iPCPriorityRate']
            yield name, HTTPStream(self.session, flv_url)

        log.debug(f'QUALITY_WEIGHTS: {self.QUALITY_WEIGHTS!r}')
예제 #15
0
    def find_vpid(self, url, res=None):
        """
        Find the Video Packet ID in the HTML for the provided URL

        :param url: URL to download, if res is not provided.
        :param res: Provide a cached version of the HTTP response to search
        :type url: string
        :type res: requests.Response
        :return: Video Packet ID for a Programme in iPlayer
        :rtype: string
        """
        log.debug(f"Looking for vpid on {url}")
        # Use pre-fetched page if available
        res = res or self.session.http.get(url)
        m = self.mediator_re.search(res.text)
        vpid = m and parse_json(m.group(1), schema=self.mediator_schema)
        return vpid
예제 #16
0
    def _parse_streams(self, res):
        _found_stream_url = False
        for meta in itertags(res.text, "meta"):
            if meta.attributes.get("property") == "og:video:url":
                stream_url = html_unescape(meta.attributes.get("content"))
                if ".mpd" in stream_url:
                    for s in DASHStream.parse_manifest(self.session,
                                                       stream_url).items():
                        yield s
                        _found_stream_url = True
                elif ".mp4" in stream_url:
                    yield "vod", HTTPStream(self.session, stream_url)
                    _found_stream_url = True
                break
        else:
            log.debug("No meta og:video:url")

        if _found_stream_url:
            return

        for match in self._src_re.finditer(res.text):
            stream_url = match.group("url")
            if "\\/" in stream_url:
                # if the URL is json encoded, decode it
                stream_url = parse_json("\"{}\"".format(stream_url))
            if ".mpd" in stream_url:
                yield from DASHStream.parse_manifest(self.session,
                                                     stream_url).items()
            elif ".mp4" in stream_url:
                yield match.group(1), HTTPStream(self.session, stream_url)
            else:
                log.debug("Non-dash/mp4 stream: {0}".format(stream_url))

        match = self._dash_manifest_re.search(res.text)
        if match:
            # facebook replaces "<" characters with the substring "\\x3C"
            manifest = match.group("manifest").replace("\\/", "/")
            manifest = bytes(unquote_plus(manifest),
                             "utf-8").decode("unicode_escape")
            # Ignore unsupported manifests until DASH SegmentBase support is implemented
            if "SegmentBase" in manifest:
                log.error("Skipped DASH manifest with SegmentBase streams")
            else:
                yield from DASHStream.parse_manifest(self.session,
                                                     manifest).items()
예제 #17
0
    def _get_video_data(self, slug):
        m = self.truncate_url_re.search(self.url)
        if m and m.group(1):
            log.debug("Truncated URL={0}".format(m.group(1)))
        else:
            raise PluginError("Failed to truncate URL")

        res = self.session.http.get(m.group(1))
        m = self.json_data_re.search(res.text)
        if m and m.group(1):
            videos = parse_json(m.group(1), schema=self._video_data_schema)
        else:
            raise PluginError("Failed to get json_data")

        for video in videos:
            if 'slug' in videos[video]:
                if slug == videos[video]['slug'] and 'id' in videos[video]:
                    return videos[video]['id']
예제 #18
0
    def _get_streams(self):
        res = self.session.http.get(self.url)
        m = self._config_re.search(res.text)
        if not m:
            log.debug("Unable to find _config_re")
            return

        stream_info = parse_json(m.group(1), "config JSON",
                                 schema=self._stream_config_schema)

        log.trace("stream_info: {0!r}".format(stream_info))
        if not (stream_info and stream_info["is_live"]):
            log.debug("Stream might be Off Air")
            return

        m3u8_url = stream_info.get("secure_m3u8_url")
        if m3u8_url:
            for s in HLSStream.parse_variant_playlist(self.session, m3u8_url).items():
                yield s
예제 #19
0
    def _get_streams(self):
        res = self.session.http.get(self.url)
        m = self._room_json_re.search(res.text)
        if not m:
            log.info("Stream currently unavailable.")
            return

        data = parse_json(m.group(1), schema=self.data_schema)
        # 1. some stream url has bitrate ending with t like _1500t.flv
        # 2. data["vid"] is required because some stream IDs are to short and
        #    it could result in a wrong bitrate for source.
        bitrate_re = re.compile(r"%s_(\d{3,4})\w?\.flv" % data["vid"])
        for d in data["urlArray"]:
            url = d["playUrl"]
            match = bitrate_re.search(url)
            if match:
                stream_name = "{0}k".format(int(match.group(1)))
            else:
                stream_name = "source"
            yield stream_name, HTTPStream(self.session, url)
예제 #20
0
    def _get_streams(self):
        res = self.session.http.get(self.url)
        data = self._re_stream.search(res.text)

        if not data:
            return

        data = parse_json(base64.b64decode(data.group(1)),
                          schema=self._schema_data)
        for info in data:
            log.trace('{0!r}'.format(info))
            flv_url = '{0}/{1}.{2}?{3}'.format(info["sFlvUrl"],
                                               info["sStreamName"],
                                               info["sFlvUrlSuffix"],
                                               info["sFlvAntiCode"])
            name = 'source_{0}'.format(info["sCdnType"].lower())
            self.QUALITY_WEIGHTS[name] = info['iPCPriorityRate']
            yield name, HTTPStream(self.session, flv_url)

        log.debug('QUALITY_WEIGHTS: {0!r}'.format(self.QUALITY_WEIGHTS))
예제 #21
0
    def on_message(self, wsapp, data: str):
        try:
            parsed = parse_json(data, schema=self._schema_cmd)
        except PluginError:
            log.error(f"Could not parse message: {data[:50]}")
            return

        cmd: str = parsed["cmd"]
        args: List[Dict] = parsed["args"]
        log.trace(f"Received '{cmd}' command")
        log.trace(f"{args!r}")

        handlers = self._MESSAGE_HANDLERS.get(cmd)
        if handlers is not None:
            for arg in args:
                for name, handler in handlers.items():
                    argdata = arg.get(name)
                    if argdata is not None:
                        log.debug(f"Processing '{cmd}' - '{name}'")
                        handler(self, argdata)
예제 #22
0
    def _get_streams(self):
        res = self.session.http.get(self.url,
                                    headers={'User-Agent': useragents.CHROME})
        video_search = res.text
        video_search = video_search[
            video_search.index('{"top":{"view":"PlayerContainer","model":{'):]
        video_search = video_search[:video_search.index('}]}}') + 4] + "}"

        video_url_found_hls = ""
        video_url_found_http = ""

        json_video_search = parse_json(video_search)
        json_video_search_sources = json_video_search["top"]["model"][
            "videos"][0]["sources"]
        log.debug('Video ID found: {0}'.format(
            json_video_search["top"]["model"]["id"]))
        for current_video_source in json_video_search_sources:
            if "HLS" in current_video_source["type"]:
                video_url_found_hls = "http://telefe.com" + current_video_source[
                    "url"]
                log.debug("HLS content available")
            if "HTTP" in current_video_source["type"]:
                video_url_found_http = "http://telefe.com" + current_video_source[
                    "url"]
                log.debug("HTTP content available")

        self.session.http.headers = {
            'Referer': self.url,
            'User-Agent': useragents.CHROME,
            'X-Requested-With': 'ShockwaveFlash/25.0.0.148'
        }

        if video_url_found_hls:
            hls_streams = HLSStream.parse_variant_playlist(
                self.session, video_url_found_hls)
            for s in hls_streams.items():
                yield s

        if video_url_found_http:
            yield "http", HTTPStream(self.session, video_url_found_http)
예제 #23
0
    def on_message(self, wsapp, data: str):
        log.debug(f"Received: {data}")
        message = parse_json(data)
        msgtype = message.get("type")
        msgdata = message.get("data", {})

        if msgtype == "ping":
            self.send_pong()

        elif msgtype == "stream" and msgdata.get("protocol") == "hls" and msgdata.get("uri"):
            self.hls_stream_url = msgdata.get("uri")
            self.ready.set()
            if self.opened.wait(self.STREAM_OPENED_TIMEOUT):
                log.debug("Stream opened, keeping websocket connection alive")
            else:
                log.info("Closing websocket connection")
                self.close()

        elif msgtype == "disconnect":
            reason = msgdata.get("reason", "Unknown reason")
            log.info(f"Received disconnect message: {reason}")
            self.close()
예제 #24
0
    def on_message(self, wsapp, data):
        # type: (object, str)
        try:
            parsed = parse_json(data, schema=self._schema_cmd)
        except PluginError:
            log.error("Could not parse message: {0}".format(data[:50]))
            return

        cmd = parsed["cmd"]
        # type: str
        args = parsed["args"]
        # type: List[Dict]
        log.trace("Received '{0}' command".format(cmd))
        log.trace("{0!r}".format(args))

        handlers = self._MESSAGE_HANDLERS.get(cmd)
        if handlers is not None:
            for arg in args:
                for name, handler in handlers.items():
                    argdata = arg.get(name)
                    if argdata is not None:
                        log.debug("Processing '{0}' - '{1}'".format(cmd, name))
                        handler(self, argdata)
예제 #25
0
 def get_hls_url(self, media_id):
     res = self.session.http.get(self.api_url,
                                 params=dict(media_id=media_id))
     return parse_json(res.text, schema=self.api_schema)
예제 #26
0
파일: youtube.py 프로젝트: tnira/streamlink
 def _get_data_from_regex(res, regex, descr):
     match = re.search(regex, res.text)
     if not match:
         log.debug(f"Missing {descr}")
         return
     return parse_json(match.group(1))
예제 #27
0
    def _get_streams(self):
        res = self.session.http.get(self.url)
        for script in itertags(res.text, "script"):
            _type = script.attributes.get("type")
            if not (_type and _type == "application/json"):
                continue

            video_url = None
            _data_ssr_name = script.attributes.get("data-ssr-name")
            if not _data_ssr_name:
                continue

            log.trace(f"Found _data_ssr_name={_data_ssr_name}")
            if _data_ssr_name == "pages/Broadcasts/Broadcasts":
                self.title, video_url, is_live = parse_json(
                    script.text,
                    schema=validate.Schema(
                        {
                            "currentLivestream": {
                                "is_live": bool,
                                "title": str,
                                "stream": validate.url(),
                            }
                        }, validate.get("currentLivestream"),
                        validate.union_get("title", "stream", "is_live")))
                if not is_live:
                    log.error(self._msg_live_offline)
                    continue
            elif _data_ssr_name == "pages/Livestream/Livestream":
                self.title, video_url, is_live = parse_json(
                    script.text,
                    schema=validate.Schema(
                        {
                            "streamIsLive": bool,
                            "title": str,
                            "stream": validate.url(),
                        }, validate.union_get("title", "stream",
                                              "streamIsLive")))
                if not is_live:
                    log.error(self._msg_live_offline)
                    continue
            elif _data_ssr_name in self.vod_keys.keys():
                _key = self.vod_keys[_data_ssr_name]
                self.title, video_url = parse_json(
                    script.text,
                    schema=validate.Schema(
                        {
                            _key: {
                                "title": str,
                                "aspect_ratios": {
                                    "profiles":
                                    validate.all(
                                        [{
                                            "name": str,
                                            "url": validate.url(),
                                        }],
                                        validate.filter(lambda n: n["name"] ==
                                                        "hls_unencrypted"))
                                }
                            }
                        }, validate.get(_key),
                        validate.union_get(
                            "title", ("aspect_ratios", "profiles", 0, "url"))))

            if video_url is not None:
                yield from HLSStream.parse_variant_playlist(
                    self.session, video_url).items()
                break
예제 #28
0
 def recv(self):
     data = parse_json(self._ws.recv(), schema=self.api_schema)
     log.debug("Received `{0}` command".format(data["cmd"]))
     log.trace("{0!r}".format(data))
     return data
예제 #29
0
 def json(cls, res, *args, **kwargs):
     """Parses JSON from a response."""
     # if an encoding is already set then use the provided encoding
     if res.encoding is None:
         res.encoding = cls.determine_json_encoding(res.content[:4])
     return parse_json(res.text, *args, **kwargs)