2 from __future__
import unicode_literals
6 from .common
import InfoExtractor
15 class GfycatIE(InfoExtractor
):
16 _VALID_URL
= r
'(?i)https?://(?:(?:www|giant|thumbs)\.)?gfycat\.com/(?:ru/|ifr/|gifs/detail/)?(?P<id>[^-/?#\."\']+)'
18 'url
': 'http
://gfycat
.com
/DeadlyDecisiveGermanpinscher
',
20 'id': 'DeadlyDecisiveGermanpinscher
',
22 'title
': 'Ghost
in the Shell
',
23 'timestamp
': 1410656006,
24 'upload_date
': '20140914',
25 'uploader
': 'anonymous
',
31 'uploader_id
': 'anonymous
',
35 'url
': 'http
://gfycat
.com
/ifr
/JauntyTimelyAmazontreeboa
',
37 'id': 'JauntyTimelyAmazontreeboa
',
39 'title
': 'JauntyTimelyAmazontreeboa
',
40 'timestamp
': 1411720126,
41 'upload_date
': '20140926',
42 'uploader
': 'anonymous
',
48 'uploader_id
': 'anonymous
',
52 'url
': 'https
://gfycat
.com
/alienatedsolidgreathornedowl
',
54 'id': 'alienatedsolidgreathornedowl
',
56 'upload_date
': '20211226',
57 'uploader_id
': 'reactions
',
58 'timestamp
': 1640536930,
61 'title
': 'Ingrid Michaelson
, Zooey Deschanel
- Merry Christmas Happy New Year
',
64 'duration
': 2.9583333333333335,
65 'uploader
': 'Reaction GIFs
',
69 'url
': 'https
://gfycat
.com
/ru
/RemarkableDrearyAmurstarfish
',
72 'url
': 'https
://gfycat
.com
/gifs
/detail
/UnconsciousLankyIvorygull
',
75 'url
': 'https
://gfycat
.com
/acceptablehappygoluckyharborporpoise
-baseball
',
78 'url
': 'https
://thumbs
.gfycat
.com
/acceptablehappygoluckyharborporpoise
-size_restricted
.gif
',
81 'url
': 'https
://giant
.gfycat
.com
/acceptablehappygoluckyharborporpoise
.mp4
',
84 'url
': 'http
://gfycat
.com
/IFR
/JauntyTimelyAmazontreeboa
',
89 def _extract_urls(webpage):
92 for mobj in re.finditer(
93 r'<(?
:iframe|source
)[^
>]+\bsrc
=["\'](?P<url>%s)' % GfycatIE._VALID_URL,
96 def _real_extract(self, url):
97 video_id = self._match_id(url)
99 gfy = self._download_json(
100 'https://api.gfycat.com/v1/gfycats/%s' % video_id,
101 video_id, 'Downloading video info')
103 raise ExtractorError('Gfycat said: ' + gfy['error'], expected=True)
106 title = gfy.get('title') or gfy['gfyName']
107 description = gfy.get('description')
108 timestamp = int_or_none(gfy.get('createDate'))
109 uploader = gfy.get('userName') or gfy.get('username')
110 view_count = int_or_none(gfy.get('views'))
111 like_count = int_or_none(gfy.get('likes'))
112 dislike_count = int_or_none(gfy.get('dislikes'))
113 age_limit = 18 if gfy.get('nsfw') == '1' else 0
115 width = int_or_none(gfy.get('width'))
116 height = int_or_none(gfy.get('height'))
117 fps = int_or_none(gfy.get('frameRate'))
118 num_frames = int_or_none(gfy.get('numFrames'))
120 duration = float_or_none(num_frames, fps) if num_frames and fps else None
122 categories = gfy.get('tags') or gfy.get('extraLemmas') or []
124 FORMATS = ('gif', 'webm', 'mp4')
125 quality = qualities(FORMATS)
128 for format_id in FORMATS:
129 video_url = gfy.get('%sUrl' % format_id)
132 filesize = int_or_none(gfy.get('%sSize' % format_id))
135 'format_id': format_id,
139 'filesize': filesize,
140 'quality': quality(format_id),
142 self._sort_formats(formats)
147 'description': description,
148 'timestamp': timestamp,
149 'uploader': gfy.get('userDisplayName') or uploader,
150 'uploader_id': uploader,
151 'duration': duration,
152 'view_count': view_count,
153 'like_count': like_count,
154 'dislike_count': dislike_count,
155 'categories': categories,
156 'age_limit': age_limit,