diff --git a/src/comic_download/reddit.py b/src/comic_download/reddit.py index ad9de76..5cf20ef 100644 --- a/src/comic_download/reddit.py +++ b/src/comic_download/reddit.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # This CLI tool allows for the download and packaging of various internet comics into .cbz files. -# Copyright (C) 2025 Markil 3 +# Copyright (C) 2026 Markil 3 # http://www.singlepilot.net # # This program is free software: you can redistribute it and/or modify @@ -39,8 +39,9 @@ from tempfile import NamedTemporaryFile import requests from PIL import Image, ImageDraw, ImageFont from bs4 import BeautifulSoup +from bs4.element import Tag -from comic_download.comic_strip import AssetRepo, ComicBook, register_comic_class +from comic_download.comic_strip import AssetRepo, ComicBook, register_comic_class, file_safe_string class RedditComic(ComicBook): """ @@ -55,7 +56,7 @@ class RedditComic(ComicBook): the subreddit and the post ID. """ super().__init__(identifier) - self.url = f"https://www.reddit.com/r/{identifier[0]}/{identifier[1]}" + self.url = f"https://www.reddit.com/r/{identifier[0]}/comments/{identifier[1]}" @classmethod def create_from_url(cls, url): @@ -64,8 +65,11 @@ class RedditComic(ComicBook): url = "https://" + url url = urlparse(url) urlpath = url.path.split('/') - subreddit = urlpath[1] - post = urlpath[2] + subreddit = urlpath[2] + if urlpath[3] == "comments": + post = urlpath[4] + else: + post = urlpath[3] return cls((subreddit, post)) @property @@ -78,49 +82,83 @@ class RedditComic(ComicBook): """The ID of the post this comic.""" return self.identifier[1] + def get_package_path(self, base_path: Path): + return Path(base_path, file_safe_string(self.author), f"{self.get_filename()}.cbz") + @classmethod def get_image_url(cls, img_el) -> str: """ Obtains the highest resolution URL for an image element """ - if "data-lazy-srcset" in img_el.attrs: + if "data-lazy-srcset" in img_el.attrs and img_el.attrs["data-lazy-srcset"]: srcsets = img_el.attrs["data-lazy-srcset"].split(', ') img_url = None max_res = 0 for srcset in srcsets: - url, resolution = srcset.split(" ") - resolution_i = int(resulution[0:-1]) - if resolution_i > max_res: - max_res = resolution_i - img_url = url - return url + if " " in srcset: + url, resolution = srcset.split(" ") + resolution_i = int(resolution[0:-1]) + if resolution_i > max_res: + max_res = resolution_i + img_url = url + elif srcset: + max_res = 0 + img_url = srcset + return img_url + elif "data-lazy-src" in img_el.attrs: + return img_el.attrs["data-lazy-src"] elif "src" in img_el.attrs: return img_el.attrs["src"] else: return None def _load_data(self): - result = requests.get(self.url) + result = requests.get(self.url, headers={"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0"}) result.raise_for_status() content = BeautifulSoup(result.content, features="lxml") + + new_url = content.find(id="canonical-url-updater") + if new_url: + result = requests.get(new_url.attrs["value"], headers={"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0"}) + result.raise_for_status + + content = BeautifulSoup(result.content, features="lxml") + + id=f"post-title-t3_{self.post}" title = content.find(id=f"post-title-t3_{self.post}") - if title and title["content"]: - self.title = title["content"] - post_content = title.next_sibling + if title and title.string: + self.title = title.string.strip() + author = content.find("a", class_="author-name") + if author and author.string: + self.author = author.string.strip() + date_el = content.find("faceplate-timeago") + if date_el and "ts" in date_el.attrs: + self.date = datetime.fromisoformat(date_el.attrs["ts"]) + post_content = None + for sibling in title.next_siblings: + if isinstance(sibling, Tag): + post_content = sibling + break post_content_image = post_content.find(id="post-image") if post_content_image: - self.image_urls.append(self.get_image_url(post_content_image)) + img_url = self.get_image_url(post_content_image) + self.image_urls.append(img_url) return post_content_list = post_content.find("ul") if post_content_list: for item in post_content_list.find_all("li"): - img_el = item.contents[0] - self.image_urls.append(image_el) + img_el = item.contents[1] + img_url = self.get_image_url(img_el) + self.image_urls.append(img_url) + return + preview_image = post_content.find("img", class_="preview-image") + if preview_image: + img_url = self.get_image_url(preview_image) + self.image_urls.append(img_url) return def _transform_images(self): self.transformed_images = self.images register_comic_class("reddit.com", RedditComic) -