Repository: yt-dlp/yt-dlp

Issue:
[MySpass] ERROR: 'NoneType' object has no attribute 'groups' 
### Checklist

- [X] I'm reporting a bug unrelated to a specific site
- [X] I've verified that I'm running yt-dlp version **2022.01.21**. ([update instructions](https://github.com/yt-dlp/yt-dlp#update))
- [X] I've checked that all provided URLs are alive and playable in a browser
- [X] I've checked that all URLs and arguments with special characters are [properly quoted or escaped](https://github.com/ytdl-org/youtube-dl#video-url-contains-an-ampersand-and-im-getting-some-strange-output-1-2839-or-v-is-not-recognized-as-an-internal-or-external-command)
- [X] I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues including closed ones. DO NOT post duplicates
- [X] I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue)

### Description

NoneType Error occured when downloading a video.

### Verbose log

```shell
[debug] Encodings: locale cp1252, fs utf-8, out utf-8, err utf-8, pref cp1252
[debug] yt-dlp version 2022.01.21 [f20d607b0]
[debug] Python version 3.9.1 (CPython 64bit) - Windows-10-10.0.19041-SP0
[debug] exe versions: ffmpeg 4.2.3
[debug] Optional libraries: Cryptodome, mutagen, sqlite, websockets
[debug] Proxy map: {}
[debug] [MySpass] Extracting URL: https://www.myspass.de/shows/tvshows/tv-total/Novak-Puffovic-bei-bester-Laune--/44996/
[MySpass] 44996: Downloading XML
ERROR: 'NoneType' object has no attribute 'groups'
Traceback (most recent call last):
  File "C:\...\Roaming\Python\Python39\site-packages\yt_dlp\YoutubeDL.py", line 1367, in wrapper
    return func(self, *args, **kwargs)
  File "C:\...\Roaming\Python\Python39\site-packages\yt_dlp\YoutubeDL.py", line 1437, in __extract_info
    ie_result = ie.extract(url)
  File "C:\...\Roaming\Python\Python39\site-packages\yt_dlp\extractor\common.py", line 612, in extract
    ie_result = self._real_extract(url)
  File "C:\...\Roaming\Python\Python39\site-packages\yt_dlp\extractor\myspass.py", line 38, in _real_extract
    for group in re.search(r'/myspass2009/\d+/(\d+)/(\d+)/(\d+)/', video_url).groups():
AttributeError: 'NoneType' object has no attribute 'groups'
```



Discussion:

Resolving patch:
diff --git a/yt_dlp/extractor/myspass.py b/yt_dlp/extractor/myspass.py
--- a/yt_dlp/extractor/myspass.py
+++ b/yt_dlp/extractor/myspass.py
@@ -1,8 +1,6 @@
 # coding: utf-8
 from __future__ import unicode_literals
 
-import re
-
 from .common import InfoExtractor
 from ..compat import compat_str
 from ..utils import (
@@ -13,33 +11,74 @@
 
 
 class MySpassIE(InfoExtractor):
-    _VALID_URL = r'https?://(?:www\.)?myspass\.de/([^/]+/)*(?P<id>\d+)'
-    _TEST = {
+    _VALID_URL = r'https?://(?:www\.)?myspass\.de/(?:[^/]+/)*(?P<id>\d+)/?[^/]*$'
+    _TESTS = [{
         'url': 'http://www.myspass.de/myspass/shows/tvshows/absolute-mehrheit/Absolute-Mehrheit-vom-17022013-Die-Highlights-Teil-2--/11741/',
         'md5': '0b49f4844a068f8b33f4b7c88405862b',
         'info_dict': {
             'id': '11741',
             'ext': 'mp4',
-            'description': 'Wer kann in die Fußstapfen von Wolfgang Kubicki treten und die Mehrheit der Zuschauer hinter sich versammeln? Wird vielleicht sogar die Absolute Mehrheit geknackt und der Jackpot von 200.000 Euro mit nach Hause genommen?',
+            'description': 'md5:9f0db5044c8fe73f528a390498f7ce9b',
             'title': '17.02.2013 - Die Highlights, Teil 2',
+            'thumbnail': r're:.*\.jpg',
+            'duration': 323.0,
+            'episode': '17.02.2013 - Die Highlights, Teil 2',
+            'season_id': '544',
+            'episode_number': 1,
+            'series': 'Absolute Mehrheit',
+            'season_number': 2,
+            'season': 'Season 2',
+        },
+    },
+        {
+        'url': 'https://www.myspass.de/shows/tvshows/tv-total/Novak-Puffovic-bei-bester-Laune--/44996/',
+        'md5': 'eb28b7c5e254192046e86ebaf7deac8f',
+        'info_dict': {
+            'id': '44996',
+            'ext': 'mp4',
+            'description': 'md5:74c7f886e00834417f1e427ab0da6121',
+            'title': 'Novak Puffovic bei bester Laune',
+            'thumbnail': r're:.*\.jpg',
+            'episode_number': 8,
+            'episode': 'Novak Puffovic bei bester Laune',
+            'series': 'TV total',
+            'season': 'Season 19',
+            'season_id': '987',
+            'duration': 2941.0,
+            'season_number': 19,
+        },
+    },
+        {
+        'url': 'https://www.myspass.de/channels/tv-total-raabigramm/17033/20831/',
+        'md5': '7b293a6b9f3a7acdd29304c8d0dbb7cc',
+        'info_dict': {
+            'id': '20831',
+            'ext': 'mp4',
+            'description': 'Gefühle pur: Schaut euch die ungeschnittene Version von Stefans Liebesbeweis an die Moderationsgrazie von Welt, Verona Feldbusch, an.',
+            'title': 'Raabigramm Verona Feldbusch',
+            'thumbnail': r're:.*\.jpg',
+            'episode_number': 6,
+            'episode': 'Raabigramm Verona Feldbusch',
+            'series': 'TV total',
+            'season': 'Season 1',
+            'season_id': '34',
+            'duration': 105.0,
+            'season_number': 1,
         },
-    }
+    }]
 
     def _real_extract(self, url):
         video_id = self._match_id(url)
 
-        metadata = self._download_xml(
-            'http://www.myspass.de/myspass/includes/apps/video/getvideometadataxml.php?id=' + video_id,
-            video_id)
+        metadata = self._download_xml('http://www.myspass.de/myspass/includes/apps/video/getvideometadataxml.php?id=' + video_id, video_id)
 
         title = xpath_text(metadata, 'title', fatal=True)
         video_url = xpath_text(metadata, 'url_flv', 'download url', True)
         video_id_int = int(video_id)
-        for group in re.search(r'/myspass2009/\d+/(\d+)/(\d+)/(\d+)/', video_url).groups():
+        for group in self._search_regex(r'/myspass2009/\d+/(\d+)/(\d+)/(\d+)/', video_url, 'myspass', group=(1, 2, 3), default=[]):
             group_int = int(group)
             if group_int > video_id_int:
-                video_url = video_url.replace(
-                    group, compat_str(group_int // video_id_int))
+                video_url = video_url.replace(group, compat_str(group_int // video_id_int))
 
         return {
             'id': video_id,


Test patch: