from bs4 import BeautifulSoup import os import requests from time import sleep from urllib.parse import urlparse, urljoin import sys def download_comic(url, download_dir): """Download a comic and return the previous comic URL""" if not url: return None try: # Fetch the page headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'} response = requests.get(url, headers=headers, timeout=15) response.raise_for_status() html_text = response.text except requests.RequestException as e: print(f"āŒ Error fetching {url}: {e}") return None soup = BeautifulSoup(html_text, "html.parser") # Get previous comic URL prev_link = soup.find("a", class_="previous-comic", href=True) if prev_link is None: print("āš ļø No previous comic link found (might be the first comic)") return None prev_url = prev_link["href"] # Make absolute URL if needed if not prev_url.startswith('http'): prev_url = urljoin(url, prev_url) print(f"šŸ”— Previous: {prev_url}") # Find comic image in spliced-comic div comic_div = soup.find("div", {"id": "spliced-comic"}) if comic_div is None: print("āŒ Can't find div#spliced-comic") return prev_url img_tag = comic_div.find("img") if img_tag is None: print("āŒ No img tag found in div#spliced-comic") return prev_url img_url = img_tag.get("src") or img_tag.get("data-src") if not img_url: print("āŒ No src or data-src attribute found") return prev_url # Make absolute URL if not img_url.startswith('http'): img_url = urljoin(url, img_url) print(f"šŸ–¼ļø Image: {img_url}") # Download the image try: img_data = requests.get(img_url, headers=headers, timeout=30) img_data.raise_for_status() except requests.RequestException as e: print(f"āŒ Failed to download image: {e}") return prev_url # Create download directory if it doesn't exist os.makedirs(download_dir, exist_ok=True) # Get filename from URL parsed_url = urlparse(img_url) filename = os.path.basename(parsed_url.path) # If filename is empty or has no extension, create one if not filename or '.' not in filename: filename = f"comic_{len(os.listdir(download_dir)) + 1:03d}.jpg" # Save the file filepath = os.path.join(download_dir, filename) # Check if file already exists if os.path.exists(filepath): print(f"ā­ļø {filename} already exists, skipping") return prev_url try: with open(filepath, "wb") as handler: handler.write(img_data.content) print(f"āœ… {filename} downloaded ({len(img_data.content)} bytes)") except IOError as e: print(f"āŒ Failed to save {filename}: {e}") return prev_url return prev_url def main(): print("╔═══════════════════════════════════╗") print("ā•‘ StoneToss Comic Downloader ā•‘") print("ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•") print() url = "https://stonetoss.com/" download_dir = "comic" max_comics = 50 downloaded = 0 print(f"šŸ“š Downloading up to {max_comics} comics...") print() for i in range(max_comics): print(f"[{i+1}/{max_comics}] Processing...") # Download the comic and get the previous URL prev_url = download_comic(url, download_dir) if prev_url is None: print("šŸ Reached the first comic or encountered an error") break downloaded += 1 url = prev_url sleep(1) # Be nice to the server print() print("╔═══════════════════════════════════╗") print(f"ā•‘ āœ… Downloaded {downloaded} comics ā•‘") print(f"ā•‘ šŸ“ Saved to: ./{download_dir}/ ā•‘") print("ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•") if __name__ == "__main__": try: main() except KeyboardInterrupt: print("\nā¹ļø Interrupted by user") sys.exit(0) except Exception as e: print(f"\nāŒ Unexpected error: {e}") sys.exit(1)