2014-01-17 03:07:01 +01:00
from __future__ import unicode_literals
2013-06-23 22:31:12 +02:00
from . common import InfoExtractor
2015-11-01 02:08:19 +01:00
from . . compat import compat_urllib_parse
2013-06-23 22:31:12 +02:00
from . . utils import (
2015-11-01 13:38:11 +01:00
ExtractorError ,
2015-11-01 02:08:19 +01:00
int_or_none ,
qualities ,
2013-06-23 22:31:12 +02:00
)
class FlickrIE ( InfoExtractor ) :
2015-11-01 02:08:19 +01:00
_VALID_URL = r ' https?://(?:www \ .|secure \ .)?flickr \ .com/photos/[ \ w \ -_@]+/(?P<id> \ d+) '
2013-06-27 20:46:46 +02:00
_TEST = {
2014-01-17 03:07:01 +01:00
' url ' : ' http://www.flickr.com/photos/forestwander-nature-pictures/5645318632/in/photostream/ ' ,
2015-11-01 02:08:19 +01:00
' md5 ' : ' 164fe3fa6c22e18d448d4d5af2330f31 ' ,
2014-01-17 03:07:01 +01:00
' info_dict ' : {
2014-09-24 10:46:33 +02:00
' id ' : ' 5645318632 ' ,
2015-11-01 02:08:19 +01:00
' ext ' : ' mpg ' ,
' description ' : ' Waterfalls in the Springtime at Dark Hollow Waterfalls. These are located just off of Skyline Drive in Virginia. They are only about 6/10 of a mile hike but it is a pretty steep hill and a good climb back up. ' ,
' title ' : ' Dark Hollow Waterfalls ' ,
' duration ' : 19 ,
' timestamp ' : 1303528740 ,
' upload_date ' : ' 20110423 ' ,
' uploader_id ' : ' 10922353@N03 ' ,
' uploader ' : ' Forest Wander ' ,
' comment_count ' : int ,
2015-12-21 00:20:22 +01:00
' view_count ' : int ,
' tags ' : list ,
2013-06-27 20:46:46 +02:00
}
}
2013-06-23 22:31:12 +02:00
2015-11-01 02:08:19 +01:00
_API_BASE_URL = ' https://api.flickr.com/services/rest? '
2015-04-22 19:24:14 +02:00
2015-11-01 13:23:23 +01:00
def _call_api ( self , method , video_id , api_key , note , secret = None ) :
2015-11-01 02:08:19 +01:00
query = {
' photo_id ' : video_id ,
' method ' : ' flickr. %s ' % method ,
2015-11-01 13:23:23 +01:00
' api_key ' : api_key ,
2015-11-01 02:08:19 +01:00
' format ' : ' json ' ,
' nojsoncallback ' : 1 ,
}
if secret :
query [ ' secret ' ] = secret
2015-11-01 13:38:11 +01:00
data = self . _download_json ( self . _API_BASE_URL + compat_urllib_parse . urlencode ( query ) , video_id , note )
if data [ ' stat ' ] != ' ok ' :
raise ExtractorError ( data [ ' message ' ] )
return data
2013-06-23 22:31:12 +02:00
2015-11-01 02:08:19 +01:00
def _real_extract ( self , url ) :
video_id = self . _match_id ( url )
2013-06-23 22:31:12 +02:00
2015-12-21 22:10:16 +01:00
api_key = self . _download_json (
' https://www.flickr.com/hermes_error_beacon.gne ' , video_id ,
' Downloading api key ' ) [ ' site_key ' ]
2015-11-01 13:23:23 +01:00
2015-12-21 22:10:16 +01:00
video_info = self . _call_api (
' photos.getInfo ' , video_id , api_key , ' Downloading video info ' ) [ ' photo ' ]
2015-11-01 02:08:19 +01:00
if video_info [ ' media ' ] == ' video ' :
2015-12-21 22:10:16 +01:00
streams = self . _call_api (
' video.getStreamInfo ' , video_id , api_key ,
' Downloading streams info ' , video_info [ ' secret ' ] ) [ ' streams ' ]
2013-06-23 22:31:12 +02:00
2015-12-21 22:10:16 +01:00
preference = qualities (
[ ' 288p ' , ' iphone_wifi ' , ' 100 ' , ' 300 ' , ' 700 ' , ' 360p ' , ' appletv ' , ' 720p ' , ' 1080p ' , ' orig ' ] )
2013-06-23 22:31:12 +02:00
2015-11-01 02:08:19 +01:00
formats = [ ]
for stream in streams [ ' stream ' ] :
stream_type = str ( stream . get ( ' type ' ) )
formats . append ( {
' format_id ' : stream_type ,
' url ' : stream [ ' _content ' ] ,
' preference ' : preference ( stream_type ) ,
} )
self . _sort_formats ( formats )
2013-06-23 22:31:12 +02:00
2015-11-01 02:08:19 +01:00
owner = video_info . get ( ' owner ' , { } )
2013-06-23 22:31:12 +02:00
2015-11-01 02:08:19 +01:00
return {
' id ' : video_id ,
' title ' : video_info [ ' title ' ] [ ' _content ' ] ,
' description ' : video_info . get ( ' description ' , { } ) . get ( ' _content ' ) ,
' formats ' : formats ,
' timestamp ' : int_or_none ( video_info . get ( ' dateuploaded ' ) ) ,
' duration ' : int_or_none ( video_info . get ( ' video ' , { } ) . get ( ' duration ' ) ) ,
' uploader_id ' : owner . get ( ' nsid ' ) ,
' uploader ' : owner . get ( ' realname ' ) ,
' comment_count ' : int_or_none ( video_info . get ( ' comments ' , { } ) . get ( ' _content ' ) ) ,
2015-12-21 00:20:22 +01:00
' view_count ' : int_or_none ( video_info . get ( ' views ' ) ) ,
' tags ' : [ tag . get ( ' _content ' ) for tag in video_info . get ( ' tags ' , { } ) . get ( ' tag ' , [ ] ) ]
2015-11-01 02:08:19 +01:00
}
2015-11-05 18:01:13 +01:00
else :
raise ExtractorError ( ' not a video ' , expected = True )