š
Online Notepad
+
ADD NEW TEXT
Untitled Note
Last saved: May 17, 10:54 AM
Untitled Note
Last saved: Apr 19, 8:09 AM
Untitled Note
Last saved: Apr 19, 7:24 AM
Untitled Note
Last saved: Apr 19, 7:21 AM
Untitled Note
Last saved: Apr 19, 7:19 AM
Untitled Note
Last saved: Apr 19, 6:19 AM
Untitled Note
Last saved: Apr 19, 5:48 AM
Untitled Note
Last saved: Apr 19, 5:44 AM
Untitled Note
Last saved: Apr 11, 10:20 AM
Untitled Note
Last saved: Apr 11, 8:34 AM
Untitled Note
Last saved: Apr 11, 8:23 AM
Untitled Note
Last saved: Apr 11, 8:14 AM
Untitled Note
Last saved: Apr 11, 7:44 AM
Untitled Note
Last saved: Apr 11, 7:43 AM
Untitled Note
Last saved: Apr 11, 7:35 AM
Untitled Note
Last saved: Apr 11, 7:32 AM
š¾ Save to Server
šļø Delete
https://www.facebook.com/profile.php?id=61570641629179&sk=reels_tab import tkinter as tk from tkinter import scrolledtext, messagebox import threading import queue import os import re import shutil from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.firefox.service import Service as FirefoxService from webdriver_manager.firefox import GeckoDriverManager # ā Auto driver from time import sleep import subprocess import csv import http.cookiejar import traceback # ā NEW for better error details class ReelsDownloaderGUI: def __init__(self, root): self.root = root self.root.title("Facebook Reels Downloader - STABLE v8.3 (Improved Scrolling) [FIREFOX + webdriver-manager]") self.root.geometry("950x720") self.root.configure(bg="#f0f0f0") self.log_queue = queue.Queue() # === PERSISTENT FIREFOX PROFILE === self.profile_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "firefox_profile") os.makedirs(self.profile_dir, exist_ok=True) tk.Label(root, text="Facebook Reels Bulk Downloader", font=("Arial", 16, "bold"), bg="#f0f0f0").pack(pady=10) tk.Label(root, text="Folder Name:", bg="#f0f0f0").pack(anchor="w", padx=20) self.folder_var = tk.StringVar(value="tanweer_reels") tk.Entry(root, textvariable=self.folder_var, width=85).pack(padx=20, pady=5) tk.Label(root, text="Reels Tab URL:", bg="#f0f0f0").pack(anchor="w", padx=20) self.url_var = tk.StringVar(value="https://www.facebook.com/profile.php?id=61573238759323&sk=reels_tab") tk.Entry(root, textvariable=self.url_var, width=85).pack(padx=20, pady=5) tk.Label(root, text="Facebook Cookies (Netscape format) - ONE-TIME ONLY:", bg="#f0f0f0").pack(anchor="w", padx=20) self.cookies_text = scrolledtext.ScrolledText(root, height=10, width=105) self.cookies_text.pack(padx=20, pady=5) saved_cookies_path = "saved_cookies.txt" profile_has_cookies = os.path.exists(os.path.join(self.profile_dir, "cookies.sqlite")) if os.path.exists(saved_cookies_path) or profile_has_cookies: self.cookies_text.insert(tk.INSERT, "=== COOKIES ALREADY SAVED IN PERSISTENT FIREFOX PROFILE ===\n\n" "ā One-time import completed!\n" "ā Leave this box BLANK for all future downloads.\n" "ā Firefox will automatically use the saved login session.\n\n" "Only paste new cookies here if you want to UPDATE your login.") else: self.cookies_text.insert(tk.INSERT, "Paste your Facebook Cookies (Netscape format) here\n" "ā This is ONLY needed the FIRST time.\n" "ā After the first successful download, leave this box blank forever.") btn_frame = tk.Frame(root, bg="#f0f0f0") btn_frame.pack(pady=12) tk.Button(btn_frame, text="š Start Download - STABLE v8.3 [FIREFOX + Auto Driver]", font=("Arial", 13, "bold"), bg="#1877f2", fg="white", height=2, command=self.start_download_thread).pack(side="left", padx=15) tk.Button(btn_frame, text="Clear Log", command=self.clear_log).pack(side="left", padx=10) tk.Button(btn_frame, text="Exit", command=root.quit).pack(side="left", padx=10) tk.Label(root, text="Live Log:", bg="#f0f0f0").pack(anchor="w", padx=20) self.log_text = scrolledtext.ScrolledText(root, height=19, bg="black", fg="#00ff00", font=("Consolas", 10)) self.log_text.pack(padx=20, pady=5, fill="both", expand=True) self.update_log() def log(self, message): self.log_queue.put(message) def update_log(self): while not self.log_queue.empty(): msg = self.log_queue.get_nowait() self.log_text.insert(tk.END, msg + "\n") self.log_text.see(tk.END) self.root.after(100, self.update_log) def clear_log(self): self.log_text.delete("1.0", tk.END) def start_download_thread(self): thread = threading.Thread(target=self.download_process, daemon=True) thread.start() def download_process(self): folder_name = self.folder_var.get().strip() or "facebook_reels" url = self.url_var.get().strip() cookies_content = self.cookies_text.get("1.0", tk.END).strip() if not url: messagebox.showerror("Error", "Please enter Reels URL") return self.log("=== STABLE v8.3 - Persistent Firefox Profile + webdriver-manager ===") self.log("ā Auto-downloads latest geckodriver (no manual path needed)") self.log(f"Target: {url}") self.log(f"Save folder: output/{folder_name}\n") saved_cookies_path = "saved_cookies.txt" apply_cookies = False if cookies_content and not cookies_content.startswith("=== COOKIES ALREADY SAVED"): apply_cookies = True with open(saved_cookies_path, "w", encoding="utf-8") as f: f.write(cookies_content) self.log("ā New cookies saved permanently (saved_cookies.txt)") elif os.path.exists(saved_cookies_path): self.log("ā Using previously saved cookies from persistent Firefox profile") # === FIREFOX OPTIONS WITH PERSISTENT PROFILE === options = webdriver.FirefoxOptions() options.set_preference("dom.webnotifications.enabled", False) options.set_preference("dom.push.enabled", False) options.set_preference("browser.cache.disk.enable", True) options.add_argument(f'-profile "{self.profile_dir}"') # ====================== webdriver-manager (AUTO driver) ====================== try: self.log("š§ webdriver-manager: Downloading latest geckodriver automatically...") service = FirefoxService(GeckoDriverManager().install()) driver = webdriver.Firefox(service=service, options=options) driver.maximize_window() self.log("ā Firefox launched successfully with auto-managed driver") except Exception as e: error_msg = str(e) full_trace = traceback.format_exc() self.log(f"ā ERROR launching Firefox: {error_msg}") self.log("\n=== FULL ERROR DETAILS ===") self.log(full_trace) self.log("\nš§ Possible fixes:") self.log("1. Make sure Firefox browser is installed on your PC") self.log("2. Run this command and try again:") self.log(" pip install --upgrade webdriver-manager") self.log("3. Check your internet connection (driver is downloaded from GitHub)") self.log("4. If you are behind a proxy/VPN, disable it temporarily") self.log("5. Restart your computer and try once more") messagebox.showerror("Launch Failed", f"Could not start Firefox driver.\n\n" f"Error: {error_msg}\n\n" f"Full details are in the Live Log.\n" f"Please follow the fixes above and try again.") return # Apply cookies ONLY the first time if apply_cookies: self.log("š Applying cookies to persistent Firefox profile...") driver.get("https://www.facebook.com") sleep(4) cj = http.cookiejar.MozillaCookieJar() cj.load(saved_cookies_path, ignore_discard=True, ignore_expires=True) for cookie in cj: if 'facebook.com' in cookie.domain: try: driver.add_cookie({ 'name': cookie.name, 'value': cookie.value, 'domain': cookie.domain, 'path': cookie.path or '/' }) except: pass driver.refresh() sleep(6) self.log("ā Logged in with cookies ā Firefox profile now saved forever!") driver.get(url) self.log("š Reels tab opened...") sleep(8) # Close any popup try: driver.find_element(By.XPATH, "//div[@aria-label='Close' or @role='button']").click() self.log("Closed popup") sleep(3) except: pass # ====================== IMPROVED REELS SCRAPING ====================== self.log("š Loading ALL reels (aggressive infinite scroll + height check)...") reel_links = [] seen = set() scroll_count = 0 max_scrolls = 5 no_progress_count = 0 previous_count = 0 last_height = driver.execute_script("return document.body.scrollHeight") while scroll_count < max_scrolls and no_progress_count < 10: scroll_count += 1 self.log(f" Scroll #{scroll_count} - loading more reels...") driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") sleep(3) for _ in range(6): driver.execute_script("window.scrollBy(0, 900);") sleep(0.7) sleep(4) current_height = driver.execute_script("return document.body.scrollHeight") new_added = 0 for el in driver.find_elements(By.XPATH, "//a[contains(@href, '/reel/')]"): href = el.get_attribute('href') if href: clean = re.sub(r'\?.*$', '', href).rstrip('/') if re.search(r'/reel/[0-9a-zA-Z]{10,}', clean) and clean not in seen: seen.add(clean) reel_links.append(clean) new_added += 1 current_total = len(reel_links) self.log(f" Scroll #{scroll_count} ā {current_total} reels (added {new_added})") if current_total == previous_count and current_height == last_height: no_progress_count += 1 else: no_progress_count = 0 previous_count = current_total last_height = current_height self.log(f"ā Final total reels found = {len(reel_links)}") driver.quit() # ====================== DOWNLOAD ====================== if not reel_links: self.log("ā ļø No reels found!") return if shutil.which("yt-dlp") is None: self.log("ā ERROR: yt-dlp not found in PATH!") self.log("Please run: pip install -U yt-dlp") messagebox.showerror("Error", "yt-dlp not found. Install it first.") return os.makedirs("output", exist_ok=True) output_dir = os.path.join("output", folder_name) os.makedirs(output_dir, exist_ok=True) csv_path = os.path.join("output", f"{folder_name}.csv") with open(csv_path, "w", newline="", encoding="utf-8") as f: writer = csv.writer(f) for link in reel_links: writer.writerow([link]) self.log(f"\nš„ Downloading {len(reel_links)} reels as SINGLE MP4 with sound...") args = ["yt-dlp"] if os.path.exists(saved_cookies_path): args.extend(["--cookies", saved_cookies_path]) args.extend([ "-f", "best[ext=mp4]/bestvideo[ext=mp4]+bestaudio[ext=m4a]/bestvideo+bestaudio/best", "--merge-output-format", "mp4", "--postprocessor-args", "ffmpeg:-c:v copy -c:a aac -movflags +faststart", "--force-ipv4", "--geo-bypass", "--retries", "30", "--fragment-retries", "30", "--sleep-interval", "2", "-a", csv_path, "--output", os.path.join(output_dir, "%(id)s.%(ext)s"), "--no-keep-video", "--no-keep-fragments", ]) process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, encoding="utf-8", errors="replace") for line in process.stdout: if line.strip(): self.log(line.strip()) process.wait() self.log("\nš ALL DONE! Reels saved as single MP4 with sound.") self.log(f"ā Check folder: output\\{folder_name}\\") messagebox.showinfo("Success", f"Done!\n{len(reel_links)} reels downloaded successfully") if __name__ == "__main__": root = tk.Tk() app = ReelsDownloaderGUI(root) root.mainloop()
ā Saved online