mirror of
https://github.com/ytdl-org/youtube-dl
synced 2025-07-16 16:34:13 +09:00
Compare commits
6 Commits
8750c5931e
...
d955565fe8
Author | SHA1 | Date | |
---|---|---|---|
![]() |
d955565fe8 | ||
![]() |
da7223d4aa | ||
![]() |
37c2440d6a | ||
![]() |
a2fd63ce22 | ||
![]() |
d6469de1da | ||
![]() |
77e8f5353c |
@ -187,10 +187,10 @@ class TestInfoExtractor(unittest.TestCase):
|
|||||||
self.assertEqual(search['track']['id'], 'testid')
|
self.assertEqual(search['track']['id'], 'testid')
|
||||||
|
|
||||||
def test_search_json_ld_realworld(self):
|
def test_search_json_ld_realworld(self):
|
||||||
# https://github.com/ytdl-org/youtube-dl/issues/23306
|
_TESTS = [
|
||||||
expect_dict(
|
# https://github.com/ytdl-org/youtube-dl/issues/23306
|
||||||
self,
|
(
|
||||||
self.ie._search_json_ld(r'''<script type="application/ld+json">
|
r'''<script type="application/ld+json">
|
||||||
{
|
{
|
||||||
"@context": "http://schema.org/",
|
"@context": "http://schema.org/",
|
||||||
"@type": "VideoObject",
|
"@type": "VideoObject",
|
||||||
@ -223,17 +223,86 @@ class TestInfoExtractor(unittest.TestCase):
|
|||||||
"name": "Kleio Valentien",
|
"name": "Kleio Valentien",
|
||||||
"url": "https://www.eporner.com/pornstar/kleio-valentien/"
|
"url": "https://www.eporner.com/pornstar/kleio-valentien/"
|
||||||
}]}
|
}]}
|
||||||
</script>''', None),
|
</script>''',
|
||||||
{
|
{
|
||||||
'title': '1 On 1 With Kleio',
|
'title': '1 On 1 With Kleio',
|
||||||
'description': 'Kleio Valentien',
|
'description': 'Kleio Valentien',
|
||||||
'url': 'https://gvideo.eporner.com/xN49A1cT3eB/xN49A1cT3eB.mp4',
|
'url': 'https://gvideo.eporner.com/xN49A1cT3eB/xN49A1cT3eB.mp4',
|
||||||
'timestamp': 1449347075,
|
'timestamp': 1449347075,
|
||||||
'duration': 743.0,
|
'duration': 743.0,
|
||||||
'view_count': 1120958,
|
'view_count': 1120958,
|
||||||
'width': 1920,
|
'width': 1920,
|
||||||
'height': 1080,
|
'height': 1080,
|
||||||
})
|
},
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
r'''<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@graph": [
|
||||||
|
{
|
||||||
|
"@type": "NewsArticle",
|
||||||
|
"mainEntityOfPage": {
|
||||||
|
"@type": "WebPage",
|
||||||
|
"@id": "https://www.ant1news.gr/Society/article/620286/symmoria-anilikon-dikigoros-thymaton-ithelan-na-toys-apoteleiosoyn"
|
||||||
|
},
|
||||||
|
"headline": "Συμμορία ανηλίκων – δικηγόρος θυμάτων: ήθελαν να τους αποτελειώσουν",
|
||||||
|
"name": "Συμμορία ανηλίκων – δικηγόρος θυμάτων: ήθελαν να τους αποτελειώσουν",
|
||||||
|
"description": "Τα παιδιά δέχθηκαν την επίθεση επειδή αρνήθηκαν να γίνουν μέλη της συμμορίας, ανέφερε ο Γ. Ζαχαρόπουλος.",
|
||||||
|
"image": {
|
||||||
|
"@type": "ImageObject",
|
||||||
|
"url": "https://ant1media.azureedge.net/imgHandler/1100/a635c968-be71-447c-bf9c-80d843ece21e.jpg",
|
||||||
|
"width": 1100,
|
||||||
|
"height": 756 },
|
||||||
|
"datePublished": "2021-11-10T08:50:00+03:00",
|
||||||
|
"dateModified": "2021-11-10T08:52:53+03:00",
|
||||||
|
"author": {
|
||||||
|
"@type": "Person",
|
||||||
|
"@id": "https://www.ant1news.gr/",
|
||||||
|
"name": "Ant1news",
|
||||||
|
"image": "https://www.ant1news.gr/images/logo-e5d7e4b3e714c88e8d2eca96130142f6.png",
|
||||||
|
"url": "https://www.ant1news.gr/"
|
||||||
|
},
|
||||||
|
"publisher": {
|
||||||
|
"@type": "Organization",
|
||||||
|
"@id": "https://www.ant1news.gr#publisher",
|
||||||
|
"name": "Ant1news",
|
||||||
|
"url": "https://www.ant1news.gr",
|
||||||
|
"logo": {
|
||||||
|
"@type": "ImageObject",
|
||||||
|
"url": "https://www.ant1news.gr/images/logo-e5d7e4b3e714c88e8d2eca96130142f6.png",
|
||||||
|
"width": 400,
|
||||||
|
"height": 400 },
|
||||||
|
"sameAs": [
|
||||||
|
"https://www.facebook.com/Ant1news.gr",
|
||||||
|
"https://twitter.com/antennanews",
|
||||||
|
"https://www.youtube.com/channel/UC0smvAbfczoN75dP0Hw4Pzw",
|
||||||
|
"https://www.instagram.com/ant1news/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
"keywords": "μαχαίρωμα,συμμορία ανηλίκων,ΕΙΔΗΣΕΙΣ,ΕΙΔΗΣΕΙΣ ΣΗΜΕΡΑ,ΝΕΑ,Κοινωνία - Ant1news",
|
||||||
|
|
||||||
|
|
||||||
|
"articleSection": "Κοινωνία"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
</script>''',
|
||||||
|
{
|
||||||
|
'timestamp': 1636523400,
|
||||||
|
'title': 'md5:91fe569e952e4d146485740ae927662b',
|
||||||
|
},
|
||||||
|
{'expected_type': 'NewsArticle'},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
for html, expected_dict, search_json_ld_kwargs in _TESTS:
|
||||||
|
expect_dict(
|
||||||
|
self,
|
||||||
|
self.ie._search_json_ld(html, None, **search_json_ld_kwargs),
|
||||||
|
expected_dict
|
||||||
|
)
|
||||||
|
|
||||||
def test_download_json(self):
|
def test_download_json(self):
|
||||||
uri = encode_data_uri(b'{"foo": "blah"}', 'application/json')
|
uri = encode_data_uri(b'{"foo": "blah"}', 'application/json')
|
||||||
|
@ -232,8 +232,32 @@ _NSIG_TESTS = [
|
|||||||
'W9HJZKktxuYoDTqW', 'jHbbkcaxm54',
|
'W9HJZKktxuYoDTqW', 'jHbbkcaxm54',
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
'https://www.youtube.com/s/player/91201489/player_ias_tce.vflset/en_US/base.js',
|
'https://www.youtube.com/s/player/643afba4/player_ias.vflset/en_US/base.js',
|
||||||
'W9HJZKktxuYoDTqW', 'U48vOZHaeYS6vO',
|
'W9HJZKktxuYoDTqW', 'larxUlagTRAcSw',
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'https://www.youtube.com/s/player/e7567ecf/player_ias_tce.vflset/en_US/base.js',
|
||||||
|
'Sy4aDGc0VpYRR9ew_', '5UPOT1VhoZxNLQ',
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'https://www.youtube.com/s/player/d50f54ef/player_ias_tce.vflset/en_US/base.js',
|
||||||
|
'Ha7507LzRmH3Utygtj', 'XFTb2HoeOE5MHg',
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'https://www.youtube.com/s/player/074a8365/player_ias_tce.vflset/en_US/base.js',
|
||||||
|
'Ha7507LzRmH3Utygtj', 'ufTsrE0IVYrkl8v',
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'https://www.youtube.com/s/player/643afba4/player_ias.vflset/en_US/base.js',
|
||||||
|
'N5uAlLqm0eg1GyHO', 'dCBQOejdq5s-ww',
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'https://www.youtube.com/s/player/69f581a5/tv-player-ias.vflset/tv-player-ias.js',
|
||||||
|
'-qIP447rVlTTwaZjY', 'KNcGOksBAvwqQg',
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'https://www.youtube.com/s/player/643afba4/tv-player-ias.vflset/tv-player-ias.js',
|
||||||
|
'ir9-V6cdbCiyKxhr', '2PL7ZDYAALMfmA',
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1438,8 +1438,16 @@ class InfoExtractor(object):
|
|||||||
})
|
})
|
||||||
extract_interaction_statistic(e)
|
extract_interaction_statistic(e)
|
||||||
|
|
||||||
for e in json_ld:
|
def traverse_json_ld(json_ld, info, at_top_level=True):
|
||||||
if '@context' in e:
|
for e in json_ld:
|
||||||
|
if at_top_level and '@context' not in e:
|
||||||
|
continue
|
||||||
|
if at_top_level and all(k in ('@context', '@graph') for k in e):
|
||||||
|
graph = e['@graph']
|
||||||
|
if isinstance(graph, dict):
|
||||||
|
graph = [graph]
|
||||||
|
traverse_json_ld(graph, info, at_top_level=False)
|
||||||
|
break
|
||||||
item_type = e.get('@type')
|
item_type = e.get('@type')
|
||||||
if expected_type is not None and expected_type != item_type:
|
if expected_type is not None and expected_type != item_type:
|
||||||
continue
|
continue
|
||||||
@ -1472,7 +1480,7 @@ class InfoExtractor(object):
|
|||||||
info.update({
|
info.update({
|
||||||
'timestamp': parse_iso8601(e.get('datePublished')),
|
'timestamp': parse_iso8601(e.get('datePublished')),
|
||||||
'title': unescapeHTML(e.get('headline')),
|
'title': unescapeHTML(e.get('headline')),
|
||||||
'description': unescapeHTML(e.get('articleBody')),
|
'description': unescapeHTML(e.get('articleBody') or e.get('description')),
|
||||||
})
|
})
|
||||||
elif item_type == 'VideoObject':
|
elif item_type == 'VideoObject':
|
||||||
extract_video_object(e)
|
extract_video_object(e)
|
||||||
@ -1487,6 +1495,8 @@ class InfoExtractor(object):
|
|||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
traverse_json_ld(json_ld, info)
|
||||||
|
|
||||||
return dict((k, v) for k, v in info.items() if v is not None)
|
return dict((k, v) for k, v in info.items() if v is not None)
|
||||||
|
|
||||||
def _search_nextjs_data(self, webpage, video_id, **kw):
|
def _search_nextjs_data(self, webpage, video_id, **kw):
|
||||||
|
@ -91,12 +91,12 @@ class YoutubeBaseInfoExtractor(InfoExtractor):
|
|||||||
'INNERTUBE_CONTEXT': {
|
'INNERTUBE_CONTEXT': {
|
||||||
'client': {
|
'client': {
|
||||||
'clientName': 'IOS',
|
'clientName': 'IOS',
|
||||||
'clientVersion': '19.45.4',
|
'clientVersion': '20.10.4',
|
||||||
'deviceMake': 'Apple',
|
'deviceMake': 'Apple',
|
||||||
'deviceModel': 'iPhone16,2',
|
'deviceModel': 'iPhone16,2',
|
||||||
'userAgent': 'com.google.ios.youtube/19.45.4 (iPhone16,2; U; CPU iOS 18_1_0 like Mac OS X;)',
|
'userAgent': 'com.google.ios.youtube/20.10.4 (iPhone16,2; U; CPU iOS 18_3_2 like Mac OS X;)',
|
||||||
'osName': 'iPhone',
|
'osName': 'iPhone',
|
||||||
'osVersion': '18.1.0.22B83',
|
'osVersion': '18.3.2.22D82',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'INNERTUBE_CONTEXT_CLIENT_NAME': 5,
|
'INNERTUBE_CONTEXT_CLIENT_NAME': 5,
|
||||||
@ -109,7 +109,7 @@ class YoutubeBaseInfoExtractor(InfoExtractor):
|
|||||||
'INNERTUBE_CONTEXT': {
|
'INNERTUBE_CONTEXT': {
|
||||||
'client': {
|
'client': {
|
||||||
'clientName': 'MWEB',
|
'clientName': 'MWEB',
|
||||||
'clientVersion': '2.20241202.07.00',
|
'clientVersion': '2.20250311.03.00',
|
||||||
# mweb previously did not require PO Token with this UA
|
# mweb previously did not require PO Token with this UA
|
||||||
'userAgent': 'Mozilla/5.0 (iPad; CPU OS 16_7_10 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1,gzip(gfe)',
|
'userAgent': 'Mozilla/5.0 (iPad; CPU OS 16_7_10 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1,gzip(gfe)',
|
||||||
},
|
},
|
||||||
@ -122,7 +122,7 @@ class YoutubeBaseInfoExtractor(InfoExtractor):
|
|||||||
'INNERTUBE_CONTEXT': {
|
'INNERTUBE_CONTEXT': {
|
||||||
'client': {
|
'client': {
|
||||||
'clientName': 'TVHTML5',
|
'clientName': 'TVHTML5',
|
||||||
'clientVersion': '7.20250120.19.00',
|
'clientVersion': '7.20250312.16.00',
|
||||||
'userAgent': 'Mozilla/5.0 (ChromiumStylePlatform) Cobalt/Version',
|
'userAgent': 'Mozilla/5.0 (ChromiumStylePlatform) Cobalt/Version',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -133,7 +133,7 @@ class YoutubeBaseInfoExtractor(InfoExtractor):
|
|||||||
'INNERTUBE_CONTEXT': {
|
'INNERTUBE_CONTEXT': {
|
||||||
'client': {
|
'client': {
|
||||||
'clientName': 'WEB',
|
'clientName': 'WEB',
|
||||||
'clientVersion': '2.20241126.01.00',
|
'clientVersion': '2.20250312.04.00',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'INNERTUBE_CONTEXT_CLIENT_NAME': 1,
|
'INNERTUBE_CONTEXT_CLIENT_NAME': 1,
|
||||||
@ -692,7 +692,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'invidious': '|'.join(_INVIDIOUS_SITES),
|
'invidious': '|'.join(_INVIDIOUS_SITES),
|
||||||
}
|
}
|
||||||
_PLAYER_INFO_RE = (
|
_PLAYER_INFO_RE = (
|
||||||
r'/s/player/(?P<id>[a-zA-Z0-9_-]{8,})/player',
|
r'/s/player/(?P<id>[a-zA-Z0-9_-]{8,})//(?:tv-)?player',
|
||||||
r'/(?P<id>[a-zA-Z0-9_-]{8,})/player(?:_ias\.vflset(?:/[a-zA-Z]{2,3}_[a-zA-Z]{2,3})?|-plasma-ias-(?:phone|tablet)-[a-z]{2}_[A-Z]{2}\.vflset)/base\.js$',
|
r'/(?P<id>[a-zA-Z0-9_-]{8,})/player(?:_ias\.vflset(?:/[a-zA-Z]{2,3}_[a-zA-Z]{2,3})?|-plasma-ias-(?:phone|tablet)-[a-z]{2}_[A-Z]{2}\.vflset)/base\.js$',
|
||||||
r'\b(?P<id>vfl[a-zA-Z0-9_-]+)\b.*?\.js$',
|
r'\b(?P<id>vfl[a-zA-Z0-9_-]+)\b.*?\.js$',
|
||||||
)
|
)
|
||||||
@ -1857,7 +1857,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
def _extract_n_function_code_jsi(self, video_id, jsi, player_id=None):
|
def _extract_n_function_code_jsi(self, video_id, jsi, player_id=None):
|
||||||
|
|
||||||
var_ay = self._search_regex(
|
var_ay = self._search_regex(
|
||||||
r'(?:[;\s]|^)\s*(var\s*[\w$]+\s*=\s*"[^"]+"\s*\.\s*split\("\{"\))(?=\s*[,;])',
|
r'(?:[;\s]|^)\s*(var\s*[\w$]+\s*=\s*"(?:\\"|[^"])+"\s*\.\s*split\("\W+"\))(?=\s*[,;])',
|
||||||
jsi.code, 'useful values', default='')
|
jsi.code, 'useful values', default='')
|
||||||
|
|
||||||
func_name = self._extract_n_function_name(jsi.code)
|
func_name = self._extract_n_function_name(jsi.code)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user