diff --git a/docs/supportedsites.md b/docs/supportedsites.md index dc716619..23c65c96 100644 --- a/docs/supportedsites.md +++ b/docs/supportedsites.md @@ -136,7 +136,7 @@ Consider all listed sites to potentially be NSFW. Bilibili https://www.bilibili.com/ - Articles, User Articles + Articles, User Articles, User Article Favorites diff --git a/gallery_dl/extractor/bilibili.py b/gallery_dl/extractor/bilibili.py index b9de1656..597ec40e 100644 --- a/gallery_dl/extractor/bilibili.py +++ b/gallery_dl/extractor/bilibili.py @@ -81,6 +81,27 @@ class BilibiliArticleExtractor(BilibiliExtractor): yield Message.Url, url, text.nameext_from_url(url, article) +class BilibiliUserArticlesFavoriteExtractor(BilibiliExtractor): + subcategory = "user-articles-favorite" + pattern = (r"(?:https?://)?space\.bilibili\.com" + r"/(\d+)/favlist\?fid=opus") + example = "https://space.bilibili.com/12345/favlist?fid=opus" + _warning = True + + def _init(self): + BilibiliExtractor._init(self) + if self._warning: + if not self.cookies_check(("SESSDATA",)): + self.log.error("'SESSDATA' cookie required") + BilibiliUserArticlesFavoriteExtractor._warning = False + + def items(self): + for article in self.api.user_favlist(): + article["_extractor"] = BilibiliArticleExtractor + url = "{}/opus/{}".format(self.root, article["opus_id"]) + yield Message.Queue, url, article + + class BilibiliAPI(): def __init__(self, extractor): self.extractor = extractor @@ -122,3 +143,28 @@ class BilibiliAPI(): raise exception.StopExtraction( "%s: Unable to extract INITIAL_STATE data", article_id) self.extractor.wait(seconds=300) + + def user_favlist(self): + endpoint = "/opus/feed/fav" + params = {"page": 1, "page_size": 20} + + while True: + data = self._call(endpoint, params)["data"] + + yield from data["items"] + + if not data.get("has_more"): + break + params["page"] += 1 + + def login_user_id(self): + url = "https://api.bilibili.com/x/space/v2/myinfo" + data = self.extractor.request(url).json() + + if data["code"] != 0: + self.extractor.log.debug("Server response: %s", data) + raise exception.StopExtraction("API request failed,Are you login?") + try: + return data["data"]["profile"]["mid"] + except Exception: + raise exception.StopExtraction("API request failed") diff --git a/scripts/supportedsites.py b/scripts/supportedsites.py index 92fa4268..60e43d87 100755 --- a/scripts/supportedsites.py +++ b/scripts/supportedsites.py @@ -206,6 +206,7 @@ SUBCATEGORY_MAP = { }, "bilibili": { "user-articles": "User Articles", + "user-articles-favorite": "User Article Favorites", }, "bluesky": { "posts": "", diff --git a/test/results/bilibili.py b/test/results/bilibili.py index d608f78b..2028dc3a 100644 --- a/test/results/bilibili.py +++ b/test/results/bilibili.py @@ -65,4 +65,10 @@ __tests__ = ( "#class" : bilibili.BilibiliUserArticlesExtractor, }, +{ + "#url" : "https://space.bilibili.com/405279279/favlist?fid=opus", + "#class" : bilibili.BilibiliUserArticlesFavoriteExtractor, + "#auth" : True, +}, + )