Repository: yt-dlp/yt-dlp

Issue:
ERROR: [n-tv.de] 23214572: Unable to extract info
### Checklist

- [X] I'm reporting a broken site
- [X] I've verified that I'm running yt-dlp version **2022.03.08.1**. ([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)
- [X] I've read about [sharing account credentials](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#are-you-willing-to-share-account-details-if-needed) and I'm willing to share it if required

### Region

Global

### Description

I tried to download the video from the following site: 

[](https://www.n-tv.de/mediathek/videos/wirtschaft/Habeck-Tesla-hofft-auf-neuen-Leitmarkt-Deutschland-article23214572.html)

### Verbose log

```shell
yt-dlp -vU https://www.n-tv.de/mediathek/videos/wirtschaft/Habeck-Tesla-hofft-auf-neuen-Leitmarkt-Deutschland-article23214572.html
[debug] Command-line config: ['-vU', 'https://www.n-tv.de/mediathek/videos/wirtschaft/Habeck-Tesla-hofft-auf-neuen-Leitmarkt-Deutschland-article23214572.html']
[debug] Encodings: locale UTF-8, fs utf-8, out utf-8, err utf-8, pref UTF-8
[debug] yt-dlp version 2022.03.08.1 [c0c2c57d3] (zip)
[debug] Python version 3.8.10 (CPython 64bit) - Linux-5.10.60.1-microsoft-standard-WSL2-x86_64-with-glibc2.29
[debug] exe versions: ffmpeg 4.2.4, ffprobe 4.2.4, rtmpdump 2.4
[debug] Optional libraries: Cryptodome, secretstorage, mutagen, sqlite, websockets
[debug] Proxy map: {}
Latest version: 2022.03.08.1, Current version: 2022.03.08.1
yt-dlp is up to date (2022.03.08.1)
[debug] [n-tv.de] Extracting URL: https://www.n-tv.de/mediathek/videos/wirtschaft/Habeck-Tesla-hofft-auf-neuen-Leitmarkt-Deutschland-article23214572.html
[n-tv.de] 23214572: Downloading webpage
ERROR: [n-tv.de] 23214572: Unable to extract info; please report this issue on  https://github.com/yt-dlp/yt-dlp , filling out the "Broken site" issue template properly. Confirm you are on the latest version using  yt-dlp -U
  File "/usr/local/bin/yt-dlp/yt_dlp/extractor/common.py", line 617, in extract
    ie_result = self._real_extract(url)
  File "/usr/local/bin/yt-dlp/yt_dlp/extractor/ntvde.py", line 39, in _real_extract
    info = self._parse_json(self._search_regex(
  File "/usr/local/bin/yt-dlp/yt_dlp/extractor/common.py", line 1192, in _search_regex
    raise RegexNotFoundError('Unable to extract %s' % _name)
```



Discussion:
> Region
Global

![image](https://user-images.githubusercontent.com/6623388/160628812-91b9fdff-44e7-436b-9b70-3b07d5fc2f56.png)

The question exists for a reason! Why can't people just put their actual location :(

Resolving patch:
diff --git a/yt_dlp/extractor/ntvde.py b/yt_dlp/extractor/ntvde.py
--- a/yt_dlp/extractor/ntvde.py
+++ b/yt_dlp/extractor/ntvde.py
@@ -1,21 +1,21 @@
 import re
 
 from .common import InfoExtractor
-from ..compat import compat_urlparse
 from ..utils import (
     int_or_none,
     js_to_json,
-    parse_duration,
+    url_or_none,
 )
+from ..utils.traversal import traverse_obj
 
 
 class NTVDeIE(InfoExtractor):
     IE_NAME = 'n-tv.de'
-    _VALID_URL = r'https?://(?:www\.)?n-tv\.de/mediathek/videos/[^/?#]+/[^/?#]+-article(?P<id>.+)\.html'
+    _VALID_URL = r'https?://(?:www\.)?n-tv\.de/mediathek/(?:videos|magazine)/[^/?#]+/[^/?#]+-article(?P<id>[^/?#]+)\.html'
 
     _TESTS = [{
         'url': 'http://www.n-tv.de/mediathek/videos/panorama/Schnee-und-Glaette-fuehren-zu-zahlreichen-Unfaellen-und-Staus-article14438086.html',
-        'md5': '6ef2514d4b1e8e03ca24b49e2f167153',
+        'md5': '6bcf2a6638cb83f45d5561659a1cb498',
         'info_dict': {
             'id': '14438086',
             'ext': 'mp4',
@@ -23,51 +23,61 @@ class NTVDeIE(InfoExtractor):
             'title': 'Schnee und Glätte führen zu zahlreichen Unfällen und Staus',
             'alt_title': 'Winterchaos auf deutschen Straßen',
             'description': 'Schnee und Glätte sorgen deutschlandweit für einen chaotischen Start in die Woche: Auf den Straßen kommt es zu kilometerlangen Staus und Dutzenden Glätteunfällen. In Düsseldorf und München wirbelt der Schnee zudem den Flugplan durcheinander. Dutzende Flüge landen zu spät, einige fallen ganz aus.',
-            'duration': 4020,
+            'duration': 67,
             'timestamp': 1422892797,
             'upload_date': '20150202',
         },
+    }, {
+        'url': 'https://www.n-tv.de/mediathek/magazine/auslandsreport/Juedische-Siedler-wollten-Rache-die-wollten-nur-toeten-article24523089.html',
+        'md5': 'c5c6014c014ccc3359470e1d34472bfd',
+        'info_dict': {
+            'id': '24523089',
+            'ext': 'mp4',
+            'thumbnail': r're:^https?://.*\.jpg$',
+            'title': 'Jüdische Siedler "wollten Rache, die wollten nur töten"',
+            'alt_title': 'Israelische Gewalt fern von Gaza',
+            'description': 'Vier Tage nach dem Massaker der Hamas greifen jüdische Siedler das Haus einer palästinensischen Familie im Westjordanland an. Die Überlebenden berichten, sie waren unbewaffnet, die Angreifer seien nur auf "Rache und Töten" aus gewesen. Als die Toten beerdigt werden sollen, eröffnen die Siedler erneut das Feuer.',
+            'duration': 326,
+            'timestamp': 1699688294,
+            'upload_date': '20231111',
+        },
     }]
 
     def _real_extract(self, url):
         video_id = self._match_id(url)
         webpage = self._download_webpage(url, video_id)
 
-        info = self._parse_json(self._search_regex(
-            r'(?s)ntv\.pageInfo\.article\s*=\s*(\{.*?\});', webpage, 'info'),
-            video_id, transform_source=js_to_json)
-        timestamp = int_or_none(info.get('publishedDateAsUnixTimeStamp'))
-        vdata = self._parse_json(self._search_regex(
-            r'(?s)\$\(\s*"\#player"\s*\)\s*\.data\(\s*"player",\s*(\{.*?\})\);',
-            webpage, 'player data'), video_id,
-            transform_source=lambda s: js_to_json(re.sub(r'advertising:\s*{[^}]+},', '', s)))
-        duration = parse_duration(vdata.get('duration'))
+        info = self._search_json(
+            r'article:', webpage, 'info', video_id, transform_source=js_to_json)
+
+        vdata = self._search_json(
+            r'\$\(\s*"#playerwrapper"\s*\)\s*\.data\(\s*"player",',
+            webpage, 'player data', video_id,
+            transform_source=lambda s: js_to_json(re.sub(r'ivw:[^},]+', '', s)))['setup']['source']
 
         formats = []
-        if vdata.get('video'):
-            formats.append({
-                'format_id': 'flash',
-                'url': 'rtmp://fms.n-tv.de/%s' % vdata['video'],
-            })
-        if vdata.get('videoMp4'):
+        if vdata.get('progressive'):
             formats.append({
-                'format_id': 'mobile',
-                'url': compat_urlparse.urljoin('http://video.n-tv.de', vdata['videoMp4']),
-                'tbr': 400,  # estimation
+                'format_id': 'http',
+                'url': vdata['progressive'],
             })
-        if vdata.get('videoM3u8'):
-            m3u8_url = compat_urlparse.urljoin('http://video.n-tv.de', vdata['videoM3u8'])
+        if vdata.get('hls'):
             formats.extend(self._extract_m3u8_formats(
-                m3u8_url, video_id, ext='mp4', entry_protocol='m3u8_native',
-                quality=1, m3u8_id='hls', fatal=False))
+                vdata['hls'], video_id, 'mp4', m3u8_id='hls', fatal=False))
+        if vdata.get('dash'):
+            formats.extend(self._extract_mpd_formats(vdata['dash'], video_id, fatal=False, mpd_id='dash'))
 
         return {
             'id': video_id,
-            'title': info['headline'],
-            'description': info.get('intro'),
-            'alt_title': info.get('kicker'),
-            'timestamp': timestamp,
-            'thumbnail': vdata.get('html5VideoPoster'),
-            'duration': duration,
+            **traverse_obj(info, {
+                'title': 'headline',
+                'description': 'intro',
+                'alt_title': 'kicker',
+                'timestamp': ('publishedDateAsUnixTimeStamp', {int_or_none}),
+            }),
+            **traverse_obj(vdata, {
+                'thumbnail': ('poster', {url_or_none}),
+                'duration': ('length', {int_or_none}),
+            }),
             'formats': formats,
         }


Test patch: