Jelajahi Sumber

Added VineUserIE extractor for vine user timeline

Added vine user timeline extractor using unofficial
vine api user profile and timeline api endpoints.
Jason Normore 11 tahun lalu
induk
melakukan
ea783d01e1
3 mengubah file dengan 48 tambahan dan 1 penghapusan
  1. 8 0
      test/test_playlists.py
  2. 4 1
      youtube_dl/extractor/__init__.py
  3. 36 0
      youtube_dl/extractor/vine.py

+ 8 - 0
test/test_playlists.py

@@ -23,6 +23,7 @@ from youtube_dl.extractor import (
     VimeoUserIE,
     VimeoAlbumIE,
     VimeoGroupsIE,
+    VineUserIE,
     UstreamChannelIE,
     SoundcloudSetIE,
     SoundcloudUserIE,
@@ -102,6 +103,13 @@ class TestPlaylists(unittest.TestCase):
         self.assertEqual(result['title'], 'Rolex Awards for Enterprise')
         self.assertTrue(len(result['entries']) > 72)
 
+    def test_vine_user(self):
+        dl = FakeYDL()
+        ie = VineUserIE(dl)
+        result = ie.extract('https://vine.co/Visa')
+        self.assertIsPlaylist(result)
+        self.assertTrue(len(result['entries']) >= 50)
+
     def test_ustream_channel(self):
         dl = FakeYDL()
         ie = UstreamChannelIE(dl)

+ 4 - 1
youtube_dl/extractor/__init__.py

@@ -305,7 +305,10 @@ from .vimeo import (
     VimeoReviewIE,
     VimeoWatchLaterIE,
 )
-from .vine import VineIE
+from .vine import (
+    VineIE,
+    VineUserIE,
+)
 from .viki import VikiIE
 from .vk import VKIE
 from .vube import VubeIE

+ 36 - 0
youtube_dl/extractor/vine.py

@@ -2,6 +2,7 @@ from __future__ import unicode_literals
 
 import re
 import json
+import itertools
 
 from .common import InfoExtractor
 from ..utils import unified_strdate
@@ -58,3 +59,38 @@ class VineIE(InfoExtractor):
             'repost_count': data['reposts']['count'],
             'formats': formats,
         }
+
+class VineUserIE(InfoExtractor):
+    IE_NAME = 'vine:user'
+    _VALID_URL = r'(?:https?://)?vine\.co/(?P<user>[^/]+)/?(\?.*)?$'
+    _VINE_BASE_URL = "https://vine.co/"
+
+    def _profile_url(self, user):
+        return "%sapi/users/profiles/vanity/%s"%(self._VINE_BASE_URL, user)
+
+    def _timeline_url(self, user_id, page=1):
+        return "%sapi/timelines/users/%s?page=%s"%(self._VINE_BASE_URL, user_id, page)
+
+    def _profile_data(self, user):
+        return self._download_json(self._profile_url(user), user)
+
+    def _timeline_data(self, user):
+        profile_data = self._profile_data(user)
+        user_id = profile_data['data']['userId']
+        timeline_data = []
+        for pagenum in itertools.count(1):
+            timeline_page = self._download_json(self._timeline_url(user_id, pagenum), user)
+            timeline_data.extend(timeline_page['data']['records'])
+            if timeline_page['data']['nextPage'] is None:
+                break
+        return timeline_data
+
+    def _extract_videos(self, user):
+        timeline_data = self._timeline_data(user)
+        entries = [self.url_result(e['permalinkUrl'], 'Vine') for e in timeline_data]
+        return self.playlist_result(entries, user)
+
+    def _real_extract(self, url):
+        mobj = re.match(self._VALID_URL, url)
+        user = mobj.group('user')
+        return self._extract_videos(user)