3 from .common
import InfoExtractor
12 class GfycatIE(InfoExtractor
):
13 _VALID_URL
= r
'https?://(?:(?:www|giant|thumbs)\.)?gfycat\.com/(?i:ru/|ifr/|gifs/detail/)?(?P<id>[^-/?#\."\']+)'
15 'url
': 'http
://gfycat
.com
/DeadlyDecisiveGermanpinscher
',
17 'id': 'DeadlyDecisiveGermanpinscher
',
19 'title
': 'Ghost
in the Shell
',
20 'timestamp
': 1410656006,
21 'upload_date
': '20140914',
22 'uploader
': 'anonymous
',
28 'uploader_id
': 'anonymous
',
32 'url
': 'http
://gfycat
.com
/ifr
/JauntyTimelyAmazontreeboa
',
34 'id': 'JauntyTimelyAmazontreeboa
',
36 'title
': 'JauntyTimelyAmazontreeboa
',
37 'timestamp
': 1411720126,
38 'upload_date
': '20140926',
39 'uploader
': 'anonymous
',
45 'uploader_id
': 'anonymous
',
49 'url
': 'https
://gfycat
.com
/alienatedsolidgreathornedowl
',
51 'id': 'alienatedsolidgreathornedowl
',
53 'upload_date
': '20211226',
54 'uploader_id
': 'reactions
',
55 'timestamp
': 1640536930,
58 'title
': 'Ingrid Michaelson
, Zooey Deschanel
- Merry Christmas Happy New Year
',
61 'duration
': 2.9583333333333335,
62 'uploader
': 'Reaction GIFs
',
66 'url
': 'https
://gfycat
.com
/ru
/RemarkableDrearyAmurstarfish
',
69 'url
': 'https
://gfycat
.com
/gifs
/detail
/UnconsciousLankyIvorygull
',
72 'url
': 'https
://gfycat
.com
/acceptablehappygoluckyharborporpoise
-baseball
',
75 'url
': 'https
://thumbs
.gfycat
.com
/acceptablehappygoluckyharborporpoise
-size_restricted
.gif
',
78 'url
': 'https
://giant
.gfycat
.com
/acceptablehappygoluckyharborporpoise
.mp4
',
81 'url
': 'http
://gfycat
.com
/IFR
/JauntyTimelyAmazontreeboa
',
86 def _extract_urls(webpage):
89 for mobj in re.finditer(
90 r'<(?
:iframe|source
)[^
>]+\bsrc
=["\'](?P<url>%s)' % GfycatIE._VALID_URL,
93 def _real_extract(self, url):
94 video_id = self._match_id(url)
96 gfy = self._download_json(
97 'https://api.gfycat.com/v1/gfycats/%s' % video_id,
98 video_id, 'Downloading video info')
100 raise ExtractorError('Gfycat said: ' + gfy['error'], expected=True)
103 title = gfy.get('title') or gfy['gfyName']
104 description = gfy.get('description')
105 timestamp = int_or_none(gfy.get('createDate'))
106 uploader = gfy.get('userName') or gfy.get('username')
107 view_count = int_or_none(gfy.get('views'))
108 like_count = int_or_none(gfy.get('likes'))
109 dislike_count = int_or_none(gfy.get('dislikes'))
110 age_limit = 18 if gfy.get('nsfw') == '1' else 0
112 width = int_or_none(gfy.get('width'))
113 height = int_or_none(gfy.get('height'))
114 fps = int_or_none(gfy.get('frameRate'))
115 num_frames = int_or_none(gfy.get('numFrames'))
117 duration = float_or_none(num_frames, fps) if num_frames and fps else None
119 categories = gfy.get('tags') or gfy.get('extraLemmas') or []
121 FORMATS = ('gif', 'webm', 'mp4')
122 quality = qualities(FORMATS)
125 for format_id in FORMATS:
126 video_url = gfy.get('%sUrl' % format_id)
129 filesize = int_or_none(gfy.get('%sSize' % format_id))
132 'format_id': format_id,
136 'filesize': filesize,
137 'quality': quality(format_id),
139 self._sort_formats(formats)
144 'description': description,
145 'timestamp': timestamp,
146 'uploader': gfy.get('userDisplayName') or uploader,
147 'uploader_id': uploader,
148 'duration': duration,
149 'view_count': view_count,
150 'like_count': like_count,
151 'dislike_count': dislike_count,
152 'categories': categories,
153 'age_limit': age_limit,