ronantakizawa/codereview-bench huggingface dataset:
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/volejtv.py (Python)

Code before:
import functools

from .common import InfoExtractor
from ..utils import (
    InAdvancePagedList,
    int_or_none,
    join_nonempty,
    orderedSet,
    str_or_none,
    strftime_or_none,
    traverse_obj,
    unified_timestamp,
    url_or_none,
)


class VolejTVBaseIE(InfoExtractor):
    TBR_HEIGHT_MAPPING = {'6000': 1080, '2400': 720, '1500': 480, '800': 360}

    def _call_api(self, endpoint, display_id, query=None):
        return self._download_json(
            f'https://api-volejtv-prod.apps.okd4.devopsie.cloud/api/{endpoint}', display_id, query=query)


class VolejTVIE(VolejTVBaseIE):
    IE_NAME = 'volejtv:match'
    _VALID_URL = r'https?://volej\.tv/match/(?P<id>\d+)'
    _TESTS = [{
        'url': 'https://volej.tv/match/270579',
        'info_dict': {
            'id': '270579',
            'ext': 'mp4',
            'title': 'SWE-CZE (2024-06-16)',
            'categories': ['ženy'],
            'series': 'ZLATÁ EVROPSKÁ VOLEJBALOVÁ LIGA',
            'season': '2023-2024',
            'timestamp': 1718553600,
            'upload_date': '20240616',

Review comment (suggestion):
```suggestion
    str_or_none,
    strftime_or_none,
    unified_timestamp,
    url_or_none,
)
from ..utils.traversal import require, traverse_obj
```

Code after:
import functools

from .common import InfoExtractor
from ..utils import (
    InAdvancePagedList,
    int_or_none,
    join_nonempty,
    orderedSet,
    str_or_none,
    strftime_or_none,
    unified_timestamp,
    url_or_none,
)
from ..utils.traversal import (
    require,
    traverse_obj,
)


class VolejTVBaseIE(InfoExtractor):
    TBR_HEIGHT_MAPPING = {
        '6000': 1080,
        '2400': 720,
        '1500': 480,
        '800': 360,
    }

    def _call_api(self, endpoint, display_id, query=None):
        return self._download_json(
            f'https://api-volejtv-prod.apps.okd4.devopsie.cloud/api/{endpoint}',
            display_id, query=query)


class VolejTVIE(VolejTVBaseIE):
    IE_NAME = 'volejtv:match'
    _VALID_URL = r'https?://volej\.tv/match/(?P<id>\d+)'
    _TESTS = [{
        'url': 'https://volej.tv/match/270579',
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/picarto.py (Python)

Code before:
import urllib.parse

from .common import InfoExtractor
from ..utils import (
    ExtractorError,
    str_or_none,
    traverse_obj,
    update_url,
)


class PicartoIE(InfoExtractor):
    IE_NAME = 'picarto:base'
    _VALID_URL = r'https?://(?:www.)?picarto\.tv/(?P<id>[^/#?]+)$'
    _TEST = {
        'url': 'https://picarto.tv/Setz',
        'info_dict': {
            'id': 'Setz',
            'ext': 'mp4',
            'title': 're:^Setz [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$',
            'timestamp': int,
            'is_live': True,
        },
        'skip': 'Stream is offline',
    }

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

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

        data = self._download_json(
            'https://ptvintern.picarto.tv/ptvapi', channel_id, query={
                'query': '''{
  channel(name: "%s") {
    adult

Review comment (suggestion):
"base" could be misinterpreted to mean a baseclass
```suggestion
    IE_NAME = 'picarto'
```

Code after:
import urllib.parse

from .common import InfoExtractor
from ..utils import (
    ExtractorError,
    str_or_none,
    traverse_obj,
    update_url,
)


class PicartoIE(InfoExtractor):
    IE_NAME = 'picarto'
    _VALID_URL = r'https?://(?:www.)?picarto\.tv/(?P<id>[^/#?]+)/?(?:$|[?#])'
    _TEST = {
        'url': 'https://picarto.tv/Setz',
        'info_dict': {
            'id': 'Setz',
            'ext': 'mp4',
            'title': 're:^Setz [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$',
            'timestamp': int,
            'is_live': True,
        },
        'skip': 'Stream is offline',
    }

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

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

        data = self._download_json(
            'https://ptvintern.picarto.tv/ptvapi', channel_id, query={
                'query': '''{
  channel(name: "%s") {
    adult
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/picarto.py (Python)

Code before:
import urllib.parse

from .common import InfoExtractor
from ..utils import (
    ExtractorError,
    str_or_none,
    traverse_obj,
    update_url,
)


class PicartoIE(InfoExtractor):
    IE_NAME = 'picarto:base'
    _VALID_URL = r'https?://(?:www.)?picarto\.tv/(?P<id>[^/#?]+)$'
    _TEST = {
        'url': 'https://picarto.tv/Setz',
        'info_dict': {
            'id': 'Setz',
            'ext': 'mp4',
            'title': 're:^Setz [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$',
            'timestamp': int,
            'is_live': True,
        },
        'skip': 'Stream is offline',
    }

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

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

        data = self._download_json(
            'https://ptvintern.picarto.tv/ptvapi', channel_id, query={
                'query': '''{
  channel(name: "%s") {
    adult
    id

Review comment (suggestion):
```suggestion
    _VALID_URL = r'https?://(?:www.)?picarto\.tv/(?P<id>[^/#?]+)/?(?:$|[?#])'
```
any specific reason for changing `[a-zA-Z0-9]+` to `[^/#?]+` ? if you have evidence that the former is insufficent please add an `only_matching` test

Code after:
import urllib.parse

from .common import InfoExtractor
from ..utils import (
    ExtractorError,
    str_or_none,
    traverse_obj,
    update_url,
)


class PicartoIE(InfoExtractor):
    IE_NAME = 'picarto'
    _VALID_URL = r'https?://(?:www.)?picarto\.tv/(?P<id>[^/#?]+)/?(?:$|[?#])'
    _TEST = {
        'url': 'https://picarto.tv/Setz',
        'info_dict': {
            'id': 'Setz',
            'ext': 'mp4',
            'title': 're:^Setz [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$',
            'timestamp': int,
            'is_live': True,
        },
        'skip': 'Stream is offline',
    }

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

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

        data = self._download_json(
            'https://ptvintern.picarto.tv/ptvapi', channel_id, query={
                'query': '''{
  channel(name: "%s") {
    adult
    id
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/picarto.py (Python)

Code before:
import urllib.parse

from .common import InfoExtractor
from ..utils import (
    ExtractorError,
    str_or_none,
    traverse_obj,
    update_url,
)


class PicartoIE(InfoExtractor):
    IE_NAME = 'picarto'
    _VALID_URL = r'https?://(?:www.)?picarto\.tv/(?P<id>[a-zA-Z0-9]+)/?(?:$|[?#])'
    _TEST = {
        'url': 'https://picarto.tv/Setz',
        'info_dict': {
            'id': 'Setz',
            'ext': 'mp4',
            'title': 're:^Setz [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$',
            'timestamp': int,
            'is_live': True,
        },
        'skip': 'Stream is offline',
    }

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

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

        data = self._download_json(
            'https://ptvintern.picarto.tv/ptvapi', channel_id, query={
                'query': '''{
  channel(name: "%s") {
    adult
    id

Review comment (suggestion):
you didn't have to revert to `[a-zA-Z0-9]+`, I was just curious
```suggestion
    _VALID_URL = r'https?://(?:www.)?picarto\.tv/(?P<id>[^/#?]+)/?(?:$|[?#])'
```

Code after:
import urllib.parse

from .common import InfoExtractor
from ..utils import (
    ExtractorError,
    str_or_none,
    traverse_obj,
    update_url,
)


class PicartoIE(InfoExtractor):
    IE_NAME = 'picarto'
    _VALID_URL = r'https?://(?:www.)?picarto\.tv/(?P<id>[^/#?]+)/?(?:$|[?#])'
    _TEST = {
        'url': 'https://picarto.tv/Setz',
        'info_dict': {
            'id': 'Setz',
            'ext': 'mp4',
            'title': 're:^Setz [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$',
            'timestamp': int,
            'is_live': True,
        },
        'skip': 'Stream is offline',
    }

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

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

        data = self._download_json(
            'https://ptvintern.picarto.tv/ptvapi', channel_id, query={
                'query': '''{
  channel(name: "%s") {
    adult
    id
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/toutiao.py (Python)

Code before:
import json
import urllib.parse

from .common import InfoExtractor
from ..utils import (
    float_or_none,
    int_or_none,
    str_or_none,
    url_or_none,
)
from ..utils.traversal import find_element, traverse_obj


class ToutiaoIE(InfoExtractor):
    IE_NAME = 'toutiao'
    IE_DESC = '今日头条'

    _VALID_URL = r'https?://www\.toutiao\.com/video/(?P<id>\d+)([/?#]|$)'
    _TESTS = [{
        'url': 'https://www.toutiao.com/video/7505382061495176511/',
        'info_dict': {
            'id': '7505382061495176511',
            'ext': 'mp4',
            'title': '新疆多地现不明飞行物，目击者称和月亮一样亮，几秒内突然加速消失，气象部门回应',
            'comment_count': int,
            'duration': 9.753,
            'like_count': int,
            'release_date': '20250517',
            'release_timestamp': 1747483344,
            'thumbnail': r're:https?://p\d+-sign\.toutiaoimg\.com/.+$',
            'uploader': '极目新闻',
            'uploader_id': 'MS4wLjABAAAAeateBb9Su8I3MJOZozmvyzWktmba5LMlliRDz1KffnM',
            'view_count': int,
        },
    }, {
        'url': 'https://www.toutiao.com/video/7479446610359878153/',
        'info_dict': {
            'id': '7479446610359878153',
            'ext': 'mp4',
            'title': '小伙竟然利用两块磁铁制作成磁力减震器，简直太有创意了！',
            'comment_count': int,
            'duration': 118.374,
            'like_count': int,

Review comment (suggestion):
Any group in a `_VALID_URL` pattern must be either a named capture group or non-capturing

And I'd imagine we don't want the url path to continue beyond the optional trailing slash
```suggestion
    _VALID_URL = r'https?://www\.toutiao\.com/video/(?P<id>\d+)/?(?:[?#]|$)'
```

Code after:
import json
import urllib.parse

from .common import InfoExtractor
from ..utils import (
    float_or_none,
    int_or_none,
    str_or_none,
    try_call,
    url_or_none,
)
from ..utils.traversal import find_element, traverse_obj


class ToutiaoIE(InfoExtractor):
    IE_NAME = 'toutiao'
    IE_DESC = '今日头条'

    _VALID_URL = r'https?://www\.toutiao\.com/video/(?P<id>\d+)/?(?:[?#]|$)'
    _TESTS = [{
        'url': 'https://www.toutiao.com/video/7505382061495176511/',
        'info_dict': {
            'id': '7505382061495176511',
            'ext': 'mp4',
            'title': '新疆多地现不明飞行物，目击者称和月亮一样亮，几秒内突然加速消失，气象部门回应',
            'comment_count': int,
            'duration': 9.753,
            'like_count': int,
            'release_date': '20250517',
            'release_timestamp': 1747483344,
            'thumbnail': r're:https?://p\d+-sign\.toutiaoimg\.com/.+$',
            'uploader': '极目新闻',
            'uploader_id': 'MS4wLjABAAAAeateBb9Su8I3MJOZozmvyzWktmba5LMlliRDz1KffnM',
            'view_count': int,
        },
    }, {
        'url': 'https://www.toutiao.com/video/7479446610359878153/',
        'info_dict': {
            'id': '7479446610359878153',
            'ext': 'mp4',
            'title': '小伙竟然利用两块磁铁制作成磁力减震器，简直太有创意了！',
            'comment_count': int,
            'duration': 118.374,
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/srmediathek.py (Python)

Code before:
from .ard import ARDMediathekBaseIE
from ..utils import (
    ExtractorError,
    clean_html,
    extract_attributes,
    parse_duration,
    parse_qs,
    unified_strdate,
)
from ..utils.traversal import (
    find_element,
    require,
    traverse_obj,
)


class SRMediathekIE(ARDMediathekBaseIE):
    IE_NAME = 'sr:mediathek'
    IE_DESC = 'Saarländischer Rundfunk'
    CLS_COMMON = 'teaser__image__caption__text teaser__image__caption__text--'

    _VALID_URL = r'https?://(?:www\.)?sr-mediathek\.de/index\.php\?.*?&id=(?P<id>\d+)'
    _TESTS = [{
        'url': 'https://www.sr-mediathek.de/index.php?seite=7&id=141317',
        'info_dict': {
            'id': '141317',
            'ext': 'mp4',
            'title': 'Kärnten, da will ich hin!',
            'channel': 'SR Fernsehen',
            'description': 'md5:7732e71e803379a499732864a572a456',
            'duration': 1788.0,
            'release_date': '20250525',
            'series': 'da will ich hin!',
            'series_id': 'DWIH',
            'thumbnail': r're:https?://.+\.jpg',
        },
    }, {
        'url': 'https://www.sr-mediathek.de/index.php?seite=7&id=153853',
        'info_dict': {
            'id': '153853',
            'ext': 'mp3',
            'title': 'Kappes, Klöße, Kokosmilch: Bruschetta mit Nduja',
            'channel': 'SR 3',
            'description': 'md5:3935798de3562b10c4070b408a15e225',
            'duration': 139.0,

Review comment (suggestion):
```suggestion
    _CLS_COMMON = 'teaser__image__caption__text teaser__image__caption__text--'
```

Code after:
from .ard import ARDMediathekBaseIE
from ..utils import (
    ExtractorError,
    clean_html,
    extract_attributes,
    parse_duration,
    parse_qs,
    unified_strdate,
)
from ..utils.traversal import (
    find_element,
    require,
    traverse_obj,
)


class SRMediathekIE(ARDMediathekBaseIE):
    IE_NAME = 'sr:mediathek'
    IE_DESC = 'Saarländischer Rundfunk'

    _CLS_COMMON = 'teaser__image__caption__text teaser__image__caption__text--'
    _VALID_URL = r'https?://(?:www\.)?sr-mediathek\.de/index\.php\?.*?&id=(?P<id>\d+)'
    _TESTS = [{
        'url': 'https://www.sr-mediathek.de/index.php?seite=7&id=141317',
        'info_dict': {
            'id': '141317',
            'ext': 'mp4',
            'title': 'Kärnten, da will ich hin!',
            'channel': 'SR Fernsehen',
            'description': 'md5:7732e71e803379a499732864a572a456',
            'duration': 1788.0,
            'release_date': '20250525',
            'series': 'da will ich hin!',
            'series_id': 'DWIH',
            'thumbnail': r're:https?://.+\.jpg',
        },
    }, {
        'url': 'https://www.sr-mediathek.de/index.php?seite=7&id=153853',
        'info_dict': {
            'id': '153853',
            'ext': 'mp3',
            'title': 'Kappes, Klöße, Kokosmilch: Bruschetta mit Nduja',
            'channel': 'SR 3',
            'description': 'md5:3935798de3562b10c4070b408a15e225',
            'duration': 139.0,
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/_extractors.py (Python)

Code before:
    NPOIE,
    VPROIE,
    WNLIE,
    AndereTijdenIE,
    HetKlokhuisIE,
    NPOLiveIE,
    NPORadioFragmentIE,
    NPORadioIE,
    SchoolTVIE,
)
from .npr import NprIE
from .nrk import (
    NRKIE,
    NRKTVIE,
    NRKPlaylistIE,
    NRKRadioPodkastIE,
    NRKSkoleIE,
    NRKTVDirekteIE,
    NRKTVEpisodeIE,
    NRKTVEpisodesIE,
    NRKTVSeasonIE,
    NRKTVSeriesIE,
)
from .nrl import NRLTVIE
from .nts import NTSLiveIE
from .ntvcojp import NTVJpCuIE
from .ntvde import NTVDeIE
from .ntvru import NTVRuIE
from .nubilesporn import NubilesPornIE
from .nuum import (
    NuumLiveIE,
    NuumMediaIE,
    NuumTabIE,
)
from .nuvid import NuvidIE
from .nytimes import (
    NYTimesArticleIE,
    NYTimesCookingIE,
    NYTimesCookingRecipeIE,
    NYTimesIE,
)
from .nzherald import NZHeraldIE
from .nzonscreen import NZOnScreenIE
from .nzz import NZZIE
from .odkmedia import OnDemandChinaEpisodeIE
from .odnoklassniki import OdnoklassnikiIE
from .oftv import (
    OfTVIE,
    OfTVPlaylistIE,
)
from .oktoberfesttv import OktoberfestTVIE

Review comment (suggestion):
sorry for causing unnecessary confusion
```suggestion
from .ntvcojp import NTVCoJpCUIE
```

Code after:
    NPOIE,
    VPROIE,
    WNLIE,
    AndereTijdenIE,
    HetKlokhuisIE,
    NPOLiveIE,
    NPORadioFragmentIE,
    NPORadioIE,
    SchoolTVIE,
)
from .npr import NprIE
from .nrk import (
    NRKIE,
    NRKTVIE,
    NRKPlaylistIE,
    NRKRadioPodkastIE,
    NRKSkoleIE,
    NRKTVDirekteIE,
    NRKTVEpisodeIE,
    NRKTVEpisodesIE,
    NRKTVSeasonIE,
    NRKTVSeriesIE,
)
from .nrl import NRLTVIE
from .nts import NTSLiveIE
from .ntvcojp import NTVCoJpCUIE
from .ntvde import NTVDeIE
from .ntvru import NTVRuIE
from .nubilesporn import NubilesPornIE
from .nuum import (
    NuumLiveIE,
    NuumMediaIE,
    NuumTabIE,
)
from .nuvid import NuvidIE
from .nytimes import (
    NYTimesArticleIE,
    NYTimesCookingIE,
    NYTimesCookingRecipeIE,
    NYTimesIE,
)
from .nzherald import NZHeraldIE
from .nzonscreen import NZOnScreenIE
from .nzz import NZZIE
from .odkmedia import OnDemandChinaEpisodeIE
from .odnoklassniki import OdnoklassnikiIE
from .oftv import (
    OfTVIE,
    OfTVPlaylistIE,
)
from .oktoberfesttv import OktoberfestTVIE
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/shiey.py (Python)

Code before:
from .common import InfoExtractor
from .vimeo import VimeoIE


class ShieyIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?shiey\.com/videos/v/(?P<id>[^/]+)'

    _TESTS = [{
        'url': 'https://www.shiey.com/videos/v/train-journey-to-edge-of-serbia-ep-2',
        'info_dict': {
            'id': 'train-journey-to-edge-of-serbia-ep-2',
            'title': 'Train Journey to the Edge of Serbia - Ep. 2',
            'uploader': 'Shiey',
        },
        'params': {
            'skip_download': True,
        },
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)
        vimeo_url = self._search_regex(r'iframe src=\\&quot;(https?://player\.vimeo\.com/video/[^\\&]+)', webpage, 'vimeo url')
        return self.url_result(VimeoIE._smuggle_referrer(vimeo_url, url), VimeoIE)


Review comment (suggestion):
Need to exclude query args or the fragment identifier
```suggestion
    _VALID_URL = r'https?://(?:www\.)?shiey\.com/videos/v/(?P<id>[^/?#]+)'
```

Code after:
import json

from .common import InfoExtractor
from .vimeo import VimeoIE
from ..utils import extract_attributes
from ..utils.traversal import find_element, traverse_obj


class ShieyIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?shiey\.com/videos/v/(?P<id>[^/?#]+)'

    _TESTS = [{
        'url': 'https://www.shiey.com/videos/v/train-journey-to-edge-of-serbia-ep-2',
        'info_dict': {
            'id': '1103409448',
            'ext': 'mp4',
            'title': 'Train Journey To Edge of Serbia (Ep. 2)',
            'uploader': 'shiey',
            'uploader_url': '',
            'duration': 1364,
            'thumbnail': r're:^https?://.+',
        },
        'params': {'skip_download': True},
        'expected_warnings': ['Failed to parse XML: not well-formed'],
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)
        oembed_html = traverse_obj(webpage, (
            {find_element(attr='data-controller', value='VideoEmbed', html=True)},
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/shiey.py (Python)

Code before:
from .common import InfoExtractor
from .vimeo import VimeoIE


class ShieyIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?shiey\.com/videos/v/(?P<id>[^/]+)'

    _TESTS = [{
        'url': 'https://www.shiey.com/videos/v/train-journey-to-edge-of-serbia-ep-2',
        'info_dict': {
            'id': 'train-journey-to-edge-of-serbia-ep-2',
            'title': 'Train Journey to the Edge of Serbia - Ep. 2',
            'uploader': 'Shiey',
        },
        'params': {
            'skip_download': True,
        },
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)
        vimeo_url = self._search_regex(r'iframe src=\\&quot;(https?://player\.vimeo\.com/video/[^\\&]+)', webpage, 'vimeo url')
        return self.url_result(VimeoIE._smuggle_referrer(vimeo_url, url), VimeoIE)


Review comment (bug):
It seems like you never ran the tests...
```suggestion
        'url': 'https://www.shiey.com/videos/v/train-journey-to-edge-of-serbia-ep-2',
        'info_dict': {
            'id': '1103409448',
            'ext': 'mp4',
            'title': 'Train Journey To Edge of Serbia (Ep. 2)',
            'uploader': 'shiey',
            'uploader_url': '',
            'duration': 1364,
            'thumbnail': r're:^https?://.+',
        },
        'params': {'skip_download': True},
        'expected_warnings': ['Failed to parse XML: not well-formed'],
```

Code after:
import json

from .common import InfoExtractor
from .vimeo import VimeoIE
from ..utils import extract_attributes
from ..utils.traversal import find_element, traverse_obj


class ShieyIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?shiey\.com/videos/v/(?P<id>[^/?#]+)'

    _TESTS = [{
        'url': 'https://www.shiey.com/videos/v/train-journey-to-edge-of-serbia-ep-2',
        'info_dict': {
            'id': '1103409448',
            'ext': 'mp4',
            'title': 'Train Journey To Edge of Serbia (Ep. 2)',
            'uploader': 'shiey',
            'uploader_url': '',
            'duration': 1364,
            'thumbnail': r're:^https?://.+',
        },
        'params': {'skip_download': True},
        'expected_warnings': ['Failed to parse XML: not well-formed'],
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)
        oembed_html = traverse_obj(webpage, (
            {find_element(attr='data-controller', value='VideoEmbed', html=True)},
            {extract_attributes}, 'data-config-embed-video', {json.loads}, 'oembedHtml', {str}))

        return self.url_result(VimeoIE._extract_url(url, oembed_html), VimeoIE)