code:
# coding: utf-8
from __future__ import unicode_literals

import re

from .common import InfoExtractor
from ..utils import parse_duration

class WatchIndianPornIE(InfoExtractor):
    IE_DESC = 'Watch Indian Porn'
    _VALID_URL = r'https?://(?:www\.)?watchindianporn\.net/(?:[^/]+/)*video/(?P<display_id>[^/]+)-(?P<id>[a-zA-Z0-9]+)\.html'
    _TEST = {
        'url': 'http://www.watchindianporn.net/video/hot-milf-from-kerala-shows-off-her-gorgeous-large-breasts-on-camera-RZa2avywNPa.html',
        'md5': '249589a164dde236ec65832bfce17440',
        'info_dict': {
            'id': 'RZa2avywNPa',
            'display_id': 'hot-milf-from-kerala-shows-off-her-gorgeous-large-breasts-on-camera',
            'ext': 'mp4',
            'title': 'Hot milf from kerala shows off her gorgeous large breasts on camera',
            'thumbnail': r're:^https?://.*\.jpg$',
            'duration': 226,
            'view_count': int,
            'categories': list,
            'age_limit': 18,
        }
    }

    def _real_extract(self, url):
        mobj = re.match(self._VALID_URL, url)
        video_id = mobj.group('id')
        display_id = mobj.group('display_id')

        webpage = self._download_webpage(url, display_id)

        info_dict = self._parse_html5_media_entries(url, webpage, video_id)[0]

        title = self._html_search_regex((
            r'<title>(.+?)\s*-\s*Indian\s+Porn</title>',
            r'
(.+?)
'
        ), webpage, 'title')

        duration = parse_duration(self._search_regex(
            r'Time:\s*\s*(.+?)\s*',
            webpage, 'duration', fatal=False))

        view_count = int(self._search_regex(
            r'(?s)Time:\s*.*?.*?\s*(\d+)\s*',
            webpage, 'view count', fatal=False))

        categories = re.findall(
            r']+class=[\'"]categories[\'"][^>]*>\s*([^<]+)\s*',
            webpage)

        info_dict.update({
            'id': video_id,
            'display_id': display_id,
            'http_headers': {
                'Referer': url,
            },
            'title': title,
            'duration': duration,
            'view_count': view_count,
            'categories': categories,
            'age_limit': 18,
        })

        return info_dict


code:
# coding: utf-8
from __future__ import unicode_literals

import re

from .common import InfoExtractor
from ..compat import (
    compat_str,
    compat_urlparse,
)
from ..utils import (
    determine_ext,
    ExtractorError,
    js_to_json,
    strip_jsonp,
    try_get,
    unified_strdate,
    update_url_query,
    urlhandle_detect_ext,
)

class WDRIE(InfoExtractor):
    _VALID_URL = r'https?://deviceids-medp\.wdr\.de/ondemand/\d+/(?P<id>\d+)\.js'
    _GEO_COUNTRIES = ['DE']
    _TEST = {
        'url': 'http://deviceids-medp.wdr.de/ondemand/155/1557833.js',
        'info_dict': {
            'id': 'mdb-1557833',
            'ext': 'mp4',
            'title': 'Biathlon-Staffel verpasst Podest bei Olympia-Generalprobe',
            'upload_date': '20180112',
        },
    }

    def _real_extract(self, url):
        video_id = self._match_id(url)

        metadata = self._download_json(
            url, video_id, transform_source=strip_jsonp)

        is_live = metadata.get('mediaType') == 'live'

        tracker_data = metadata['trackerData']
        media_resource = metadata['mediaResource']

        formats = []

        # check if the metadata contains a direct URL to a file
        for kind, media_resource in media_resource.items():
            if kind not in ('dflt', 'alt'):
                continue

            for tag_name, medium_url in media_resource.items():
                if tag_name not in ('videoURL', 'audioURL'):
                    continue

                ext = determine_ext(medium_url)
                if ext == 'm3u8':
                    formats.extend(self._extract_m3u8_formats(
                        medium_url, video_id, 'mp4', 'm3u8_native',
                        m3u8_id='hls'))
                elif ext == 'f4m':
                    manifest_url = update_url_query(
                        medium_url, {'hdcore': '3.2.0', 'plugin': 'aasp-3.2.0.77.18'})
                    formats.extend(self._extract_f4m_formats(
                        manifest_url, video_id, f4m_id='hds', fatal=False))
                elif ext == 'smil':
                    formats.extend(self._extract_smil_formats(
                        medium_url, 'stream', fatal=False))
                else:
                    a_format = {
                        'url': medium_url
                    }
                    if ext == 'unknown_video':
                        urlh = self._request_webpage(
                            medium_url, video_id, note='Determining extension')
                        ext = urlhandle_detect_ext(urlh)
                        a_format['ext'] = ext
                    formats.append(a_format)

        self._sort_formats(formats)

        subtitles = {}
        caption_url = media_resource.get('captionURL')
        if caption_url:
            subtitles['de'] = [{
                'url': caption_url,
                'ext': 'ttml',
            }]

        title = tracker_data['trackerClipTitle']

        return {
            'id': tracker_data.get('trackerClipId', video_id),
            'title': self._live_title(title) if is_live else title,
            'alt_title': tracker_data.get('trackerClipSubcategory'),
            'formats': formats,
            'subtitles': subtitles,
            'upload_date': unified_strdate(tracker_data.get('trackerClipAirTime')),
            'is_live': is_live,
        }

class WDRPageIE(InfoExtractor):
    _CURRENT_MAUS_URL = r'https?://(?:www\.)wdrmaus.de/(?:[^/]+/){1,2}[^/?#]+\.php5'
    _PAGE_REGEX = r'/(?:mediathek/)?(?:[^/]+/)*(?P<display_id>[^/]+)\.html'
    _VALID_URL = r'https?://(?:www\d?\.)?(?:wdr\d?|sportschau)\.de' + _PAGE_REGEX + '|' + _CURRENT_MAUS_URL

    _TESTS = [
        {
            'url': 'http://www1.wdr.de/mediathek/video/sendungen/doku-am-freitag/video-geheimnis-aachener-dom-100.html',
            # HDS download, MD5 is unstable
            'info_dict': {
                'id': 'mdb-1058683',
                'ext': 'flv',
                'display_id': 'doku-am-freitag/video-geheimnis-aachener-dom-100',
                'title': 'Geheimnis Aachener Dom',
                'alt_title': 'Doku am Freitag',
                'upload_date': '20160304',
                'description': 'md5:87be8ff14d8dfd7a7ee46f0299b52318',
                'is_live': False,
                'subtitles': {'de': [{
                    'url': 'http://ondemand-ww.wdr.de/medp/fsk0/105/1058683/1058683_12220974.xml',
                    'ext': 'ttml',
                }]},
            },
            'skip': 'HTTP Error 404: Not Found',
        },
        {
            'url': 'http://www1.wdr.de/mediathek/audio/wdr3/wdr3-gespraech-am-samstag/audio-schriftstellerin-juli-zeh-100.html',
            'md5': 'f4c1f96d01cf285240f53ea4309663d8',
            'info_dict': {
                'id': 'mdb-1072000',
                'ext': 'mp3',
                'display_id': 'wdr3-gespraech-am-samstag/audio-schriftstellerin-juli-zeh-100',
                'title': 'Schriftstellerin Juli Zeh',
                'alt_title': 'WDR 3 Gespräch am Samstag',
                'upload_date': '20160312',
                'description': 'md5:e127d320bc2b1f149be697ce044a3dd7',
                'is_live': False,
                'subtitles': {}
            },
            'skip': 'HTTP Error 404: Not Found',
        },
        {
            'url': 'http://www1.wdr.de/mediathek/video/live/index.html',
            'info_dict': {
                'id': 'mdb-1406149',
                'ext': 'mp4',
                'title': r're:^WDR Fernsehen im Livestream \(nur in Deutschland erreichbar\) [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$',
                'alt_title': 'WDR Fernsehen Live',
                'upload_date': '20150101',
                'is_live': True,
            },
            'params': {
                'skip_download': True,  # m3u8 download
            },
        },
        {
            'url': 'http://www1.wdr.de/mediathek/video/sendungen/aktuelle-stunde/aktuelle-stunde-120.html',
            'playlist_mincount': 7,
            'info_dict': {
                'id': 'aktuelle-stunde-120',
            },
        },
        {
            'url': 'http://www.wdrmaus.de/aktuelle-sendung/index.php5',
            'info_dict': {
                'id': 'mdb-1552552',
                'ext': 'mp4',
                'upload_date': 're:^[0-9]{8}$',
                'title': 're:^Die Sendung mit der Maus vom [0-9.]{10}$',
            },
            'skip': 'The id changes from week to week because of the new episode'
        },
        {
            'url': 'http://www.wdrmaus.de/filme/sachgeschichten/achterbahn.php5',
            'md5': '803138901f6368ee497b4d195bb164f2',
            'info_dict': {
                'id': 'mdb-186083',
                'ext': 'mp4',
                'upload_date': '20130919',
                'title': 'Sachgeschichte - Achterbahn ',
            },
        },
        {
            'url': 'http://www1.wdr.de/radio/player/radioplayer116~_layout-popupVersion.html',
            # Live stream, MD5 unstable
            'info_dict': {
                'id': 'mdb-869971',
                'ext': 'mp4',
                'title': r're:^COSMO Livestream [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$',
                'upload_date': '20160101',
            },
            'params': {
                'skip_download': True,  # m3u8 download
            }
        },
        {
            'url': 'http://www.sportschau.de/handballem2018/handball-nationalmannschaft-em-stolperstein-vorrunde-100.html',
            'info_dict': {
                'id': 'mdb-1556012',
                'ext': 'mp4',
                'title': 'DHB-Vizepräsident Bob Hanning - "Die Weltspitze ist extrem breit"',
                'upload_date': '20180111',
            },
            'params': {
                'skip_download': True,
            },
        },
        {
            'url': 'http://www.sportschau.de/handballem2018/audio-vorschau---die-handball-em-startet-mit-grossem-favoritenfeld-100.html',
            'only_matching': True,
        }
    ]

    def _real_extract(self, url):
        mobj = re.match(self._VALID_URL, url)
        display_id = mobj.group('display_id')
        webpage = self._download_webpage(url, display_id)

        entries = []

        # Article with several videos

        # for wdr.de the data-extension is in a tag with the class "mediaLink"
        # for wdr.de radio players, in a tag with the class "wdrrPlayerPlayBtn"
        # for wdrmaus, in a tag with the class "videoButton" (previously a link
        # to the page in a multiline "videoLink"-tag)
        for mobj in re.finditer(
            r'''(?sx)class=
                    (?:
                        (["\'])(?:mediaLink|wdrrPlayerPlayBtn|videoButton)\b.*?\1[^>]+|
                        (["\'])videoLink\b.*?\2[\s]*>\n[^\n]*
                    )data-extension=(["\'])(?P<data>(?:(?!\3).)+)\3
                    ''', webpage):
            media_link_obj = self._parse_json(
                mobj.group('data'), display_id, transform_source=js_to_json,
                fatal=False)
            if not media_link_obj:
                continue
            jsonp_url = try_get(
                media_link_obj, lambda x: x['mediaObj']['url'], compat_str)
            if jsonp_url:
                entries.append(self.url_result(jsonp_url, ie=WDRIE.ie_key()))

        # Playlist (e.g. https://www1.wdr.de/mediathek/video/sendungen/aktuelle-stunde/aktuelle-stunde-120.html)
        if not entries:
            entries = [
                self.url_result(
                    compat_urlparse.urljoin(url, mobj.group('href')),
                    ie=WDRPageIE.ie_key())
                for mobj in re.finditer(
                    r'<a[^>]+\bhref=(["\'])(?P<href>(?:(?!\1).)+)\1[^>]+\bdata-extension=',
                    webpage) if re.match(self._PAGE_REGEX, mobj.group('href'))
            ]

        return self.playlist_result(entries, playlist_id=display_id)

class WDRElefantIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)wdrmaus\.de/elefantenseite/#(?P<id>.+)'
    _TEST = {
        'url': 'http://www.wdrmaus.de/elefantenseite/#folge_ostern_2015',
        'info_dict': {
            'title': 'Folge Oster-Spezial 2015',
            'id': 'mdb-1088195',
            'ext': 'mp4',
            'age_limit': None,
            'upload_date': '20150406'
        },
        'params': {
            'skip_download': True,
        },
    }

    def _real_extract(self, url):
        display_id = self._match_id(url)

        # Table of Contents seems to always be at this address, so fetch it directly.
        # The website fetches configurationJS.php5, which links to tableOfContentsJS.php5.
        table_of_contents = self._download_json(
            'https://www.wdrmaus.de/elefantenseite/data/tableOfContentsJS.php5',
            display_id)
        if display_id not in table_of_contents:
            raise ExtractorError(
                'No entry in site\'s table of contents for this URL. '
                'Is the fragment part of the URL (after the #) correct?',
                expected=True)
        xml_metadata_path = table_of_contents[display_id]['xmlPath']
        xml_metadata = self._download_xml(
            'https://www.wdrmaus.de/elefantenseite/' + xml_metadata_path,
            display_id)
        zmdb_url_element = xml_metadata.find('./movie/zmdb_url')
        if zmdb_url_element is None:
            raise ExtractorError(
                '%s is not a video' % display_id, expected=True)
        return self.url_result(zmdb_url_element.text, ie=WDRIE.ie_key())

class WDRMobileIE(InfoExtractor):
    _VALID_URL = r'''(?x)
        https?://mobile-ondemand\.wdr\.de/
        .*?/fsk(?P<age_limit>[0-9]+)
        /[0-9]+/[0-9]+/
        (?P<id>[0-9]+)_(?P<title>[0-9]+)'''
    IE_NAME = 'wdr:mobile'
    _TEST = {
        'url': 'http://mobile-ondemand.wdr.de/CMS2010/mdb/ondemand/weltweit/fsk0/42/421735/421735_4283021.mp4',
        'info_dict': {
            'title': '4283021',
            'id': '421735',
            'ext': 'mp4',
            'age_limit': 0,
        },
        'skip': 'Problems with loading data.'
    }

    def _real_extract(self, url):
        mobj = re.match(self._VALID_URL, url)
        return {
            'id': mobj.group('id'),
            'title': mobj.group('title'),
            'age_limit': int(mobj.group('age_limit')),
            'url': url,
            'http_headers': {
                'User-Agent': 'mobile',
            },
        }

repo_name: rrosajp/youtube


code:
# coding: utf-8
from __future__ import unicode_literals

import re

from .common import InfoExtractor
from ..utils import (
    determine_ext,
    xpath_text,
)

class WebcasterIE(InfoExtractor):
    _VALID_URL = r'https?://bl\.webcaster\.pro/(?:quote|media)/start/free_(?P<id>[^/]+)'
    _TESTS = [{
        # http://video.khl.ru/quotes/393859
        'url': 'http://bl.webcaster.pro/quote/start/free_c8cefd240aa593681c8d068cff59f407_hd/q393859/eb173f99dd5f558674dae55f4ba6806d/1480289104?sr%3D105%26fa%3D1%26type_id%3D18',
        'md5': '0c162f67443f30916ff1c89425dcd4cd',
        'info_dict': {
            'id': 'c8cefd240aa593681c8d068cff59f407_hd',
            'ext': 'mp4',
            'title': 'Сибирь - Нефтехимик. Лучшие моменты первого периода',
            'thumbnail': r're:^https?://.*\.jpg$',
        },
    }, {
        'url': 'http://bl.webcaster.pro/media/start/free_6246c7a4453ac4c42b4398f840d13100_hd/2_2991109016/e8d0d82587ef435480118f9f9c41db41/4635726126',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)

        video = self._download_xml(url, video_id)

        title = xpath_text(video, './/event_name', 'event name', fatal=True)

        def make_id(parts, separator):
            return separator.join(filter(None, parts))

        formats = []
        for format_id in (None, 'noise'):
            track_tag = make_id(('track', format_id), '_')
            for track in video.findall('.//iphone/%s' % track_tag):
                track_url = track.text
                if not track_url:
                    continue
                if determine_ext(track_url) == 'm3u8':
                    m3u8_formats = self._extract_m3u8_formats(
                        track_url, video_id, 'mp4',
                        entry_protocol='m3u8_native',
                        m3u8_id=make_id(('hls', format_id), '-'), fatal=False)
                    for f in m3u8_formats:
                        f.update({
                            'source_preference': 0 if format_id == 'noise' else 1,
                            'format_note': track.get('title'),
                        })
                    formats.extend(m3u8_formats)
        self._sort_formats(formats)

        thumbnail = xpath_text(video, './/image', 'thumbnail')

        return {
            'id': video_id,
            'title': title,
            'thumbnail': thumbnail,
            'formats': formats,
        }

class WebcasterFeedIE(InfoExtractor):
    _VALID_URL = r'https?://bl\.webcaster\.pro/feed/start/free_(?P<id>[^/]+)'
    _TEST = {
        'url': 'http://bl.webcaster.pro/feed/start/free_c8cefd240aa593681c8d068cff59f407_hd/q393859/eb173f99dd5f558674dae55f4ba6806d/1480289104',
        'only_matching': True,
    }

    @staticmethod
    def _extract_url(ie, webpage):
        mobj = re.search(
            r'<(?:object|a[^>]+class=["\']webcaster-player["\'])[^>]+data(?:-config)?=(["\']).*?config=(?P<url>https?://bl\.webcaster\.pro/feed/start/free_.*?)(?:[?&]|\1)',
            webpage)
        if mobj:
            return mobj.group('url')
        for secure in (True, False):
            video_url = ie._og_search_video_url(
                webpage, secure=secure, default=None)
            if video_url:
                mobj = re.search(
                    r'config=(?P<url>https?://bl\.webcaster\.pro/feed/start/free_[^?&=]+)',
                    video_url)
                if mobj:
                    return mobj.group('url')

    def _real_extract(self, url):
        video_id = self._match_id(url)

        feed = self._download_xml(url, video_id)

        video_url = xpath_text(
            feed, ('video_hd', 'video'), 'video url', fatal=True)

        return self.url_result(video_url, WebcasterIE.ie_key())


code:
# coding: utf-8
from __future__ import unicode_literals

import re

from .common import InfoExtractor
from ..utils import (
    int_or_none,
    orderedSet,
)

class WebOfStoriesIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?webofstories\.com/play/(?:[^/]+/)?(?P<id>[0-9]+)'
    _VIDEO_DOMAIN = 'http://eu-mobile.webofstories.com/'
    _GREAT_LIFE_STREAMER = 'rtmp://eu-cdn1.webofstories.com/cfx/st/'
    _USER_STREAMER = 'rtmp://eu-users.webofstories.com/cfx/st/'
    _TESTS = [{
        'url': 'http://www.webofstories.com/play/hans.bethe/71',
        'md5': '373e4dd915f60cfe3116322642ddf364',
        'info_dict': {
            'id': '4536',
            'ext': 'mp4',
            'title': 'The temperature of the sun',
            'thumbnail': r're:^https?://.*\.jpg$',
            'description': 'Hans Bethe talks about calculating the temperature of the sun',
            'duration': 238,
        }
    }, {
        'url': 'http://www.webofstories.com/play/55908',
        'md5': '2985a698e1fe3211022422c4b5ed962c',
        'info_dict': {
            'id': '55908',
            'ext': 'mp4',
            'title': 'The story of Gemmata obscuriglobus',
            'thumbnail': r're:^https?://.*\.jpg$',
            'description': 'Planctomycete talks about The story of Gemmata obscuriglobus',
            'duration': 169,
        },
        'skip': 'notfound',
    }, {
        # malformed og:title meta
        'url': 'http://www.webofstories.com/play/54215?o=MS',
        'info_dict': {
            'id': '54215',
            'ext': 'mp4',
            'title': '"A Leg to Stand On"',
            'thumbnail': r're:^https?://.*\.jpg$',
            'description': 'Oliver Sacks talks about the death and resurrection of a limb',
            'duration': 97,
        },
        'params': {
            'skip_download': True,
        },
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)

        webpage = self._download_webpage(url, video_id)
        # Sometimes og:title meta is malformed
        title = self._og_search_title(webpage, default=None) or self._html_search_regex(
            r'(?s)Title:\s*(.+?)<', webpage, 'title')
        description = self._html_search_meta('description', webpage)
        thumbnail = self._og_search_thumbnail(webpage)

        embed_params = [s.strip(" \r\n\t'") for s in self._search_regex(
            r'(?s)\$\("#embedCode"\).html\(getEmbedCode\((.*?)\)',
            webpage, 'embed params').split(',')]

        (
            _, speaker_id, story_id, story_duration,
            speaker_type, great_life, _thumbnail, _has_subtitles,
            story_filename, _story_order) = embed_params

        is_great_life_series = great_life == 'true'
        duration = int_or_none(story_duration)

        # URL building, see: http://www.webofstories.com/scripts/player.js
        ms_prefix = ''
        if speaker_type.lower() == 'ms':
            ms_prefix = 'mini_sites/'

        if is_great_life_series:
            mp4_url = '{0:}lives/{1:}/{2:}.mp4'.format(
                self._VIDEO_DOMAIN, speaker_id, story_filename)
            rtmp_ext = 'flv'
            streamer = self._GREAT_LIFE_STREAMER
            play_path = 'stories/{0:}/{1:}'.format(
                speaker_id, story_filename)
        else:
            mp4_url = '{0:}{1:}{2:}/{3:}.mp4'.format(
                self._VIDEO_DOMAIN, ms_prefix, speaker_id, story_filename)
            rtmp_ext = 'mp4'
            streamer = self._USER_STREAMER
            play_path = 'mp4:{0:}{1:}/{2}.mp4'.format(
                ms_prefix, speaker_id, story_filename)

        formats = [{
            'format_id': 'mp4_sd',
            'url': mp4_url,
        }, {
            'format_id': 'rtmp_sd',
            'page_url': url,
            'url': streamer,
            'ext': rtmp_ext,
            'play_path': play_path,
        }]

        self._sort_formats(formats)

        return {
            'id': story_id,
            'title': title,
            'formats': formats,
            'thumbnail': thumbnail,
            'description': description,
            'duration': duration,
        }

class WebOfStoriesPlaylistIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?webofstories\.com/playAll/(?P<id>[^/]+)'
    _TEST = {
        'url': 'http://www.webofstories.com/playAll/donald.knuth',
        'info_dict': {
            'id': 'donald.knuth',
            'title': 'Donald Knuth (Scientist)',
        },
        'playlist_mincount': 97,
    }

    def _real_extract(self, url):
        playlist_id = self._match_id(url)

        webpage = self._download_webpage(url, playlist_id)

        entries = [
            self.url_result(
                'http://www.webofstories.com/play/%s' % video_id,
                'WebOfStories', video_id=video_id)
            for video_id in orderedSet(re.findall(r'\bid=["\']td_(\d+)', webpage))
        ]

        title = self._search_regex(
            r'
\s*([^<]+)',
            webpage, 'speaker', default=None)
        if title:
            field = self._search_regex(
                r'([^<]+)',
                webpage, 'field', default=None)
            if field:
                title += ' (%s)' % field

        if not title:
            title = self._search_regex(
                r'<title>Play\s+all\s+stories\s*-\s*([^<]+)\s*-\s*Web\s+of\s+Stories</title>',
                webpage, 'title')

        return self.playlist_result(entries, playlist_id, title)


code:
# coding: utf-8
from __future__ import unicode_literals

from .common import InfoExtractor

import json
import random
import re

from ..compat import (
    compat_parse_qs,
    compat_str,
)
from ..utils import (
    js_to_json,
    strip_jsonp,
    urlencode_postdata,
)

class WeiboIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?weibo\.com/[0-9]+/(?P<id>[a-zA-Z0-9]+)'
    _TEST = {
        'url': 'https://weibo.com/6275294458/Fp6RGfbff?type=comment',
        'info_dict': {
            'id': 'Fp6RGfbff',
            'ext': 'mp4',
            'title': 'You should have servants to massage you,... 来自Hosico_猫 - 微博',
        }
    }

    def _real_extract(self, url):
        video_id = self._match_id(url)
        # to get Referer url for genvisitor
        webpage, urlh = self._download_webpage_handle(url, video_id)

        visitor_url = urlh.geturl()

        if 'passport.weibo.com' in visitor_url:
            # first visit
            visitor_data = self._download_json(
                'https://passport.weibo.com/visitor/genvisitor', video_id,
                note='Generating first-visit data',
                transform_source=strip_jsonp,
                headers={'Referer': visitor_url},
                data=urlencode_postdata({
                    'cb': 'gen_callback',
                    'fp': json.dumps({
                        'os': '2',
                        'browser': 'Gecko57,0,0,0',
                        'fonts': 'undefined',
                        'screenInfo': '1440*900*24',
                        'plugins': '',
                    }),
                }))

            tid = visitor_data['data']['tid']
            cnfd = '%03d' % visitor_data['data']['confidence']

            self._download_webpage(
                'https://passport.weibo.com/visitor/visitor', video_id,
                note='Running first-visit callback',
                query={
                    'a': 'incarnate',
                    't': tid,
                    'w': 2,
                    'c': cnfd,
                    'cb': 'cross_domain',
                    'from': 'weibo',
                    '_rand': random.random(),
                })

            webpage = self._download_webpage(
                url, video_id, note='Revisiting webpage')

        title = self._html_search_regex(
            r'<title>(.+?)</title>', webpage, 'title')

        video_formats = compat_parse_qs(self._search_regex(
            r'video-sources=\\\"(.+?)\"', webpage, 'video_sources'))

        formats = []
        supported_resolutions = (480, 720)
        for res in supported_resolutions:
            vid_urls = video_formats.get(compat_str(res))
            if not vid_urls or not isinstance(vid_urls, list):
                continue

            vid_url = vid_urls[0]
            formats.append({
                'url': vid_url,
                'height': res,
            })

        self._sort_formats(formats)

        uploader = self._og_search_property(
            'nick-name', webpage, 'uploader', default=None)

        return {
            'id': video_id,
            'title': title,
            'uploader': uploader,
            'formats': formats
        }

class WeiboMobileIE(InfoExtractor):
    _VALID_URL = r'https?://m\.weibo\.cn/status/(?P<id>[0-9]+)(\?.+)?'
    _TEST = {
        'url': 'https://m.weibo.cn/status/4189191225395228?wm=3333_2001&sourcetype=weixin&featurecode=newtitle&from=singlemessage&isappinstalled=0',
        'info_dict': {
            'id': '4189191225395228',
            'ext': 'mp4',
            'title': '午睡当然是要甜甜蜜蜜的啦',
            'uploader': '柴犬柴犬'
        }
    }

    def _real_extract(self, url):
        video_id = self._match_id(url)
        # to get Referer url for genvisitor
        webpage = self._download_webpage(url, video_id, note='visit the page')

        weibo_info = self._parse_json(self._search_regex(
            r'var\s+\$render_data\s*=\s*\[({.*})\]\[0\]\s*\|\|\s*{};',
            webpage, 'js_code', flags=re.DOTALL),
            video_id, transform_source=js_to_json)

        status_data = weibo_info.get('status', {})
        page_info = status_data.get('page_info')
        title = status_data['status_title']
        uploader = status_data.get('user', {}).get('screen_name')

        return {
            'id': video_id,
            'title': title,
            'uploader': uploader,
            'url': page_info['media_info']['stream_url']
        }


code:
# coding: utf-8
from __future__ import unicode_literals

from .common import InfoExtractor

class WeiqiTVIE(InfoExtractor):
    IE_DESC = 'WQTV'
    _VALID_URL = r'https?://(?:www\.)?weiqitv\.com/index/video_play\?videoId=(?P<id>[A-Za-z0-9]+)'

    _TESTS = [{
        'url': 'http://www.weiqitv.com/index/video_play?videoId=53c744f09874f0e76a8b46f3',
        'md5': '26450599afd64c513bc77030ad15db44',
        'info_dict': {
            'id': '53c744f09874f0e76a8b46f3',
            'ext': 'mp4',
            'title': '2013年度盘点',
        },
    }, {
        'url': 'http://www.weiqitv.com/index/video_play?videoId=567379a2d4c36cca518b4569',
        'info_dict': {
            'id': '567379a2d4c36cca518b4569',
            'ext': 'mp4',
            'title': '民国围棋史',
        },
    }, {
        'url': 'http://www.weiqitv.com/index/video_play?videoId=5430220a9874f088658b4567',
        'info_dict': {
            'id': '5430220a9874f088658b4567',
            'ext': 'mp4',
            'title': '二路托过的手段和运用',
        },
    }]

    def _real_extract(self, url):
        media_id = self._match_id(url)
        page = self._download_webpage(url, media_id)

        info_json_str = self._search_regex(
            r'var\s+video\s*=\s*(.+});', page, 'info json str')
        info_json = self._parse_json(info_json_str, media_id)

        letvcloud_url = self._search_regex(
            r'var\s+letvurl\s*=\s*"([^"]+)', page, 'letvcloud url')

        return {
            '_type': 'url_transparent',
            'ie_key': 'LetvCloud',
            'url': letvcloud_url,
            'title': info_json['name'],
            'id': media_id,
        }


code:
from __future__ import unicode_literals

import re

from .common import InfoExtractor
from ..utils import (
    ExtractorError,
    int_or_none,
    float_or_none,
    unescapeHTML,
)

class WistiaIE(InfoExtractor):
    _VALID_URL = r'(?:wistia:|https?://(?:fast\.)?wistia\.(?:net|com)/embed/(?:iframe|medias)/)(?P<id>[a-z0-9]{10})'
    _EMBED_BASE_URL = 'http://fast.wistia.com/embed/'

    _TESTS = [{
        'url': 'http://fast.wistia.net/embed/iframe/sh7fpupwlt',
        'md5': 'cafeb56ec0c53c18c97405eecb3133df',
        'info_dict': {
            'id': 'sh7fpupwlt',
            'ext': 'mov',
            'title': 'Being Resourceful',
            'description': 'a Clients From Hell Video Series video from worldwidewebhosting',
            'upload_date': '20131204',
            'timestamp': 1386185018,
            'duration': 117,
        },
    }, {
        'url': 'wistia:sh7fpupwlt',
        'only_matching': True,
    }, {
        # with hls video
        'url': 'wistia:807fafadvk',
        'only_matching': True,
    }, {
        'url': 'http://fast.wistia.com/embed/iframe/sh7fpupwlt',
        'only_matching': True,
    }, {
        'url': 'http://fast.wistia.net/embed/medias/sh7fpupwlt.json',
        'only_matching': True,
    }]

    # https://wistia.com/support/embed-and-share/video-on-your-website
    @staticmethod
    def _extract_url(webpage):
        urls = WistiaIE._extract_urls(webpage)
        return urls[0] if urls else None

    @staticmethod
    def _extract_urls(webpage):
        urls = []
        for match in re.finditer(
                r'<(?:meta[^>]+?content|(?:iframe|script)[^>]+?src)=["\'](?P<url>(?:https?:)?//(?:fast\.)?wistia\.(?:net|com)/embed/(?:iframe|medias)/[a-z0-9]{10})', webpage):
            urls.append(unescapeHTML(match.group('url')))
        for match in re.finditer(
                r'''(?sx)
                    <div[^>]+class=(["'])(?:(?!\1).)*?\bwistia_async_(?P<id>[a-z0-9]{10})\b(?:(?!\1).)*?\1
                ''', webpage):
            urls.append('wistia:%s' % match.group('id'))
        for match in re.finditer(r'(?:data-wistia-?id=["\']|Wistia\.embed\(["\']|id=["\']wistia_)(?P<id>[a-z0-9]{10})', webpage):
            urls.append('wistia:%s' % match.group('id'))
        return urls

    def _real_extract(self, url):
        video_id = self._match_id(url)

        data_json = self._download_json(
            self._EMBED_BASE_URL + 'medias/%s.json' % video_id, video_id,
            # Some videos require this.
            headers={
                'Referer': url if url.startswith('http') else self._EMBED_BASE_URL + 'iframe/' + video_id,
            })

        if data_json.get('error'):
            raise ExtractorError(
                'Error while getting the playlist', expected=True)

        data = data_json['media']
        title = data['name']

        formats = []
        thumbnails = []
        for a in data['assets']:
            aurl = a.get('url')
            if not aurl:
                continue
            astatus = a.get('status')
            atype = a.get('type')
            if (astatus is not None and astatus != 2) or atype in ('preview', 'storyboard'):
                continue
            elif atype in ('still', 'still_image'):
                thumbnails.append({
                    'url': aurl,
                    'width': int_or_none(a.get('width')),
                    'height': int_or_none(a.get('height')),
                    'filesize': int_or_none(a.get('size')),
                })
            else:
                aext = a.get('ext')
                display_name = a.get('display_name')
                format_id = atype
                if atype and atype.endswith('_video') and display_name:
                    format_id = '%s-%s' % (atype[:-6], display_name)
                f = {
                    'format_id': format_id,
                    'url': aurl,
                    'tbr': int_or_none(a.get('bitrate')) or None,
                    'preference': 1 if atype == 'original' else None,
                }
                if display_name == 'Audio':
                    f.update({
                        'vcodec': 'none',
                    })
                else:
                    f.update({
                        'width': int_or_none(a.get('width')),
                        'height': int_or_none(a.get('height')),
                        'vcodec': a.get('codec'),
                    })
                if a.get('container') == 'm3u8' or aext == 'm3u8':
                    ts_f = f.copy()
                    ts_f.update({
                        'ext': 'ts',
                        'format_id': f['format_id'].replace('hls-', 'ts-'),
                        'url': f['url'].replace('.bin', '.ts'),
                    })
                    formats.append(ts_f)
                    f.update({
                        'ext': 'mp4',
                        'protocol': 'm3u8_native',
                    })
                else:
                    f.update({
                        'container': a.get('container'),
                        'ext': aext,
                        'filesize': int_or_none(a.get('size')),
                    })
                formats.append(f)

        self._sort_formats(formats)

        subtitles = {}
        for caption in data.get('captions', []):
            language = caption.get('language')
            if not language:
                continue
            subtitles[language] = [{
                'url': self._EMBED_BASE_URL + 'captions/' + video_id + '.vtt?language=' + language,
            }]

        return {
            'id': video_id,
            'title': title,
            'description': data.get('seoDescription'),
            'formats': formats,
            'thumbnails': thumbnails,
            'duration': float_or_none(data.get('duration')),
            'timestamp': int_or_none(data.get('createdAt')),
            'subtitles': subtitles,
        }


code:
from __future__ import unicode_literals

from .common import InfoExtractor

class WorldStarHipHopIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www|m)\.worldstar(?:candy|hiphop)\.com/(?:videos|android)/video\.php\?.*?\bv=(?P<id>[^&]+)'
    _TESTS = [{
        'url': 'http://www.worldstarhiphop.com/videos/video.php?v=wshh6a7q1ny0G34ZwuIO',
        'md5': '9d04de741161603bf7071bbf4e883186',
        'info_dict': {
            'id': 'wshh6a7q1ny0G34ZwuIO',
            'ext': 'mp4',
            'title': 'KO Of The Week: MMA Fighter Gets Knocked Out By Swift Head Kick!'
        }
    }, {
        'url': 'http://m.worldstarhiphop.com/android/video.php?v=wshh6a7q1ny0G34ZwuIO',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)

        entries = self._parse_html5_media_entries(url, webpage, video_id)

        if not entries:
            return self.url_result(url, 'Generic')

        title = self._html_search_regex(
            [r'(?s)
\s*
(.*?)
',
             r']+class="tc-sp-pinned-title">(.*)'],
            webpage, 'title')

        info = entries[0]
        info.update({
            'id': video_id,
            'title': title,
        })
        return info


code:
# coding: utf-8
from __future__ import unicode_literals

from .common import InfoExtractor
from ..utils import (
    int_or_none,
    float_or_none,
    unified_strdate,
)

class WSJIE(InfoExtractor):
    _VALID_URL = r'''(?x)
                        (?:
                            https?://video-api\.wsj\.com/api-video/player/iframe\.html\?.*?\bguid=|
                            https?://(?:www\.)?(?:wsj|barrons)\.com/video/(?:[^/]+/)+|
                            wsj:
                        )
                        (?P<id>[a-fA-F0-9-]{36})
                    '''
    IE_DESC = 'Wall Street Journal'
    _TESTS = [{
        'url': 'http://video-api.wsj.com/api-video/player/iframe.html?guid=1BD01A4C-BFE8-40A5-A42F-8A8AF9898B1A',
        'md5': 'e230a5bb249075e40793b655a54a02e4',
        'info_dict': {
            'id': '1BD01A4C-BFE8-40A5-A42F-8A8AF9898B1A',
            'ext': 'mp4',
            'upload_date': '20150202',
            'uploader_id': 'jdesai',
            'creator': 'jdesai',
            'categories': list,  # a long list
            'duration': 90,
            'title': 'Bills Coach Rex Ryan Updates His Old Jets Tattoo',
        },
    }, {
        'url': 'http://www.wsj.com/video/can-alphabet-build-a-smarter-city/359DDAA8-9AC1-489C-82E6-0429C1E430E0.html',
        'only_matching': True,
    }, {
        'url': 'http://www.barrons.com/video/capitalism-deserves-more-respect-from-millennials/F301217E-6F46-43AE-B8D2-B7180D642EE9.html',
        'only_matching': True,
    }, {
        'url': 'https://www.wsj.com/video/series/a-brief-history-of/the-modern-cell-carrier-how-we-got-here/980E2187-401D-48A1-B82B-1486CEE06CB9',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)

        info = self._download_json(
            'http://video-api.wsj.com/api-video/find_all_videos.asp', video_id,
            query={
                'type': 'guid',
                'count': 1,
                'query': video_id,
                'fields': ','.join((
                    'type', 'hls', 'videoMP4List', 'thumbnailList', 'author',
                    'description', 'name', 'duration', 'videoURL', 'titletag',
                    'formattedCreationDate', 'keywords', 'editor')),
            })['items'][0]
        title = info.get('name', info.get('titletag'))

        formats = []

        f4m_url = info.get('videoURL')
        if f4m_url:
            formats.extend(self._extract_f4m_formats(
                f4m_url, video_id, f4m_id='hds', fatal=False))

        m3u8_url = info.get('hls')
        if m3u8_url:
            formats.extend(self._extract_m3u8_formats(
                info['hls'], video_id, ext='mp4',
                entry_protocol='m3u8_native', m3u8_id='hls', fatal=False))

        for v in info.get('videoMP4List', []):
            mp4_url = v.get('url')
            if not mp4_url:
                continue
            tbr = int_or_none(v.get('bitrate'))
            formats.append({
                'url': mp4_url,
                'format_id': 'http' + ('-%d' % tbr if tbr else ''),
                'tbr': tbr,
                'width': int_or_none(v.get('width')),
                'height': int_or_none(v.get('height')),
                'fps': float_or_none(v.get('fps')),
            })
        self._sort_formats(formats)

        return {
            'id': video_id,
            'formats': formats,
            # Thumbnails are conveniently in the correct format already
            'thumbnails': info.get('thumbnailList'),
            'creator': info.get('author'),
            'uploader_id': info.get('editor'),
            'duration': int_or_none(info.get('duration')),
            'upload_date': unified_strdate(info.get(
                'formattedCreationDate'), day_first=False),
            'title': title,
            'categories': info.get('keywords'),
        }

class WSJArticleIE(InfoExtractor):
    _VALID_URL = r'(?i)https?://(?:www\.)?wsj\.com/articles/(?P<id>[^/?#&]+)'
    _TEST = {
        'url': 'https://www.wsj.com/articles/dont-like-china-no-pandas-for-you-1490366939?',
        'info_dict': {
            'id': '4B13FA62-1D8C-45DB-8EA1-4105CB20B362',
            'ext': 'mp4',
            'upload_date': '20170221',
            'uploader_id': 'ralcaraz',
            'title': 'Bao Bao the Panda Leaves for China',
        }
    }

    def _real_extract(self, url):
        article_id = self._match_id(url)
        webpage = self._download_webpage(url, article_id)
        video_id = self._search_regex(
            r'data-src=["\']([a-fA-F0-9-]{36})', webpage, 'video id')
        return self.url_result('wsj:%s' % video_id, WSJIE.ie_key(), video_id)


code:
from __future__ import unicode_literals

import re

from .common import InfoExtractor
from ..compat import compat_str
from ..utils import (
    try_get,
    unescapeHTML,
    url_or_none,
    urljoin,
)

class WWEBaseIE(InfoExtractor):
    _SUBTITLE_LANGS = {
        'English': 'en',
        'Deutsch': 'de',
    }

    def _extract_entry(self, data, url, video_id=None):
        video_id = compat_str(video_id or data['nid'])
        title = data['title']

        formats = self._extract_m3u8_formats(
            data['file'], video_id, 'mp4', entry_protocol='m3u8_native',
            m3u8_id='hls')

        description = data.get('description')
        thumbnail = urljoin(url, data.get('image'))
        series = data.get('show_name')
        episode = data.get('episode_name')

        subtitles = {}
        tracks = data.get('tracks')
        if isinstance(tracks, list):
            for track in tracks:
                if not isinstance(track, dict):
                    continue
                if track.get('kind') != 'captions':
                    continue
                track_file = url_or_none(track.get('file'))
                if not track_file:
                    continue
                label = track.get('label')
                lang = self._SUBTITLE_LANGS.get(label, label) or 'en'
                subtitles.setdefault(lang, []).append({
                    'url': track_file,
                })

        return {
            'id': video_id,
            'title': title,
            'description': description,
            'thumbnail': thumbnail,
            'series': series,
            'episode': episode,
            'formats': formats,
            'subtitles': subtitles,
        }

class WWEIE(WWEBaseIE):
    _VALID_URL = r'https?://(?:[^/]+\.)?wwe\.com/(?:[^/]+/)*videos/(?P<id>[^/?#&]+)'
    _TESTS = [{
        'url': 'https://www.wwe.com/videos/daniel-bryan-vs-andrade-cien-almas-smackdown-live-sept-4-2018',
        'md5': '92811c6a14bfc206f7a6a9c5d9140184',
        'info_dict': {
            'id': '40048199',
            'ext': 'mp4',
            'title': 'Daniel Bryan vs. Andrade "Cien" Almas: SmackDown LIVE, Sept. 4, 2018',
            'description': 'md5:2d7424dbc6755c61a0e649d2a8677f67',
            'thumbnail': r're:^https?://.*\.jpg$',
        }
    }, {
        'url': 'https://de.wwe.com/videos/gran-metalik-vs-tony-nese-wwe-205-live-sept-4-2018',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        display_id = self._match_id(url)
        webpage = self._download_webpage(url, display_id)

        landing = self._parse_json(
            self._html_search_regex(
                r'(?s)Drupal\.settings\s*,\s*({.+?})\s*\)\s*;',
                webpage, 'drupal settings'),
            display_id)['WWEVideoLanding']

        data = landing['initialVideo']['playlist'][0]
        video_id = landing.get('initialVideoId')

        info = self._extract_entry(data, url, video_id)
        info['display_id'] = display_id
        return info

class WWEPlaylistIE(WWEBaseIE):
    _VALID_URL = r'https?://(?:[^/]+\.)?wwe\.com/(?:[^/]+/)*(?P<id>[^/?#&]+)'
    _TESTS = [{
        'url': 'https://www.wwe.com/shows/raw/2018-11-12',
        'info_dict': {
            'id': '2018-11-12',
        },
        'playlist_mincount': 11,
    }, {
        'url': 'http://www.wwe.com/article/walk-the-prank-wwe-edition',
        'only_matching': True,
    }, {
        'url': 'https://www.wwe.com/shows/wwenxt/article/matt-riddle-interview',
        'only_matching': True,
    }]

    @classmethod
    def suitable(cls, url):
        return False if WWEIE.suitable(url) else super(WWEPlaylistIE, cls).suitable(url)

    def _real_extract(self, url):
        display_id = self._match_id(url)
        webpage = self._download_webpage(url, display_id)

        entries = []
        for mobj in re.finditer(
                r'data-video\s*=\s*(["\'])(?P<data>{.+?})\1', webpage):
            video = self._parse_json(
                mobj.group('data'), display_id, transform_source=unescapeHTML,
                fatal=False)
            if not video:
                continue
            data = try_get(video, lambda x: x['playlist'][0], dict)
            if not data:
                continue
            try:
                entry = self._extract_entry(data, url)
            except Exception:
                continue
            entry['extractor_key'] = WWEIE.ie_key()
            entries.append(entry)

        return self.playlist_result(entries, display_id)


code:
from __future__ import unicode_literals

from .common import InfoExtractor
from ..compat import compat_urllib_parse_unquote

class XBefIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?xbef\.com/video/(?P<id>[0-9]+)'
    _TEST = {
        'url': 'http://xbef.com/video/5119-glamourous-lesbians-smoking-drinking-and-fucking',
        'md5': 'a478b565baff61634a98f5e5338be995',
        'info_dict': {
            'id': '5119',
            'ext': 'mp4',
            'title': 'md5:7358a9faef8b7b57acda7c04816f170e',
            'age_limit': 18,
            'thumbnail': r're:^http://.*\.jpg',
        }
    }

    def _real_extract(self, url):
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)

        title = self._html_search_regex(
            r'<h1[^>]*>(.*?)</h1>', webpage, 'title')

        config_url_enc = self._download_webpage(
            'http://xbef.com/Main/GetVideoURLEncoded/%s' % video_id, video_id,
            note='Retrieving config URL')
        config_url = compat_urllib_parse_unquote(config_url_enc)
        config = self._download_xml(
            config_url, video_id, note='Retrieving config')

        video_url = config.find('./file').text
        thumbnail = config.find('./image').text

        return {
            'id': video_id,
            'url': video_url,
            'title': title,
            'thumbnail': thumbnail,
            'age_limit': 18,
        }


code:
# coding: utf-8
from __future__ import unicode_literals

from .common import InfoExtractor
from ..utils import (
    int_or_none,
    parse_filesize,
    unified_strdate,
)

class XboxClipsIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?xboxclips\.com/(?:video\.php\?.*vid=|[^/]+/)(?P<id>[\w-]{36})'
    _TEST = {
        'url': 'http://xboxclips.com/video.php?uid=2533274823424419&gamertag=Iabdulelah&vid=074a69a9-5faf-46aa-b93b-9909c1720325',
        'md5': 'fbe1ec805e920aeb8eced3c3e657df5d',
        'info_dict': {
            'id': '074a69a9-5faf-46aa-b93b-9909c1720325',
            'ext': 'mp4',
            'title': 'Iabdulelah playing Titanfall',
            'filesize_approx': 26800000,
            'upload_date': '20140807',
            'duration': 56,
        }
    }

    def _real_extract(self, url):
        video_id = self._match_id(url)

        webpage = self._download_webpage(url, video_id)

        video_url = self._html_search_regex(
            r'>(?:Link|Download): <a[^>]+href="([^"]+)"', webpage, 'video URL')
        title = self._html_search_regex(
            r'<title>XboxClips \| ([^<]+)</title>', webpage, 'title')
        upload_date = unified_strdate(self._html_search_regex(
            r'>Recorded: ([^<]+)<', webpage, 'upload date', fatal=False))
        filesize = parse_filesize(self._html_search_regex(
            r'>Size: ([^<]+)<', webpage, 'file size', fatal=False))
        duration = int_or_none(self._html_search_regex(
            r'>Duration: (\d+) Seconds<', webpage, 'duration', fatal=False))
        view_count = int_or_none(self._html_search_regex(
            r'>Views: (\d+)<', webpage, 'view count', fatal=False))

        return {
            'id': video_id,
            'url': video_url,
            'title': title,
            'upload_date': upload_date,
            'filesize_approx': filesize,
            'duration': duration,
            'view_count': view_count,
        }


code:
# coding: utf-8
from __future__ import unicode_literals

import re

from .common import InfoExtractor
from ..compat import compat_chr
from ..utils import (
    decode_packed_codes,
    determine_ext,
    ExtractorError,
    int_or_none,
    js_to_json,
    urlencode_postdata,
)

# based on openload_decode from 2bfeee69b976fe049761dd3012e30b637ee05a58
def aa_decode(aa_code):
    symbol_table = [
        ('7', '((ﾟｰﾟ) + (o^_^o))'),
        ('6', '((o^_^o) +(o^_^o))'),
        ('5', '((ﾟｰﾟ) + (ﾟΘﾟ))'),
        ('2', '((o^_^o) - (ﾟΘﾟ))'),
        ('4', '(ﾟｰﾟ)'),
        ('3', '(o^_^o)'),
        ('1', '(ﾟΘﾟ)'),
        ('0', '(c^_^o)'),
    ]
    delim = '(ﾟДﾟ)[ﾟεﾟ]+'
    ret = ''
    for aa_char in aa_code.split(delim):
        for val, pat in symbol_table:
            aa_char = aa_char.replace(pat, val)
        aa_char = aa_char.replace('+ ', '')
        m = re.match(r'^\d+', aa_char)
        if m:
            ret += compat_chr(int(m.group(0), 8))
        else:
            m = re.match(r'^u([\da-f]+)', aa_char)
            if m:
                ret += compat_chr(int(m.group(1), 16))
    return ret

class XFileShareIE(InfoExtractor):
    _SITES = (
        (r'clipwatching\.com', 'ClipWatching'),
        (r'gounlimited\.to', 'GoUnlimited'),
        (r'govid\.me', 'GoVid'),
        (r'holavid\.com', 'HolaVid'),
        (r'streamty\.com', 'Streamty'),
        (r'thevideobee\.to', 'TheVideoBee'),
        (r'uqload\.com', 'Uqload'),
        (r'vidbom\.com', 'VidBom'),
        (r'vidlo\.us', 'vidlo'),
        (r'vidlocker\.xyz', 'VidLocker'),
        (r'vidshare\.tv', 'VidShare'),
        (r'vup\.to', 'VUp'),
        (r'xvideosharing\.com', 'XVideoSharing'),
    )

    IE_DESC = 'XFileShare based sites: %s' % ', '.join(list(zip(*_SITES))[1])
    _VALID_URL = (r'https?://(?:www\.)?(?P<host>%s)/(?:embed-)?(?P<id>[0-9a-zA-Z]+)'
                  % '|'.join(site for site in list(zip(*_SITES))[0]))

    _FILE_NOT_FOUND_REGEXES = (
        r'>(?:404 - )?File Not Found<',
        r'>The file was removed by administrator<',
    )

    _TESTS = [{
        'url': 'http://xvideosharing.com/fq65f94nd2ve',
        'md5': '4181f63957e8fe90ac836fa58dc3c8a6',
        'info_dict': {
            'id': 'fq65f94nd2ve',
            'ext': 'mp4',
            'title': 'sample',
            'thumbnail': r're:http://.*\.jpg',
        },
    }]

    @staticmethod
    def _extract_urls(webpage):
        return [
            mobj.group('url')
            for mobj in re.finditer(
                r']+\bsrc=(["\'])(?P<url>(?:https?:)?//(?:%s)/embed-[0-9a-zA-Z]+.*?)\1'
                % '|'.join(site for site in list(zip(*XFileShareIE._SITES))[0]),
                webpage)]

    def _real_extract(self, url):
        host, video_id = re.match(self._VALID_URL, url).groups()

        url = 'https://%s/' % host + ('embed-%s.html' % video_id if host in ('govid.me', 'vidlo.us') else video_id)
        webpage = self._download_webpage(url, video_id)

        if any(re.search(p, webpage) for p in self._FILE_NOT_FOUND_REGEXES):
            raise ExtractorError('Video %s does not exist' % video_id, expected=True)

        fields = self._hidden_inputs(webpage)

        if fields.get('op') == 'download1':
            countdown = int_or_none(self._search_regex(
                r'(?:[Ww]ait)?\s*(\d+)\s*(?:seconds?)?',
                webpage, 'countdown', default=None))
            if countdown:
                self._sleep(countdown, video_id)

            webpage = self._download_webpage(
                url, video_id, 'Downloading video page',
                data=urlencode_postdata(fields), headers={
                    'Referer': url,
                    'Content-type': 'application/x-www-form-urlencoded',
                })

        title = (self._search_regex(
            (r'style="z-index: [0-9]+;">([^<]+)',
             r'([^<]+)	',
             r'h4-fine[^>]*>([^<]+)<',
             r'>Watch (.+)[ <]',
             r'
([^<]+)
',
             r'
]*>([^<]+)<',  # streamin.to
             r'title\s*:\s*"([^"]+)"'),  # govid.me
            webpage, 'title', default=None) or self._og_search_title(
            webpage, default=None) or video_id).strip()

        for regex, func in (
                (r'(eval\(function\(p,a,c,k,e,d\){.+)', decode_packed_codes),
                (r'(ﾟ.+)', aa_decode)):
            obf_code = self._search_regex(regex, webpage, 'obfuscated code', default=None)
            if obf_code:
                webpage = webpage.replace(obf_code, func(obf_code))

        formats = []

        jwplayer_data = self._search_regex(
            [
                r'jwplayer\("[^"]+"\)\.load\(\[({.+?})\]\);',
                r'jwplayer\("[^"]+"\)\.setup\(({.+?})\);',
            ], webpage,
            'jwplayer data', default=None)
        if jwplayer_data:
            jwplayer_data = self._parse_json(
                jwplayer_data.replace(r"\'", "'"), video_id, js_to_json)
            if jwplayer_data:
                formats = self._parse_jwplayer_data(
                    jwplayer_data, video_id, False,
                    m3u8_id='hls', mpd_id='dash')['formats']

        if not formats:
            urls = []
            for regex in (
                    r'(?:file|src)\s*:\s*(["\'])(?P<url>http(?:(?!\1).)+\.(?:m3u8|mp4|flv)(?:(?!\1).)*)\1',
                    r'file_link\s*=\s*(["\'])(?P<url>http(?:(?!\1).)+)\1',
                    r'addVariable\((\\?["\'])file\1\s*,\s*(\\?["\'])(?P<url>http(?:(?!\2).)+)\2\)',
                    r'<embed[^>]+src=(["\'])(?P<url>http(?:(?!\1).)+\.(?:m3u8|mp4|flv)(?:(?!\1).)*)\1'):
                for mobj in re.finditer(regex, webpage):
                    video_url = mobj.group('url')
                    if video_url not in urls:
                        urls.append(video_url)

            sources = self._search_regex(
                r'sources\s*:\s*(\[(?!{)[^\]]+\])', webpage, 'sources', default=None)
            if sources:
                urls.extend(self._parse_json(sources, video_id))

            formats = []
            for video_url in urls:
                if determine_ext(video_url) == 'm3u8':
                    formats.extend(self._extract_m3u8_formats(
                        video_url, video_id, 'mp4',
                        entry_protocol='m3u8_native', m3u8_id='hls',
                        fatal=False))
                else:
                    formats.append({
                        'url': video_url,
                        'format_id': 'sd',
                    })
        self._sort_formats(formats)

        thumbnail = self._search_regex(
            [
                r'<video[^>]+poster="([^"]+)"',
                r'(?:image|poster)\s*:\s*["\'](http[^"\']+)["\'],',
            ], webpage, 'thumbnail', default=None)

        return {
            'id': video_id,
            'title': title,
            'thumbnail': thumbnail,
            'formats': formats,
        }


code:
from __future__ import unicode_literals

import itertools
import re

from .common import InfoExtractor
from ..compat import compat_str
from ..utils import (
    clean_html,
    determine_ext,
    dict_get,
    extract_attributes,
    ExtractorError,
    int_or_none,
    parse_duration,
    try_get,
    unified_strdate,
    url_or_none,
)

class XHamsterIE(InfoExtractor):
    _DOMAINS = r'(?:xhamster\.(?:com|one|desi)|xhms\.pro|xhamster\d+\.com)'
    _VALID_URL = r'''(?x)
                    https?://
                        (?:.+?\.)?%s/
                        (?:
                            movies/(?P<id>[\dA-Za-z]+)/(?P<display_id>[^/]*)\.html|
                            videos/(?P<display_id_2>[^/]*)-(?P<id_2>[\dA-Za-z]+)
                        )
                    ''' % _DOMAINS
    _TESTS = [{
        'url': 'https://xhamster.com/videos/femaleagent-shy-beauty-takes-the-bait-1509445',
        'md5': '98b4687efb1ffd331c4197854dc09e8f',
        'info_dict': {
            'id': '1509445',
            'display_id': 'femaleagent-shy-beauty-takes-the-bait',
            'ext': 'mp4',
            'title': 'FemaleAgent Shy beauty takes the bait',
            'timestamp': 1350194821,
            'upload_date': '20121014',
            'uploader': 'Ruseful2011',
            'duration': 893,
            'age_limit': 18,
        },
    }, {
        'url': 'https://xhamster.com/videos/britney-spears-sexy-booty-2221348?hd=',
        'info_dict': {
            'id': '2221348',
            'display_id': 'britney-spears-sexy-booty',
            'ext': 'mp4',
            'title': 'Britney Spears  Sexy Booty',
            'timestamp': 1379123460,
            'upload_date': '20130914',
            'uploader': 'jojo747400',
            'duration': 200,
            'age_limit': 18,
        },
        'params': {
            'skip_download': True,
        },
    }, {
        # empty seo, unavailable via new URL schema
        'url': 'http://xhamster.com/movies/5667973/.html',
        'info_dict': {
            'id': '5667973',
            'ext': 'mp4',
            'title': '....',
            'timestamp': 1454948101,
            'upload_date': '20160208',
            'uploader': 'parejafree',
            'duration': 72,
            'age_limit': 18,
        },
        'params': {
            'skip_download': True,
        },
    }, {
        # mobile site
        'url': 'https://m.xhamster.com/videos/cute-teen-jacqueline-solo-masturbation-8559111',
        'only_matching': True,
    }, {
        'url': 'https://xhamster.com/movies/2272726/amber_slayed_by_the_knight.html',
        'only_matching': True,
    }, {
        # This video is visible for marcoalfa123456's friends only
        'url': 'https://it.xhamster.com/movies/7263980/la_mia_vicina.html',
        'only_matching': True,
    }, {
        # new URL schema
        'url': 'https://pt.xhamster.com/videos/euro-pedal-pumping-7937821',
        'only_matching': True,
    }, {
        'url': 'https://xhamster.one/videos/femaleagent-shy-beauty-takes-the-bait-1509445',
        'only_matching': True,
    }, {
        'url': 'https://xhamster.desi/videos/femaleagent-shy-beauty-takes-the-bait-1509445',
        'only_matching': True,
    }, {
        'url': 'https://xhamster2.com/videos/femaleagent-shy-beauty-takes-the-bait-1509445',
        'only_matching': True,
    }, {
        'url': 'https://xhamster11.com/videos/femaleagent-shy-beauty-takes-the-bait-1509445',
        'only_matching': True,
    }, {
        'url': 'https://xhamster26.com/videos/femaleagent-shy-beauty-takes-the-bait-1509445',
        'only_matching': True,
    }, {
        'url': 'http://xhamster.com/movies/1509445/femaleagent_shy_beauty_takes_the_bait.html',
        'only_matching': True,
    }, {
        'url': 'http://xhamster.com/movies/2221348/britney_spears_sexy_booty.html?hd',
        'only_matching': True,
    }, {
        'url': 'http://de.xhamster.com/videos/skinny-girl-fucks-herself-hard-in-the-forest-xhnBJZx',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        mobj = re.match(self._VALID_URL, url)
        video_id = mobj.group('id') or mobj.group('id_2')
        display_id = mobj.group('display_id') or mobj.group('display_id_2')

        desktop_url = re.sub(r'^(https?://(?:.+?\.)?)m\.', r'\1', url)
        webpage, urlh = self._download_webpage_handle(desktop_url, video_id)

        error = self._html_search_regex(
            r'
]+id=["\']videoClosed["\'][^>]*>(.+?)
',
            webpage, 'error', default=None)
        if error:
            raise ExtractorError(error, expected=True)

        age_limit = self._rta_search(webpage)

        def get_height(s):
            return int_or_none(self._search_regex(
                r'^(\d+)[pP]', s, 'height', default=None))

        initials = self._parse_json(
            self._search_regex(
                (r'window\.initials\s*=\s*({.+?})\s*;\s*</script>',
                 r'window\.initials\s*=\s*({.+?})\s*;'), webpage, 'initials',
                default='{}'),
            video_id, fatal=False)
        if initials:
            video = initials['videoModel']
            title = video['title']
            formats = []
            for format_id, formats_dict in video['sources'].items():
                if not isinstance(formats_dict, dict):
                    continue
                for quality, format_item in formats_dict.items():
                    if format_id == 'download':
                        # Download link takes some time to be generated,
                        # skipping for now
                        continue
                        if not isinstance(format_item, dict):
                            continue
                        format_url = format_item.get('link')
                        filesize = int_or_none(
                            format_item.get('size'), invscale=1000000)
                    else:
                        format_url = format_item
                        filesize = None
                    format_url = url_or_none(format_url)
                    if not format_url:
                        continue
                    formats.append({
                        'format_id': '%s-%s' % (format_id, quality),
                        'url': format_url,
                        'ext': determine_ext(format_url, 'mp4'),
                        'height': get_height(quality),
                        'filesize': filesize,
                        'http_headers': {
                            'Referer': urlh.geturl(),
                        },
                    })
            self._sort_formats(formats)

            categories_list = video.get('categories')
            if isinstance(categories_list, list):
                categories = []
                for c in categories_list:
                    if not isinstance(c, dict):
                        continue
                    c_name = c.get('name')
                    if isinstance(c_name, compat_str):
                        categories.append(c_name)
            else:
                categories = None

            return {
                'id': video_id,
                'display_id': display_id,
                'title': title,
                'description': video.get('description'),
                'timestamp': int_or_none(video.get('created')),
                'uploader': try_get(
                    video, lambda x: x['author']['name'], compat_str),
                'thumbnail': video.get('thumbURL'),
                'duration': int_or_none(video.get('duration')),
                'view_count': int_or_none(video.get('views')),
                'like_count': int_or_none(try_get(
                    video, lambda x: x['rating']['likes'], int)),
                'dislike_count': int_or_none(try_get(
                    video, lambda x: x['rating']['dislikes'], int)),
                'comment_count': int_or_none(video.get('views')),
                'age_limit': age_limit,
                'categories': categories,
                'formats': formats,
            }

        # Old layout fallback

        title = self._html_search_regex(
            [r'
]*>([^<]+)
',
             r'<meta[^>]+itemprop=".*?caption.*?"[^>]+content="(.+?)"',
             r'<title[^>]*>(.+?)(?:,\s*[^,]*?\s*Porn\s*[^,]*?:\s*xHamster[^<]*| - xHamster\.com)</title>'],
            webpage, 'title')

        formats = []
        format_urls = set()

        sources = self._parse_json(
            self._search_regex(
                r'sources\s*:\s*({.+?})\s*,?\s*\n', webpage, 'sources',
                default='{}'),
            video_id, fatal=False)
        for format_id, format_url in sources.items():
            format_url = url_or_none(format_url)
            if not format_url:
                continue
            if format_url in format_urls:
                continue
            format_urls.add(format_url)
            formats.append({
                'format_id': format_id,
                'url': format_url,
                'height': get_height(format_id),
            })

        video_url = self._search_regex(
            [r'''file\s*:\s*(?P<q>["'])(?P<mp4>.+?)(?P=q)''',
             r'''<a\s+href=(?P<q>["'])(?P<mp4>.+?)(?P=q)\s+class=["']mp4Thumb''',
             r'''<video[^>]+file=(?P<q>["'])(?P<mp4>.+?)(?P=q)[^>]*>'''],
            webpage, 'video url', group='mp4', default=None)
        if video_url and video_url not in format_urls:
            formats.append({
                'url': video_url,
            })

        self._sort_formats(formats)

        # Only a few videos have an description
        mobj = re.search(r'Description: ([^<]+)', webpage)
        description = mobj.group(1) if mobj else None

        upload_date = unified_strdate(self._search_regex(
            r'hint=["\'](\d{4}-\d{2}-\d{2}) \d{2}:\d{2}:\d{2} [A-Z]{3,4}',
            webpage, 'upload date', fatal=False))

        uploader = self._html_search_regex(
            r']+itemprop=["\']author[^>]+>]+>]+>([^<]+)',
            webpage, 'uploader', default='anonymous')

        thumbnail = self._search_regex(
            [r'''["']thumbUrl["']\s*:\s*(?P<q>["'])(?P<thumbnail>.+?)(?P=q)''',
             r'''<video[^>]+"poster"=(?P<q>["'])(?P<thumbnail>.+?)(?P=q)[^>]*>'''],
            webpage, 'thumbnail', fatal=False, group='thumbnail')

        duration = parse_duration(self._search_regex(
            [r'<[^<]+\bitemprop=["\']duration["\'][^<]+\bcontent=["\'](.+?)["\']',
             r'Runtime:\s*\s*([\d:]+)'], webpage,
            'duration', fatal=False))

        view_count = int_or_none(self._search_regex(
            r'content=["\']User(?:View|Play)s:(\d+)',
            webpage, 'view count', fatal=False))

        mobj = re.search(r'hint=[\'"](?P<likecount>\d+) Likes / (?P<dislikecount>\d+) Dislikes', webpage)
        (like_count, dislike_count) = (mobj.group('likecount'), mobj.group('dislikecount')) if mobj else (None, None)

        mobj = re.search(r'Comments \((?P<commentcount>\d+)\)
', webpage)
        comment_count = mobj.group('commentcount') if mobj else 0

        categories_html = self._search_regex(
            r'(?s)<table.+?(Categories:.+?)
', webpage,
            'categories', default=None)
        categories = [clean_html(category) for category in re.findall(
            r']+>(.+?)', categories_html)] if categories_html else None

        return {
            'id': video_id,
            'display_id': display_id,
            'title': title,
            'description': description,
            'upload_date': upload_date,
            'uploader': uploader,
            'thumbnail': thumbnail,
            'duration': duration,
            'view_count': view_count,
            'like_count': int_or_none(like_count),
            'dislike_count': int_or_none(dislike_count),
            'comment_count': int_or_none(comment_count),
            'age_limit': age_limit,
            'categories': categories,
            'formats': formats,
        }

class XHamsterEmbedIE(InfoExtractor):
    _VALID_URL = r'https?://(?:.+?\.)?%s/xembed\.php\?video=(?P<id>\d+)' % XHamsterIE._DOMAINS
    _TEST = {
        'url': 'http://xhamster.com/xembed.php?video=3328539',
        'info_dict': {
            'id': '3328539',
            'ext': 'mp4',
            'title': 'Pen Masturbation',
            'timestamp': 1406581861,
            'upload_date': '20140728',
            'uploader': 'ManyakisArt',
            'duration': 5,
            'age_limit': 18,
        }
    }

    @staticmethod
    def _extract_urls(webpage):
        return [url for _, url in re.findall(
            r']+?src=(["\'])(?P<url>(?:https?:)?//(?:www\.)?xhamster\.com/xembed\.php\?video=\d+)\1',
            webpage)]

    def _real_extract(self, url):
        video_id = self._match_id(url)

        webpage = self._download_webpage(url, video_id)

        video_url = self._search_regex(
            r'href="(https?://xhamster\.com/(?:movies/{0}/[^"]*\.html|videos/[^/]*-{0})[^"]*)"'.format(video_id),
            webpage, 'xhamster url', default=None)

        if not video_url:
            vars = self._parse_json(
                self._search_regex(r'vars\s*:\s*({.+?})\s*,\s*\n', webpage, 'vars'),
                video_id)
            video_url = dict_get(vars, ('downloadLink', 'homepageLink', 'commentsLink', 'shareUrl'))

        return self.url_result(video_url, 'XHamster')

class XHamsterUserIE(InfoExtractor):
    _VALID_URL = r'https?://(?:.+?\.)?%s/users/(?P<id>[^/?#&]+)' % XHamsterIE._DOMAINS
    _TESTS = [{
        # Paginated user profile
        'url': 'https://xhamster.com/users/netvideogirls/videos',
        'info_dict': {
            'id': 'netvideogirls',
        },
        'playlist_mincount': 267,
    }, {
        # Non-paginated user profile
        'url': 'https://xhamster.com/users/firatkaan/videos',
        'info_dict': {
            'id': 'firatkaan',
        },
        'playlist_mincount': 1,
    }]

    def _entries(self, user_id):
        next_page_url = 'https://xhamster.com/users/%s/videos/1' % user_id
        for pagenum in itertools.count(1):
            page = self._download_webpage(
                next_page_url, user_id, 'Downloading page %s' % pagenum)
            for video_tag in re.findall(
                    r'(]+class=["\'].*?\bvideo-thumb__image-container[^>]+>)',
                    page):
                video = extract_attributes(video_tag)
                video_url = url_or_none(video.get('href'))
                if not video_url or not XHamsterIE.suitable(video_url):
                    continue
                video_id = XHamsterIE._match_id(video_url)
                yield self.url_result(
                    video_url, ie=XHamsterIE.ie_key(), video_id=video_id)
            mobj = re.search(r']+data-page=["\']next[^>]+>', page)
            if not mobj:
                break
            next_page = extract_attributes(mobj.group(0))
            next_page_url = url_or_none(next_page.get('href'))
            if not next_page_url:
                break

    def _real_extract(self, url):
        user_id = self._match_id(url)
        return self.playlist_result(self._entries(user_id), user_id)


code:
# coding: utf-8
from __future__ import unicode_literals

from .common import InfoExtractor
from ..compat import compat_urllib_parse_unquote
from ..utils import int_or_none

class XiamiBaseIE(InfoExtractor):
    _API_BASE_URL = 'https://emumo.xiami.com/song/playlist/cat/json/id'

    def _download_webpage_handle(self, *args, **kwargs):
        webpage = super(XiamiBaseIE, self)._download_webpage_handle(*args, **kwargs)
        if '>Xiami is currently not available in your country.<' in webpage:
            self.raise_geo_restricted('Xiami is currently not available in your country')
        return webpage

    def _extract_track(self, track, track_id=None):
        track_name = track.get('songName') or track.get('name') or track['subName']
        artist = track.get('artist') or track.get('artist_name') or track.get('singers')
        title = '%s - %s' % (artist, track_name) if artist else track_name
        track_url = self._decrypt(track['location'])

        subtitles = {}
        lyrics_url = track.get('lyric_url') or track.get('lyric')
        if lyrics_url and lyrics_url.startswith('http'):
            subtitles['origin'] = [{'url': lyrics_url}]

        return {
            'id': track.get('song_id') or track_id,
            'url': track_url,
            'title': title,
            'thumbnail': track.get('pic') or track.get('album_pic'),
            'duration': int_or_none(track.get('length')),
            'creator': track.get('artist', '').split(';')[0],
            'track': track_name,
            'track_number': int_or_none(track.get('track')),
            'album': track.get('album_name') or track.get('title'),
            'artist': artist,
            'subtitles': subtitles,
        }

    def _extract_tracks(self, item_id, referer, typ=None):
        playlist = self._download_json(
            '%s/%s%s' % (self._API_BASE_URL, item_id, '/type/%s' % typ if typ else ''),
            item_id, headers={
                'Referer': referer,
            })
        return [
            self._extract_track(track, item_id)
            for track in playlist['data']['trackList']]

    @staticmethod
    def _decrypt(origin):
        n = int(origin[0])
        origin = origin[1:]
        short_lenth = len(origin) // n
        long_num = len(origin) - short_lenth * n
        l = tuple()
        for i in range(0, n):
            length = short_lenth
            if i < long_num:
                length += 1
            l += (origin[0:length], )
            origin = origin[length:]
        ans = ''
        for i in range(0, short_lenth + 1):
            for j in range(0, n):
                if len(l[j]) > i:
                    ans += l[j][i]
        return compat_urllib_parse_unquote(ans).replace('^', '0')

class XiamiSongIE(XiamiBaseIE):
    IE_NAME = 'xiami:song'
    IE_DESC = '虾米音乐'
    _VALID_URL = r'https?://(?:www\.)?xiami\.com/song/(?P<id>[^/?#&]+)'
    _TESTS = [{
        'url': 'http://www.xiami.com/song/1775610518',
        'md5': '521dd6bea40fd5c9c69f913c232cb57e',
        'info_dict': {
            'id': '1775610518',
            'ext': 'mp3',
            'title': 'HONNE - Woman',
            'thumbnail': r're:http://img\.xiami\.net/images/album/.*\.jpg',
            'duration': 265,
            'creator': 'HONNE',
            'track': 'Woman',
            'album': 'Woman',
            'artist': 'HONNE',
            'subtitles': {
                'origin': [{
                    'ext': 'lrc',
                }],
            },
        },
        'skip': 'Georestricted',
    }, {
        'url': 'http://www.xiami.com/song/1775256504',
        'md5': '932a3abd45c6aa2b1fdbe028fcb4c4fc',
        'info_dict': {
            'id': '1775256504',
            'ext': 'mp3',
            'title': '戴荃 - 悟空',
            'thumbnail': r're:http://img\.xiami\.net/images/album/.*\.jpg',
            'duration': 200,
            'creator': '戴荃',
            'track': '悟空',
            'album': '悟空',
            'artist': '戴荃',
            'subtitles': {
                'origin': [{
                    'ext': 'lrc',
                }],
            },
        },
        'skip': 'Georestricted',
    }, {
        'url': 'http://www.xiami.com/song/1775953850',
        'info_dict': {
            'id': '1775953850',
            'ext': 'mp3',
            'title': 'До Скону - Чума Пожирает Землю',
            'thumbnail': r're:http://img\.xiami\.net/images/album/.*\.jpg',
            'duration': 683,
            'creator': 'До Скону',
            'track': 'Чума Пожирает Землю',
            'track_number': 7,
            'album': 'Ад',
            'artist': 'До Скону',
        },
        'params': {
            'skip_download': True,
        },
    }, {
        'url': 'http://www.xiami.com/song/xLHGwgd07a1',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        return self._extract_tracks(self._match_id(url), url)[0]

class XiamiPlaylistBaseIE(XiamiBaseIE):
    def _real_extract(self, url):
        item_id = self._match_id(url)
        return self.playlist_result(self._extract_tracks(item_id, url, self._TYPE), item_id)

class XiamiAlbumIE(XiamiPlaylistBaseIE):
    IE_NAME = 'xiami:album'
    IE_DESC = '虾米音乐 - 专辑'
    _VALID_URL = r'https?://(?:www\.)?xiami\.com/album/(?P<id>[^/?#&]+)'
    _TYPE = '1'
    _TESTS = [{
        'url': 'http://www.xiami.com/album/2100300444',
        'info_dict': {
            'id': '2100300444',
        },
        'playlist_count': 10,
        'skip': 'Georestricted',
    }, {
        'url': 'http://www.xiami.com/album/512288?spm=a1z1s.6843761.1110925389.6.hhE9p9',
        'only_matching': True,
    }, {
        'url': 'http://www.xiami.com/album/URVDji2a506',
        'only_matching': True,
    }]

class XiamiArtistIE(XiamiPlaylistBaseIE):
    IE_NAME = 'xiami:artist'
    IE_DESC = '虾米音乐 - 歌手'
    _VALID_URL = r'https?://(?:www\.)?xiami\.com/artist/(?P<id>[^/?#&]+)'
    _TYPE = '2'
    _TESTS = [{
        'url': 'http://www.xiami.com/artist/2132?spm=0.0.0.0.dKaScp',
        'info_dict': {
            'id': '2132',
        },
        'playlist_count': 20,
        'skip': 'Georestricted',
    }, {
        'url': 'http://www.xiami.com/artist/bC5Tk2K6eb99',
        'only_matching': True,
    }]

class XiamiCollectionIE(XiamiPlaylistBaseIE):
    IE_NAME = 'xiami:collection'
    IE_DESC = '虾米音乐 - 精选集'
    _VALID_URL = r'https?://(?:www\.)?xiami\.com/collect/(?P<id>[^/?#&]+)'
    _TYPE = '3'
    _TEST = {
        'url': 'http://www.xiami.com/collect/156527391?spm=a1z1s.2943601.6856193.12.4jpBnr',
        'info_dict': {
            'id': '156527391',
        },
        'playlist_mincount': 29,
        'skip': 'Georestricted',
    }


code:
# coding: utf-8

from __future__ import unicode_literals

import itertools
import re

from .common import InfoExtractor

class XimalayaBaseIE(InfoExtractor):
    _GEO_COUNTRIES = ['CN']

class XimalayaIE(XimalayaBaseIE):
    IE_NAME = 'ximalaya'
    IE_DESC = '喜马拉雅FM'
    _VALID_URL = r'https?://(?:www\.|m\.)?ximalaya\.com/(?P<uid>[0-9]+)/sound/(?P<id>[0-9]+)'
    _USER_URL_FORMAT = '%s://www.ximalaya.com/zhubo/%i/'
    _TESTS = [
        {
            'url': 'http://www.ximalaya.com/61425525/sound/47740352/',
            'info_dict': {
                'id': '47740352',
                'ext': 'm4a',
                'uploader': '小彬彬爱听书',
                'uploader_id': 61425525,
                'uploader_url': 'http://www.ximalaya.com/zhubo/61425525/',
                'title': '261.唐诗三百首.卷八.送孟浩然之广陵.李白',
                'description': "contains:《送孟浩然之广陵》\n作者：李白\n故人西辞黄鹤楼，烟花三月下扬州。\n孤帆远影碧空尽，惟见长江天际流。",
                'thumbnails': [
                    {
                        'name': 'cover_url',
                        'url': r're:^https?://.*\.jpg$',
                    },
                    {
                        'name': 'cover_url_142',
                        'url': r're:^https?://.*\.jpg$',
                        'width': 180,
                        'height': 180
                    }
                ],
                'categories': ['renwen', '人文'],
                'duration': 93,
                'view_count': int,
                'like_count': int,
            }
        },
        {
            'url': 'http://m.ximalaya.com/61425525/sound/47740352/',
            'info_dict': {
                'id': '47740352',
                'ext': 'm4a',
                'uploader': '小彬彬爱听书',
                'uploader_id': 61425525,
                'uploader_url': 'http://www.ximalaya.com/zhubo/61425525/',
                'title': '261.唐诗三百首.卷八.送孟浩然之广陵.李白',
                'description': "contains:《送孟浩然之广陵》\n作者：李白\n故人西辞黄鹤楼，烟花三月下扬州。\n孤帆远影碧空尽，惟见长江天际流。",
                'thumbnails': [
                    {
                        'name': 'cover_url',
                        'url': r're:^https?://.*\.jpg$',
                    },
                    {
                        'name': 'cover_url_142',
                        'url': r're:^https?://.*\.jpg$',
                        'width': 180,
                        'height': 180
                    }
                ],
                'categories': ['renwen', '人文'],
                'duration': 93,
                'view_count': int,
                'like_count': int,
            }
        },
        {
            'url': 'https://www.ximalaya.com/11045267/sound/15705996/',
            'info_dict': {
                'id': '15705996',
                'ext': 'm4a',
                'uploader': '李延隆老师',
                'uploader_id': 11045267,
                'uploader_url': 'https://www.ximalaya.com/zhubo/11045267/',
                'title': 'Lesson 1 Excuse me!',
                'description': "contains:Listen to the tape then answer\xa0this question. Whose handbag is it?\n"
                               "听录音，然后回答问题，这是谁的手袋？",
                'thumbnails': [
                    {
                        'name': 'cover_url',
                        'url': r're:^https?://.*\.jpg$',
                    },
                    {
                        'name': 'cover_url_142',
                        'url': r're:^https?://.*\.jpg$',
                        'width': 180,
                        'height': 180
                    }
                ],
                'categories': ['train', '外语'],
                'duration': 40,
                'view_count': int,
                'like_count': int,
            }
        },
    ]

    def _real_extract(self, url):

        is_m = 'm.ximalaya' in url
        scheme = 'https' if url.startswith('https') else 'http'

        audio_id = self._match_id(url)
        webpage = self._download_webpage(url, audio_id,
                                         note='Download sound page for %s' % audio_id,
                                         errnote='Unable to get sound page')

        audio_info_file = '%s://m.ximalaya.com/tracks/%s.json' % (scheme, audio_id)
        audio_info = self._download_json(audio_info_file, audio_id,
                                         'Downloading info json %s' % audio_info_file,
                                         'Unable to download info file')

        formats = []
        for bps, k in (('24k', 'play_path_32'), ('64k', 'play_path_64')):
            if audio_info.get(k):
                formats.append({
                    'format_id': bps,
                    'url': audio_info[k],
                })

        thumbnails = []
        for k in audio_info.keys():
            # cover pics kyes like: cover_url', 'cover_url_142'
            if k.startswith('cover_url'):
                thumbnail = {'name': k, 'url': audio_info[k]}
                if k == 'cover_url_142':
                    thumbnail['width'] = 180
                    thumbnail['height'] = 180
                thumbnails.append(thumbnail)

        audio_uploader_id = audio_info.get('uid')

        if is_m:
            audio_description = self._html_search_regex(r'(?s)
]+>(.+?)
',
                                                        webpage, 'audio_description', fatal=False)
        else:
            audio_description = self._html_search_regex(r'(?s)
]*>(.+?
)',
                                                        webpage, 'audio_description', fatal=False)

        if not audio_description:
            audio_description_file = '%s://www.ximalaya.com/sounds/%s/rich_intro' % (scheme, audio_id)
            audio_description = self._download_webpage(audio_description_file, audio_id,
                                                       note='Downloading description file %s' % audio_description_file,
                                                       errnote='Unable to download descrip file',
                                                       fatal=False)
            audio_description = audio_description.strip() if audio_description else None

        return {
            'id': audio_id,
            'uploader': audio_info.get('nickname'),
            'uploader_id': audio_uploader_id,
            'uploader_url': self._USER_URL_FORMAT % (scheme, audio_uploader_id) if audio_uploader_id else None,
            'title': audio_info['title'],
            'thumbnails': thumbnails,
            'description': audio_description,
            'categories': list(filter(None, (audio_info.get('category_name'), audio_info.get('category_title')))),
            'duration': audio_info.get('duration'),
            'view_count': audio_info.get('play_count'),
            'like_count': audio_info.get('favorites_count'),
            'formats': formats,
        }

class XimalayaAlbumIE(XimalayaBaseIE):
    IE_NAME = 'ximalaya:album'
    IE_DESC = '喜马拉雅FM 专辑'
    _VALID_URL = r'https?://(?:www\.|m\.)?ximalaya\.com/(?P<uid>[0-9]+)/album/(?P<id>[0-9]+)'
    _TEMPLATE_URL = '%s://www.ximalaya.com/%s/album/%s/'
    _BASE_URL_TEMPL = '%s://www.ximalaya.com%s'
    _LIST_VIDEO_RE = r']+?href="(?P<url>/%s/sound/(?P<id>\d+)/?)"[^>]+?title="(?P<title>[^>]+)">'
    _TESTS = [{
        'url': 'http://www.ximalaya.com/61425525/album/5534601/',
        'info_dict': {
            'title': '唐诗三百首（含赏析）',
            'id': '5534601',
        },
        'playlist_count': 312,
    }, {
        'url': 'http://m.ximalaya.com/61425525/album/5534601',
        'info_dict': {
            'title': '唐诗三百首（含赏析）',
            'id': '5534601',
        },
        'playlist_count': 312,
    },
    ]

    def _real_extract(self, url):
        self.scheme = scheme = 'https' if url.startswith('https') else 'http'

        mobj = re.match(self._VALID_URL, url)
        uid, playlist_id = mobj.group('uid'), mobj.group('id')

        webpage = self._download_webpage(self._TEMPLATE_URL % (scheme, uid, playlist_id), playlist_id,
                                         note='Download album page for %s' % playlist_id,
                                         errnote='Unable to get album info')

        title = self._html_search_regex(r'detailContent_title[^>]*>
]+)?>([^<]+)
',
                                        webpage, 'title', fatal=False)

        return self.playlist_result(self._entries(webpage, playlist_id, uid), playlist_id, title)

    def _entries(self, page, playlist_id, uid):
        html = page
        for page_num in itertools.count(1):
            for entry in self._process_page(html, uid):
                yield entry

            next_url = self._search_regex(r'<a\s+href=(["\'])(?P<more>[\S]+)\1[^>]+rel=(["\'])next\3',
                                          html, 'list_next_url', default=None, group='more')
            if not next_url:
                break

            next_full_url = self._BASE_URL_TEMPL % (self.scheme, next_url)
            html = self._download_webpage(next_full_url, playlist_id)

    def _process_page(self, html, uid):
        find_from = html.index('album_soundlist')
        for mobj in re.finditer(self._LIST_VIDEO_RE % uid, html[find_from:]):
            yield self.url_result(self._BASE_URL_TEMPL % (self.scheme, mobj.group('url')),
                                  XimalayaIE.ie_key(),
                                  mobj.group('id'),
                                  mobj.group('title'))


code:
# coding: utf-8
from __future__ import unicode_literals

import re
import time

from .common import InfoExtractor
from ..compat import (
    compat_ord,
)
from ..utils import (
    int_or_none,
    parse_duration,
)

class XMinusIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?x-minus\.org/track/(?P<id>[0-9]+)'
    _TEST = {
        'url': 'http://x-minus.org/track/4542/%D0%BF%D0%B5%D1%81%D0%B5%D0%BD%D0%BA%D0%B0-%D1%88%D0%BE%D1%84%D0%B5%D1%80%D0%B0.html',
        'md5': '401a15f2d2dcf6d592cb95528d72a2a8',
        'info_dict': {
            'id': '4542',
            'ext': 'mp3',
            'title': 'Леонид Агутин-Песенка шофёра',
            'duration': 156,
            'tbr': 320,
            'filesize_approx': 5900000,
            'view_count': int,
            'description': 'md5:03238c5b663810bc79cf42ef3c03e371',
        }
    }

    def _real_extract(self, url):
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)

        artist = self._html_search_regex(
            r']+href="/artist/\d+">([^<]+)', webpage, 'artist')
        title = artist + '-' + self._html_search_regex(
            r']+class="minustrack-full-title(?:\s+[^"]+)?"[^>]*>([^<]+)', webpage, 'title')
        duration = parse_duration(self._html_search_regex(
            r']+class="player-duration(?:\s+[^"]+)?"[^>]*>([^<]+)',
            webpage, 'duration', fatal=False))
        mobj = re.search(
            r'
]+class="dw-info(?:\s+[^"]+)?"[^>]*>(?P<tbr>\d+)\s*кбит/c\s+(?P<filesize>[0-9.]+)\s*мб
',
            webpage)
        tbr = filesize_approx = None
        if mobj:
            filesize_approx = float(mobj.group('filesize')) * 1000000
            tbr = float(mobj.group('tbr'))
        view_count = int_or_none(self._html_search_regex(
            r'<[^>]+class="icon-chart-bar".*?>(\d+)',
            webpage, 'view count', fatal=False))
        description = self._html_search_regex(
            r'(?s)
]+id="lyrics-original"[^>]*>(.*?)
',
            webpage, 'song lyrics', fatal=False)
        if description:
            description = re.sub(' *\r *', '\n', description)

        k = self._search_regex(
            r'
]+id="player-bottom"[^>]+data-k="([^"]+)">', webpage,
            'encoded data')
        h = time.time() / 3600
        a = sum(map(int, [compat_ord(c) for c in k])) + int(video_id) + h
        video_url = 'http://x-minus.me/dl/minus?id=%s&tkn2=%df%d' % (video_id, a, h)

        return {
            'id': video_id,
            'title': title,
            'url': video_url,
            # The extension is unknown until actual downloading
            'ext': 'mp3',
            'duration': duration,
            'filesize_approx': filesize_approx,
            'tbr': tbr,
            'view_count': view_count,
            'description': description,
        }


code:
# coding: utf-8
from __future__ import unicode_literals

import re

from .common import InfoExtractor
from ..utils import (
    determine_ext,
    int_or_none,
    NO_DEFAULT,
    str_to_int,
)

class XNXXIE(InfoExtractor):
    _VALID_URL = r'https?://(?:video|www)\.xnxx\.com/video-?(?P<id>[0-9a-z]+)/'
    _TESTS = [{
        'url': 'http://www.xnxx.com/video-55awb78/skyrim_test_video',
        'md5': '7583e96c15c0f21e9da3453d9920fbba',
        'info_dict': {
            'id': '55awb78',
            'ext': 'mp4',
            'title': 'Skyrim Test Video',
            'thumbnail': r're:^https?://.*\.jpg',
            'duration': 469,
            'view_count': int,
            'age_limit': 18,
        },
    }, {
        'url': 'http://video.xnxx.com/video1135332/lida_naked_funny_actress_5_',
        'only_matching': True,
    }, {
        'url': 'http://www.xnxx.com/video-55awb78/',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)

        webpage = self._download_webpage(url, video_id)

        def get(meta, default=NO_DEFAULT, fatal=True):
            return self._search_regex(
                r'set%s\s*\(\s*(["\'])(?P<value>(?:(?!\1).)+)\1' % meta,
                webpage, meta, default=default, fatal=fatal, group='value')

        title = self._og_search_title(
            webpage, default=None) or get('VideoTitle')

        formats = []
        for mobj in re.finditer(
                r'setVideo(?:Url(?P<id>Low|High)|HLS)\s*\(\s*(?P<q>["\'])(?P<url>(?:https?:)?//.+?)(?P=q)', webpage):
            format_url = mobj.group('url')
            if determine_ext(format_url) == 'm3u8':
                formats.extend(self._extract_m3u8_formats(
                    format_url, video_id, 'mp4', entry_protocol='m3u8_native',
                    preference=1, m3u8_id='hls', fatal=False))
            else:
                format_id = mobj.group('id')
                if format_id:
                    format_id = format_id.lower()
                formats.append({
                    'url': format_url,
                    'format_id': format_id,
                    'quality': -1 if format_id == 'low' else 0,
                })
        self._sort_formats(formats)

        thumbnail = self._og_search_thumbnail(webpage, default=None) or get(
            'ThumbUrl', fatal=False) or get('ThumbUrl169', fatal=False)
        duration = int_or_none(self._og_search_property('duration', webpage))
        view_count = str_to_int(self._search_regex(
            r'id=["\']nb-views-number[^>]+>([\d,.]+)', webpage, 'view count',
            default=None))

        return {
            'id': video_id,
            'title': title,
            'thumbnail': thumbnail,
            'duration': duration,
            'view_count': view_count,
            'age_limit': 18,
            'formats': formats,
        }


code:
# coding: utf-8
from __future__ import unicode_literals

import re

from .common import InfoExtractor
from ..utils import (
    int_or_none,
    parse_iso8601,
    xpath_with_ns,
    xpath_text,
    find_xpath_attr,
)

class XstreamIE(InfoExtractor):
    _VALID_URL = r'''(?x)
                    (?:
                        xstream:|
                        https?://frontend\.xstream\.(?:dk|net)/
                    )
                    (?P<partner_id>[^/]+)
                    (?:
                        :|
                        /feed/video/\?.*?\bid=
                    )
                    (?P<id>\d+)
                    '''
    _TESTS = [{
        'url': 'http://frontend.xstream.dk/btno/feed/video/?platform=web&id=86588',
        'md5': 'd7d17e3337dc80de6d3a540aefbe441b',
        'info_dict': {
            'id': '86588',
            'ext': 'mov',
            'title': 'Otto Wollertsen',
            'description': 'Vestlendingen Otto Fredrik Wollertsen',
            'timestamp': 1430473209,
            'upload_date': '20150501',
        },
    }, {
        'url': 'http://frontend.xstream.dk/ap/feed/video/?platform=web&id=21039',
        'only_matching': True,
    }]

    def _extract_video_info(self, partner_id, video_id):
        data = self._download_xml(
            'http://frontend.xstream.dk/%s/feed/video/?platform=web&id=%s'
            % (partner_id, video_id),
            video_id)

        NS_MAP = {
            'atom': 'http://www.w3.org/2005/Atom',
            'xt': 'http://xstream.dk/',
            'media': 'http://search.yahoo.com/mrss/',
        }

        entry = data.find(xpath_with_ns('./atom:entry', NS_MAP))

        title = xpath_text(
            entry, xpath_with_ns('./atom:title', NS_MAP), 'title')
        description = xpath_text(
            entry, xpath_with_ns('./atom:summary', NS_MAP), 'description')
        timestamp = parse_iso8601(xpath_text(
            entry, xpath_with_ns('./atom:published', NS_MAP), 'upload date'))

        formats = []
        media_group = entry.find(xpath_with_ns('./media:group', NS_MAP))
        for media_content in media_group.findall(xpath_with_ns('./media:content', NS_MAP)):
            media_url = media_content.get('url')
            if not media_url:
                continue
            tbr = int_or_none(media_content.get('bitrate'))
            mobj = re.search(r'^(?P<url>rtmp://[^/]+/(?P<app>[^/]+))/(?P<playpath>.+)$', media_url)
            if mobj:
                formats.append({
                    'url': mobj.group('url'),
                    'play_path': 'mp4:%s' % mobj.group('playpath'),
                    'app': mobj.group('app'),
                    'ext': 'flv',
                    'tbr': tbr,
                    'format_id': 'rtmp-%d' % tbr,
                })
            else:
                formats.append({
                    'url': media_url,
                    'tbr': tbr,
                })
        self._sort_formats(formats)

        link = find_xpath_attr(
            entry, xpath_with_ns('./atom:link', NS_MAP), 'rel', 'original')
        if link is not None:
            formats.append({
                'url': link.get('href'),
                'format_id': link.get('rel'),
                'preference': 1,
            })

        thumbnails = [{
            'url': splash.get('url'),
            'width': int_or_none(splash.get('width')),
            'height': int_or_none(splash.get('height')),
        } for splash in media_group.findall(xpath_with_ns('./xt:splash', NS_MAP))]

        return {
            'id': video_id,
            'title': title,
            'description': description,
            'timestamp': timestamp,
            'formats': formats,
            'thumbnails': thumbnails,
        }

    def _real_extract(self, url):
        mobj = re.match(self._VALID_URL, url)
        partner_id = mobj.group('partner_id')
        video_id = mobj.group('id')

        return self._extract_video_info(partner_id, video_id)