diff --git a/docs/supportedsites.md b/docs/supportedsites.md index f779217e18..a6b5cfb140 100644 --- a/docs/supportedsites.md +++ b/docs/supportedsites.md @@ -547,6 +547,12 @@ Consider all listed sites to potentially be NSFW. Blogs, Posts + + LOFTER + https://www.lofter.com/ + Blog Posts, Posts + + Luscious https://members.luscious.net/ diff --git a/gallery_dl/extractor/lofter.py b/gallery_dl/extractor/lofter.py index bb167761d3..412b6b9fbb 100644 --- a/gallery_dl/extractor/lofter.py +++ b/gallery_dl/extractor/lofter.py @@ -27,9 +27,8 @@ def items(self): post = post["post"] post["blog_name"] = post["blogInfo"]["blogName"] - + post["date"] = text.parse_timestamp(post["publishTime"] // 1000) post_type = post["type"] - image_urls = [] # Article if post_type == 1: @@ -56,6 +55,7 @@ def items(self): image_urls = [x.partition("?")[0] for x in image_urls] else: + image_urls = () self.log.warning( "%s: Unsupported post type '%s'.", post["id"], post_type) @@ -73,7 +73,7 @@ class LofterPostExtractor(LofterExtractor): """Extractor for a lofter post""" subcategory = "post" pattern = r"(?:https?://)?[\w-]+\.lofter\.com/post/([0-9a-f]+)_([0-9a-f]+)" - example = "https://blog_name.lofter.com/post/12345678_90abcdef" + example = "https://BLOG.lofter.com/post/12345678_90abcdef" def posts(self): blog_id, post_id = self.groups @@ -89,21 +89,39 @@ class LofterBlogPostsExtractor(LofterExtractor): r"www\.lofter\.com/front/blog/home-page/([\w-]+)|" # https://.lofter.com/ r"([\w-]+)\.lofter\.com" - r")") - example = "https://blog_name.lofter.com/" + r")/?(?:$|\?|#)") + example = "https://BLOG.lofter.com/" def posts(self): blog_name = self.groups[0] or self.groups[1] - posts = self.api.blog_posts(blog_name) - return posts + return self.api.blog_posts(blog_name) class LofterAPI(): + def __init__(self, extractor): self.extractor = extractor + def blog_posts(self, blog_name): + endpoint = "/v2.0/blogHomePage.api" + params = { + "method": "getPostLists", + "offset": 0, + "limit": 200, + "blogdomain": blog_name + ".lofter.com", + } + return self._pagination(endpoint, params) + + def post(self, blog_id, post_id): + endpoint = "/oldapi/post/detail.api" + params = { + "targetblogid": blog_id, + "postid": post_id, + } + return self._call(endpoint, params)["posts"][0] + def _call(self, endpoint, data): - url = "https://api.lofter.com{}".format(endpoint) + url = "https://api.lofter.com" + endpoint params = { 'product': 'lofter-android-7.9.10' } @@ -115,36 +133,15 @@ def _call(self, endpoint, data): self.extractor.log.debug("Server response: %s", info) raise exception.StopExtraction("API request failed") - return info - - def blog_posts(self, blog_name): - endpoint = "/v2.0/blogHomePage.api" - params = { - "method": "getPostLists", - "offset": 0, - "limit": 200, - "blogdomain": "{}.lofter.com".format(blog_name), - } + return info["response"] + def _pagination(self, endpoint, params): while True: data = self._call(endpoint, params) - posts = data["response"]["posts"] + posts = data["posts"] - for post in posts: - yield post + yield from posts - if params["offset"] + len(posts) < data["response"]["offset"]: + if params["offset"] + len(posts) < data["offset"]: break - - params["offset"] = data["response"]["offset"] - - def post(self, blog_id, post_id): - endpoint = "/oldapi/post/detail.api" - params = { - "targetblogid": blog_id, - "postid": post_id, - } - data = self._call(endpoint, params) - posts = data["response"]["posts"] - post = posts[0] - return post + params["offset"] = data["offset"] diff --git a/scripts/supportedsites.py b/scripts/supportedsites.py index aafdb0d27c..a101266575 100755 --- a/scripts/supportedsites.py +++ b/scripts/supportedsites.py @@ -86,6 +86,7 @@ "kemonoparty" : "Kemono", "koharu" : "SchaleNetwork", "livedoor" : "livedoor Blog", + "lofter" : "LOFTER", "ohpolly" : "Oh Polly", "omgmiamiswimwear": "Omg Miami Swimwear", "mangadex" : "MangaDex", @@ -265,6 +266,9 @@ "lensdump": { "albums": "", }, + "lofter": { + "blog-posts": "Blog Posts", + }, "mangadex": { "feed" : "Followed Feed", }, diff --git a/test/results/lofter.py b/test/results/lofter.py new file mode 100644 index 0000000000..99a8f570d4 --- /dev/null +++ b/test/results/lofter.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- + +# 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 +# published by the Free Software Foundation. + +from gallery_dl.extractor import lofter + + +__tests__ = ( +{ + "#url" : "https://gengar563.lofter.com/post/1e82da8c_1c98dae1b", + "#class": lofter.LofterPostExtractor, + "#urls" : ( + "https://imglf3.lf127.net/img/S1d2QlVsWkJhSW1qcnpIS0ZSa3ZJQ1RxY0lYaU1UUE9tQ0NvUE9rVXFpOFFEVzMwbnQ4aEFnPT0.jpg", + "https://imglf3.lf127.net/img/S1d2QlVsWkJhSW1qcnpIS0ZSa3ZJRWlXYTRVOEpXTU9TSGt3TjBDQ0JFZVpZMEJtWjFneVNBPT0.png", + "https://imglf6.lf127.net/img/S1d2QlVsWkJhSW1qcnpIS0ZSa3ZJR1d3Y2VvbTNTQlIvdFU1WWlqZHEzbjI4MFVNZVdoN3VBPT0.png", + "https://imglf6.lf127.net/img/S1d2QlVsWkJhSW1qcnpIS0ZSa3ZJTi83NDRDUjNvd3hySGxEZFovd2hwbi9oaG9NQ1hOUkZ3PT0.png", + "https://imglf4.lf127.net/img/S1d2QlVsWkJhSW1qcnpIS0ZSa3ZJUFczb2RKSVlpMHJkNy9kc3BSQVQvQm5DNzB4eVhxay9nPT0.png", + "https://imglf4.lf127.net/img/S1d2QlVsWkJhSW1qcnpIS0ZSa3ZJSStJZE9RYnJURktHazdIVHNNMjQ5eFJldHVTQy9XbDB3PT0.png", + "https://imglf3.lf127.net/img/S1d2QlVsWkJhSW1qcnpIS0ZSa3ZJSzFCWFlnUWgzb01DcUdpT1lreG5yQjJVMkhGS09HNGR3PT0.png", + ), + + "blog_name": "gengar563", + "content" : "

发了三次发不出有毒……

\n

二部运动au  性转ac注意

\n

失去耐心.jpg

", + "date" : "dt:2020-06-04 12:51:42", + "id" : 7676472859, +}, + +{ + "#url" : "https://wooden-brain.lofter.com/post/1e60de5b_1c9bf8efb", + "#comment": "video", + "#class" : lofter.LofterPostExtractor, + "#urls" : ( + "https://vodm2lzexwq.vod.126.net/vodm2lzexwq/Pc5jg1nL_3039990631_sd.mp4?resId=254486990bfa2cd7aa860229db639341_3039990631_1&sign=4j02HTHXqNfhaF%2B%2FO14Ny%2F9SMNZj%2FIjpJDCqXfYa4aM%3D", + ), + + "blog_name": "wooden-brain", + "date" : "dt:2020-06-24 11:01:59", + "id" : 7679741691, +}, + +{ + "#url" : "https://gengar563.lofter.com/", + "#class": lofter.LofterBlogPostsExtractor, + "#range": "1-25", + "#count": 25, + + "blog_name": "gengar563", + "date" : "type:datetime", + "id" : int, +}, + +{ + "#url" : "https://www.lofter.com/front/blog/home-page/gengar563", + "#class": lofter.LofterBlogPostsExtractor, +}, + +)