diff options
Diffstat (limited to 'gallery_dl/extractor/vsco.py')
| -rw-r--r-- | gallery_dl/extractor/vsco.py | 58 |
1 files changed, 26 insertions, 32 deletions
diff --git a/gallery_dl/extractor/vsco.py b/gallery_dl/extractor/vsco.py index 524bd81..42839a8 100644 --- a/gallery_dl/extractor/vsco.py +++ b/gallery_dl/extractor/vsco.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright 2019-2023 Mike Fährmann +# Copyright 2019-2025 Mike Fährmann # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as @@ -8,7 +8,7 @@ """Extractors for https://vsco.co/""" -from .common import Extractor, Message +from .common import Extractor, Message, Dispatch from .. import text, util BASE_PATTERN = r"(?:https?://)?(?:www\.)?vsco\.co" @@ -25,7 +25,7 @@ class VscoExtractor(Extractor): def __init__(self, match): Extractor.__init__(self, match) - self.user = match.group(1).lower() + self.user = match[1].lower() def items(self): videos = self.config("videos", True) @@ -47,7 +47,7 @@ class VscoExtractor(Extractor): base = img["responsive_url"].partition("/")[2] cdn, _, path = base.partition("/") if cdn.startswith("aws"): - url = "https://image-{}.vsco.co/{}".format(cdn, path) + url = f"https://image-{cdn}.vsco.co/{path}" elif cdn.isdecimal(): url = "https://image.vsco.co/" + base elif img["responsive_url"].startswith("http"): @@ -79,11 +79,11 @@ class VscoExtractor(Extractor): def _extract_preload_state(self, url): page = self.request(url, notfound=self.subcategory).text return util.json_loads(text.extr(page, "__PRELOADED_STATE__ = ", "<") - .replace('"prevPageToken":undefined,', '')) + .replace('":undefined', '":null')) def _pagination(self, url, params, token, key, extra=None): headers = { - "Referer" : "{}/{}".format(self.root, self.user), + "Referer" : f"{self.root}/{self.user}", "Authorization" : "Bearer " + token, "X-Client-Platform": "web", "X-Client-Build" : "1", @@ -93,7 +93,7 @@ class VscoExtractor(Extractor): yield from map(self._transform_media, extra) while True: - data = self.request(url, params=params, headers=headers).json() + data = self.request_json(url, params=params, headers=headers) medias = data.get(key) if not medias: return @@ -109,8 +109,7 @@ class VscoExtractor(Extractor): yield from medias params["page"] += 1 - @staticmethod - def _transform_media(media): + def _transform_media(self, media): if "responsiveUrl" not in media: return None media["_id"] = media["id"] @@ -122,8 +121,7 @@ class VscoExtractor(Extractor): media["image_meta"] = media.get("imageMeta") return media - @staticmethod - def _transform_video(media): + def _transform_video(self, media): media["is_video"] = True media["grid_name"] = "" media["video_url"] = media["playback_url"] @@ -132,17 +130,13 @@ class VscoExtractor(Extractor): return media -class VscoUserExtractor(VscoExtractor): +class VscoUserExtractor(Dispatch, VscoExtractor): """Extractor for a vsco user profile""" - subcategory = "user" pattern = USER_PATTERN + r"/?$" example = "https://vsco.co/USER" - def initialize(self): - pass - def items(self): - base = "{}/{}/".format(self.root, self.user) + base = f"{self.root}/{self.user}/" return self._dispatch_extractors(( (VscoAvatarExtractor , base + "avatar"), (VscoGalleryExtractor , base + "gallery"), @@ -158,12 +152,12 @@ class VscoGalleryExtractor(VscoExtractor): example = "https://vsco.co/USER/gallery" def images(self): - url = "{}/{}/gallery".format(self.root, self.user) + url = f"{self.root}/{self.user}/gallery" data = self._extract_preload_state(url) tkn = data["users"]["currentUser"]["tkn"] sid = str(data["sites"]["siteByUsername"][self.user]["site"]["id"]) - url = "{}/api/3.0/medias/profile".format(self.root) + url = f"{self.root}/api/3.0/medias/profile" params = { "site_id" : sid, "limit" : "14", @@ -182,14 +176,14 @@ class VscoCollectionExtractor(VscoExtractor): example = "https://vsco.co/USER/collection/1" def images(self): - url = "{}/{}/collection/1".format(self.root, self.user) + url = f"{self.root}/{self.user}/collection/1" data = self._extract_preload_state(url) tkn = data["users"]["currentUser"]["tkn"] cid = (data["sites"]["siteByUsername"][self.user] ["site"]["siteCollectionId"]) - url = "{}/api/2.0/collections/{}/medias".format(self.root, cid) + url = f"{self.root}/api/2.0/collections/{cid}/medias" params = {"page": 2, "size": "20"} return self._pagination(url, params, tkn, "medias", ( data["medias"]["byId"][mid["id"]]["media"] @@ -207,7 +201,7 @@ class VscoSpaceExtractor(VscoExtractor): example = "https://vsco.co/spaces/a1b2c3d4e5f" def images(self): - url = "{}/spaces/{}".format(self.root, self.user) + url = f"{self.root}/spaces/{self.user}" data = self._extract_preload_state(url) tkn = data["users"]["currentUser"]["tkn"] @@ -221,14 +215,14 @@ class VscoSpaceExtractor(VscoExtractor): space = data["spaces"]["byId"][sid] space["postsList"] = [posts[pid] for pid in space["postsList"]] - url = "{}/grpc/spaces/{}/posts".format(self.root, sid) + url = f"{self.root}/grpc/spaces/{sid}/posts" params = {} return self._pagination(url, params, tkn, space) def _pagination(self, url, params, token, data): headers = { "Accept" : "application/json", - "Referer" : "{}/spaces/{}".format(self.root, self.user), + "Referer" : f"{self.root}/spaces/{self.user}", "Content-Type" : "application/json", "Authorization": "Bearer " + token, } @@ -244,7 +238,7 @@ class VscoSpaceExtractor(VscoExtractor): return params["cursor"] = cursor["postcursorcontext"]["postId"] - data = self.request(url, params=params, headers=headers).json() + data = self.request_json(url, params=params, headers=headers) class VscoSpacesExtractor(VscoExtractor): @@ -254,7 +248,7 @@ class VscoSpacesExtractor(VscoExtractor): example = "https://vsco.co/USER/spaces" def items(self): - url = "{}/{}/spaces".format(self.root, self.user) + url = f"{self.root}/{self.user}/spaces" data = self._extract_preload_state(url) tkn = data["users"]["currentUser"]["tkn"] @@ -267,12 +261,12 @@ class VscoSpacesExtractor(VscoExtractor): "Authorization": "Bearer " + tkn, } # this would theoretically need to be paginated - url = "{}/grpc/spaces/user/{}".format(self.root, uid) - data = self.request(url, headers=headers).json() + url = f"{self.root}/grpc/spaces/user/{uid}" + data = self.request_json(url, headers=headers) for space in data["spacesWithRoleList"]: space = space["space"] - url = "{}/spaces/{}".format(self.root, space["id"]) + url = f"{self.root}/spaces/{space['id']}" space["_extractor"] = VscoSpaceExtractor yield Message.Queue, url, space @@ -284,7 +278,7 @@ class VscoAvatarExtractor(VscoExtractor): example = "https://vsco.co/USER/avatar" def images(self): - url = "{}/{}/gallery".format(self.root, self.user) + url = f"{self.root}/{self.user}/gallery" page = self.request(url).text piid = text.extr(page, '"profileImageId":"', '"') @@ -312,7 +306,7 @@ class VscoImageExtractor(VscoExtractor): example = "https://vsco.co/USER/media/0123456789abcdef" def images(self): - url = "{}/{}/media/{}".format(self.root, self.user, self.groups[1]) + url = f"{self.root}/{self.user}/media/{self.groups[1]}" data = self._extract_preload_state(url) media = data["medias"]["byId"].popitem()[1]["media"] return (self._transform_media(media),) @@ -325,7 +319,7 @@ class VscoVideoExtractor(VscoExtractor): example = "https://vsco.co/USER/video/012345678-9abc-def0" def images(self): - url = "{}/{}/video/{}".format(self.root, self.user, self.groups[1]) + url = f"{self.root}/{self.user}/video/{self.groups[1]}" data = self._extract_preload_state(url) media = data["medias"]["byId"].popitem()[1]["media"] |
