From 03339b7b5bb8f563eace8826512e2f7a4baba415 Mon Sep 17 00:00:00 2001 From: remitamine Date: Fri, 26 Jun 2015 18:25:43 +0100 Subject: [PATCH 1/5] [snagfilms] Add new extractor --- youtube_dl/extractor/__init__.py | 1 + youtube_dl/extractor/snagfilms.py | 67 +++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 youtube_dl/extractor/snagfilms.py diff --git a/youtube_dl/extractor/__init__.py b/youtube_dl/extractor/__init__.py index dc1a302e6..3b906b880 100644 --- a/youtube_dl/extractor/__init__.py +++ b/youtube_dl/extractor/__init__.py @@ -492,6 +492,7 @@ SmotriUserIE, SmotriBroadcastIE, ) +from .snagfilms import SnagFilmsIE from .snotr import SnotrIE from .sohu import SohuIE from .soompi import ( diff --git a/youtube_dl/extractor/snagfilms.py b/youtube_dl/extractor/snagfilms.py new file mode 100644 index 000000000..33832855f --- /dev/null +++ b/youtube_dl/extractor/snagfilms.py @@ -0,0 +1,67 @@ +from .common import InfoExtractor +from ..utils import js_to_json +from re import DOTALL + +class SnagFilmsIE(InfoExtractor): + _VALID_URL = r'(?:https?://)?(?:www.)?snagfilms\.com/films/title/(?P.+?)(?:/|$)' + _TEST = { + 'url': 'http://www.snagfilms.com/films/title/lost_for_life', + 'info_dict': + { + 'id': '0000014c-de2f-d5d6-abcf-ffef58af0017', + 'display_id': 'lost_for_life', + 'ext': 'mp4', + 'title': 'Lost for Life', + 'duration': 4489, + 'description': 'In the United States, more than 2500 individuals are serving life-without-parole sentences for crimes they committed when they were seventeen years old or younger. Children as young as thirteen are among the thousands serving these sentences. Directed by Joshua Rofé (who spent four intensive years on the project), LOST FOR LIFE tells the stories of these individuals, their families and the families of juvenile murder victims. This searingly powerful documentary tackles this contentious issue from multiple perspectives and explores the complexity of the lives of those affected. What is justice when a kid kills? Can a horrific act place a life beyond redemption? Could you forgive?
', + 'categories': ['Documentary','Crime','Award Winning','Festivals'] + } + } + + def _real_extract(self, url): + display_id = self._search_regex( + self._VALID_URL, + url, + 'display_id', + group='display_id' + ) + webpage = self._download_webpage(url, display_id) + + json_data = self._parse_json(self._html_search_regex( + r'"data":{"film":(?P{.*?}})}', + webpage, + 'data', + group='data' + ), display_id) + title = json_data['title'] + video_id = json_data['id'] + duration = int(json_data['duration']) + description = json_data['synopsis'] + categories = [category['title'] for category in json_data['categories']] + + embed_webpage = self._download_webpage('http://www.snagfilms.com/embed/player?filmId=' + video_id, video_id) + sources = self._parse_json(js_to_json(self._html_search_regex( + r'sources: (?P\[.*?\])', + embed_webpage, + 'sources', + group='sources', + flags=DOTALL + )), video_id) + + formats = [] + for source in sources: + if source['type'] == 'm3u8': + formats.extend(self._extract_m3u8_formats(source['file'], video_id)) + else: + formats.append({'url': source['file'],'ext': source['type'], 'resolution': source['label']}) + self._sort_formats(formats) + + return { + 'id': video_id, + 'display_id': display_id, + 'title': title, + 'duration': duration, + 'description': description, + 'categories': categories, + 'formats': formats, + } From 7e0480ae0e7a9d0b3c73366b8d9ecf86226ad5a8 Mon Sep 17 00:00:00 2001 From: remitamine Date: Fri, 26 Jun 2015 21:50:27 +0100 Subject: [PATCH 2/5] convert tabs to 4 spaces identation --- youtube_dl/extractor/snagfilms.py | 114 +++++++++++++++--------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/youtube_dl/extractor/snagfilms.py b/youtube_dl/extractor/snagfilms.py index 33832855f..212fefef7 100644 --- a/youtube_dl/extractor/snagfilms.py +++ b/youtube_dl/extractor/snagfilms.py @@ -3,65 +3,65 @@ from re import DOTALL class SnagFilmsIE(InfoExtractor): - _VALID_URL = r'(?:https?://)?(?:www.)?snagfilms\.com/films/title/(?P.+?)(?:/|$)' - _TEST = { - 'url': 'http://www.snagfilms.com/films/title/lost_for_life', - 'info_dict': - { - 'id': '0000014c-de2f-d5d6-abcf-ffef58af0017', - 'display_id': 'lost_for_life', - 'ext': 'mp4', - 'title': 'Lost for Life', - 'duration': 4489, - 'description': 'In the United States, more than 2500 individuals are serving life-without-parole sentences for crimes they committed when they were seventeen years old or younger. Children as young as thirteen are among the thousands serving these sentences. Directed by Joshua Rofé (who spent four intensive years on the project), LOST FOR LIFE tells the stories of these individuals, their families and the families of juvenile murder victims. This searingly powerful documentary tackles this contentious issue from multiple perspectives and explores the complexity of the lives of those affected. What is justice when a kid kills? Can a horrific act place a life beyond redemption? Could you forgive?
', - 'categories': ['Documentary','Crime','Award Winning','Festivals'] - } - } + _VALID_URL = r'(?:https?://)?(?:www.)?snagfilms\.com/films/title/(?P.+?)(?:/|$)' + _TEST = { + 'url': 'http://www.snagfilms.com/films/title/lost_for_life', + 'info_dict': + { + 'id': '0000014c-de2f-d5d6-abcf-ffef58af0017', + 'display_id': 'lost_for_life', + 'ext': 'mp4', + 'title': 'Lost for Life', + 'duration': 4489, + 'description': 'In the United States, more than 2500 individuals are serving life-without-parole sentences for crimes they committed when they were seventeen years old or younger. Children as young as thirteen are among the thousands serving these sentences. Directed by Joshua Rofé (who spent four intensive years on the project), LOST FOR LIFE tells the stories of these individuals, their families and the families of juvenile murder victims. This searingly powerful documentary tackles this contentious issue from multiple perspectives and explores the complexity of the lives of those affected. What is justice when a kid kills? Can a horrific act place a life beyond redemption? Could you forgive?
', + 'categories': ['Documentary','Crime','Award Winning','Festivals'] + } + } - def _real_extract(self, url): - display_id = self._search_regex( - self._VALID_URL, - url, - 'display_id', - group='display_id' - ) - webpage = self._download_webpage(url, display_id) + def _real_extract(self, url): + display_id = self._search_regex( + self._VALID_URL, + url, + 'display_id', + group='display_id' + ) + webpage = self._download_webpage(url, display_id) - json_data = self._parse_json(self._html_search_regex( - r'"data":{"film":(?P{.*?}})}', - webpage, - 'data', - group='data' - ), display_id) - title = json_data['title'] - video_id = json_data['id'] - duration = int(json_data['duration']) - description = json_data['synopsis'] - categories = [category['title'] for category in json_data['categories']] + json_data = self._parse_json(self._html_search_regex( + r'"data":{"film":(?P{.*?}})}', + webpage, + 'data', + group='data' + ), display_id) + title = json_data['title'] + video_id = json_data['id'] + duration = int(json_data['duration']) + description = json_data['synopsis'] + categories = [category['title'] for category in json_data['categories']] - embed_webpage = self._download_webpage('http://www.snagfilms.com/embed/player?filmId=' + video_id, video_id) - sources = self._parse_json(js_to_json(self._html_search_regex( - r'sources: (?P\[.*?\])', - embed_webpage, - 'sources', - group='sources', - flags=DOTALL - )), video_id) + embed_webpage = self._download_webpage('http://www.snagfilms.com/embed/player?filmId=' + video_id, video_id) + sources = self._parse_json(js_to_json(self._html_search_regex( + r'sources: (?P\[.*?\])', + embed_webpage, + 'sources', + group='sources', + flags=DOTALL + )), video_id) - formats = [] - for source in sources: - if source['type'] == 'm3u8': - formats.extend(self._extract_m3u8_formats(source['file'], video_id)) - else: - formats.append({'url': source['file'],'ext': source['type'], 'resolution': source['label']}) - self._sort_formats(formats) + formats = [] + for source in sources: + if source['type'] == 'm3u8': + formats.extend(self._extract_m3u8_formats(source['file'], video_id)) + else: + formats.append({'url': source['file'],'ext': source['type'], 'resolution': source['label']}) + self._sort_formats(formats) - return { - 'id': video_id, - 'display_id': display_id, - 'title': title, - 'duration': duration, - 'description': description, - 'categories': categories, - 'formats': formats, - } + return { + 'id': video_id, + 'display_id': display_id, + 'title': title, + 'duration': duration, + 'description': description, + 'categories': categories, + 'formats': formats, + } From fd40bdc0be8984bf6043e70796c1d465a0499d03 Mon Sep 17 00:00:00 2001 From: remitamine Date: Fri, 26 Jun 2015 21:56:15 +0100 Subject: [PATCH 3/5] remove unnecessary symbolic name for group --- youtube_dl/extractor/snagfilms.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/youtube_dl/extractor/snagfilms.py b/youtube_dl/extractor/snagfilms.py index 212fefef7..60354b9af 100644 --- a/youtube_dl/extractor/snagfilms.py +++ b/youtube_dl/extractor/snagfilms.py @@ -31,7 +31,6 @@ def _real_extract(self, url): r'"data":{"film":(?P{.*?}})}', webpage, 'data', - group='data' ), display_id) title = json_data['title'] video_id = json_data['id'] @@ -44,7 +43,6 @@ def _real_extract(self, url): r'sources: (?P\[.*?\])', embed_webpage, 'sources', - group='sources', flags=DOTALL )), video_id) From 7d7d4690259f343385a240efcef8d157fc99c72d Mon Sep 17 00:00:00 2001 From: remitamine Date: Sat, 27 Jun 2015 00:13:14 +0100 Subject: [PATCH 4/5] add support for embed links --- youtube_dl/extractor/snagfilms.py | 48 ++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/youtube_dl/extractor/snagfilms.py b/youtube_dl/extractor/snagfilms.py index 60354b9af..cd345474e 100644 --- a/youtube_dl/extractor/snagfilms.py +++ b/youtube_dl/extractor/snagfilms.py @@ -1,10 +1,10 @@ +from re import match,DOTALL from .common import InfoExtractor from ..utils import js_to_json -from re import DOTALL class SnagFilmsIE(InfoExtractor): - _VALID_URL = r'(?:https?://)?(?:www.)?snagfilms\.com/films/title/(?P.+?)(?:/|$)' - _TEST = { + _VALID_URL = r'(?:https?://)?(?:www.|embed.)?snagfilms\.com/(?:films/title/(?P.+?)|embed/player\?.*filmId=(?P.+?))(?:&|/|$)' + _TESTS = [{ 'url': 'http://www.snagfilms.com/films/title/lost_for_life', 'info_dict': { @@ -16,29 +16,48 @@ class SnagFilmsIE(InfoExtractor): 'description': 'In the United States, more than 2500 individuals are serving life-without-parole sentences for crimes they committed when they were seventeen years old or younger. Children as young as thirteen are among the thousands serving these sentences. Directed by Joshua Rofé (who spent four intensive years on the project), LOST FOR LIFE tells the stories of these individuals, their families and the families of juvenile murder victims. This searingly powerful documentary tackles this contentious issue from multiple perspectives and explores the complexity of the lives of those affected. What is justice when a kid kills? Can a horrific act place a life beyond redemption? Could you forgive?
', 'categories': ['Documentary','Crime','Award Winning','Festivals'] } - } + },{ + 'url': 'http://embed.snagfilms.com/embed/player?filmId=74849a00-85a9-11e1-9660-123139220831', + 'info_dict': + { + 'id': '74849a00-85a9-11e1-9660-123139220831', + 'display_id': 'while_we_watch', + 'ext': 'mp4', + 'title': '#whilewewatch', + 'duration': 2311, + 'description': 'A gripping portrait of the Occupy Wall Street media revolution, #WHILEWEWATCH is the first definitive film to emerge from Zuccotti Park—with full access and cooperation from masterminds who made #OccupyWallStreet a reality. The #OccupyWallStreet media team had no fear of a critical city government, big corporations, hostile police or a lagging mainstream media to tell their story. Through rain, snow, grueling days and sleeping on concrete, they pump out exhilarating ideas to the world. With little money, they rely on Twitter, texting, Wi-Fi, posters, Tumblr, live streams, YouTube, Facebook, dramatic marches, drumbeats and chants. As the film unfolds, we witness the burgeoning power of social media.
', + 'categories': ['Documentary','Politics'] + } + }] def _real_extract(self, url): - display_id = self._search_regex( - self._VALID_URL, - url, - 'display_id', - group='display_id' - ) - webpage = self._download_webpage(url, display_id) + display_id, video_id = match(self._VALID_URL,url).groups() + if display_id is None: + embed_webpage = self._download_webpage('http://www.snagfilms.com/embed/player?filmId=' + video_id, video_id) + + display_id = self._html_search_regex( + r"snagfilms\.com/films/title/(?P.+?)(?:/|')", + embed_webpage, + 'display_id' + ) + webpage = self._download_webpage('http://www.snagfilms.com/films/title/' + display_id, display_id) json_data = self._parse_json(self._html_search_regex( r'"data":{"film":(?P{.*?}})}', webpage, - 'data', + 'data' ), display_id) + title = json_data['title'] - video_id = json_data['id'] duration = int(json_data['duration']) description = json_data['synopsis'] categories = [category['title'] for category in json_data['categories']] + thumbnail = json_data['image'] + + if video_id is None: + video_id = json_data['id'] + embed_webpage = self._download_webpage('http://www.snagfilms.com/embed/player?filmId=' + video_id, video_id) - embed_webpage = self._download_webpage('http://www.snagfilms.com/embed/player?filmId=' + video_id, video_id) sources = self._parse_json(js_to_json(self._html_search_regex( r'sources: (?P\[.*?\])', embed_webpage, @@ -61,5 +80,6 @@ def _real_extract(self, url): 'duration': duration, 'description': description, 'categories': categories, + 'thumbnail': thumbnail, 'formats': formats, } From f39eb98bab497d8e06b9f243a8240509326678f0 Mon Sep 17 00:00:00 2001 From: remitamine Date: Sat, 27 Jun 2015 10:55:25 +0100 Subject: [PATCH 5/5] download all pages before start extracting info --- youtube_dl/extractor/snagfilms.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/youtube_dl/extractor/snagfilms.py b/youtube_dl/extractor/snagfilms.py index cd345474e..74cd2698d 100644 --- a/youtube_dl/extractor/snagfilms.py +++ b/youtube_dl/extractor/snagfilms.py @@ -34,7 +34,6 @@ def _real_extract(self, url): display_id, video_id = match(self._VALID_URL,url).groups() if display_id is None: embed_webpage = self._download_webpage('http://www.snagfilms.com/embed/player?filmId=' + video_id, video_id) - display_id = self._html_search_regex( r"snagfilms\.com/films/title/(?P.+?)(?:/|')", embed_webpage, @@ -48,16 +47,16 @@ def _real_extract(self, url): 'data' ), display_id) + if video_id is None: + video_id = json_data['id'] + embed_webpage = self._download_webpage('http://www.snagfilms.com/embed/player?filmId=' + video_id, video_id) + title = json_data['title'] duration = int(json_data['duration']) description = json_data['synopsis'] categories = [category['title'] for category in json_data['categories']] thumbnail = json_data['image'] - if video_id is None: - video_id = json_data['id'] - embed_webpage = self._download_webpage('http://www.snagfilms.com/embed/player?filmId=' + video_id, video_id) - sources = self._parse_json(js_to_json(self._html_search_regex( r'sources: (?P\[.*?\])', embed_webpage,