Yous135774 commited on
Commit
a7593d2
·
verified ·
1 Parent(s): 5483422

Update bot.py

Browse files
Files changed (1) hide show
  1. bot.py +149 -49
bot.py CHANGED
@@ -607,9 +607,19 @@ class ImageToolbox:
607
  return False
608
 
609
  # ================================
610
- # 📥 9. Universal Downloader & Advanced Web Scraper
611
  # ================================
612
  class DownloadManager:
 
 
 
 
 
 
 
 
 
 
613
  @staticmethod
614
  def extract_archives(folder):
615
  for root, _, files in os.walk(folder):
@@ -630,8 +640,7 @@ class DownloadManager:
630
  except: pass
631
 
632
  @staticmethod
633
- def scrape_web_selenium(url, output_folder):
634
- # 🚀 تحديث جذري لسحب مواقع الويب وحل مشكلة صورتين فقط (Lazy Loading Fix)
635
  driver = None
636
  try:
637
  chrome_options = Options()
@@ -645,70 +654,163 @@ class DownloadManager:
645
  driver.get(url)
646
  time.sleep(5)
647
 
648
- # النزول البطيء والمستمر لتحفيز تحميل الصور
649
- last_h = driver.execute_script("return document.body.scrollHeight")
650
- for _ in range(60): # محاولة النزول 60 مرة
651
- driver.execute_script("window.scrollBy(0, 1000);")
652
- time.sleep(1.2) # انتظار كافٍ لرد السيرفر
653
- new_h = driver.execute_script("return document.body.scrollHeight")
654
- if new_h == last_h:
655
- time.sleep(3) # محاولة أخيرة لو توقف النزول
656
- new_h = driver.execute_script("return document.body.scrollHeight")
657
- if new_h == last_h: break
658
- last_h = new_h
659
 
660
- time.sleep(3)
661
 
662
- # استخراج الصور بذكاء (تجاهل الأيقونات والبنرات)
663
- elems = driver.find_elements(By.TAG_NAME, 'img')
664
- urls = []
665
- for e in elems:
666
- src = e.get_attribute('src') or e.get_attribute('data-src') or e.get_attribute('data-original')
667
- if src and src.startswith('http') and not any(x in src.lower() for x in ['logo','ad','banner','icon','avatar', 'profile']):
668
- urls.append(src)
669
 
670
- # إزالة التكرار مع الحفاظ على الترتيب الأصلي
671
- urls = list(dict.fromkeys(urls))
 
 
 
 
 
 
 
 
 
 
672
 
673
- saved_paths = []
674
- req_headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'}
 
 
 
 
 
 
 
675
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
676
  for idx, u in enumerate(urls):
677
  try:
678
- c = requests.get(u, headers=req_headers, timeout=15).content
679
  im = Image.open(io.BytesIO(c)).convert('RGB')
680
- # التأكد من أن الصورة هي صفحة مانهوا فعلية (أبعاد كبيرة) وليست أيقونة صغيرة
681
- if im.width > 300 and im.height > 300:
682
- path = os.path.join(output_folder, f"page_{idx:03d}.jpg")
683
  im.save(path)
684
  saved_paths.append(path)
685
  except: pass
686
-
687
  title = driver.title.split('|')[0].strip() if driver.title else "Web_Chapter"
688
  title = re.sub(r'[\\/*?:"<>|]', "", title)
689
  driver.quit()
690
  return saved_paths, title
691
  except Exception as e:
692
  if driver: driver.quit()
693
- print(f"Scraper Error: {e}")
694
  return [], "Error"
695
 
696
  @staticmethod
697
  async def download(url, output_folder):
698
  success = False
699
  name = "Downloaded_Content"
700
-
701
- # التوجه مباشرة لخطة الطوارئ gdown لتحميل الملفات
702
  if "drive.google.com" in url:
703
- try:
704
- if "folder" in url or "drive.google.com/drive/folders" in url:
705
- res = await asyncio.to_thread(gdown.download_folder, url, output=output_folder, quiet=False, use_cookies=False)
706
- if res: success = True
707
- else:
708
- res = await asyncio.to_thread(gdown.download, url, output=os.path.join(output_folder, "gdown_fallback.zip"), quiet=False, fuzzy=True)
709
- if res: success = True
710
- if success: name = "Drive_Content"
711
- except Exception as e: print(f"Drive Error: {e}")
712
  else:
713
  try:
714
  async with aiohttp.ClientSession() as s:
@@ -716,11 +818,10 @@ class DownloadManager:
716
  if r.status == 200:
717
  cd = r.headers.get('Content-Disposition', '')
718
  if 'filename=' in cd: name = re.findall("filename=(.+)", cd)[0].strip('"')
719
- else: name = "file.zip"
720
  with open(os.path.join(output_folder, name), 'wb') as f: f.write(await r.read())
721
  success = True
722
  except: pass
723
-
724
  DownloadManager.extract_archives(output_folder)
725
  has_images = any(f.lower().endswith(('.png','.jpg','.jpeg','.webp')) for r, d, files in os.walk(output_folder) for f in files)
726
  if success and has_images: return True, name
@@ -732,13 +833,12 @@ class DownloadManager:
732
  subdirs = [d for d in os.listdir(folder) if os.path.isdir(os.path.join(folder, d))]
733
  if not subdirs:
734
  imgs = [os.path.join(folder, f) for f in os.listdir(folder) if f.lower().endswith(('.png','.jpg','.jpeg','.webp'))]
735
- # هنا نستخدم دالة natural_sort_key التي وضعناها في الجزء الأول لترتيب الصور بشكل بشري دقيق
736
- if imgs: chapters["Main"] = sorted(imgs, key=natural_sort_key)
737
  else:
738
- for d in sorted(subdirs, key=natural_sort_key):
739
  d_path = os.path.join(folder, d)
740
  imgs = [os.path.join(d_path, f) for f in os.listdir(d_path) if f.lower().endswith(('.png','.jpg','.jpeg','.webp'))]
741
- if imgs: chapters[d] = sorted(imgs, key=natural_sort_key)
742
  return chapters
743
 
744
  # ================================
 
607
  return False
608
 
609
  # ================================
610
+ # 📥 Universal Downloader (Drive, Gofile, Web & gdown Fallback)
611
  # ================================
612
  class DownloadManager:
613
+ @staticmethod
614
+ def get_drive_real_name(url):
615
+ try:
616
+ r = requests.get(url, timeout=10)
617
+ soup = BeautifulSoup(r.text, 'html.parser')
618
+ title = soup.title.string
619
+ if title: return title.replace(" - Google Drive", "").strip()
620
+ return "Drive_Content"
621
+ except: return "Drive_Content"
622
+
623
  @staticmethod
624
  def extract_archives(folder):
625
  for root, _, files in os.walk(folder):
 
640
  except: pass
641
 
642
  @staticmethod
643
+ def scrape_drive_selenium(url, output_folder):
 
644
  driver = None
645
  try:
646
  chrome_options = Options()
 
654
  driver.get(url)
655
  time.sleep(5)
656
 
657
+ page_title = driver.title.replace(" - Google Drive", "").strip()
658
+ if not page_title or page_title == "Google Drive": page_title = "Drive_Folder"
659
+
660
+ last_height = driver.execute_script("return document.body.scrollHeight")
661
+ for _ in range(15):
662
+ driver.execute_script("window.scrollBy(0, 1500);")
663
+ time.sleep(1)
664
+ new_height = driver.execute_script("return document.body.scrollHeight")
665
+ if new_height == last_height: break
666
+ last_height = new_height
 
667
 
668
+ time.sleep(2)
669
 
670
+ elements = driver.find_elements(By.XPATH, "//*[@data-id]")
671
+ file_ids = []
672
+ for el in elements:
673
+ fid = el.get_attribute("data-id")
674
+ if fid and len(fid) > 20 and fid not in file_ids:
675
+ file_ids.append(fid)
 
676
 
677
+ if not file_ids:
678
+ page_source = driver.page_source
679
+ found = re.findall(r'\["([^"]{25,})",', page_source)
680
+ file_ids = list(set([fid for fid in found if len(fid) > 28]))
681
+
682
+ if not file_ids:
683
+ driver.quit()
684
+ return False, "Error"
685
+
686
+ saved = False
687
+ session = requests.Session()
688
+ session.headers.update({"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"})
689
 
690
+ for idx, fid in enumerate(file_ids):
691
+ try:
692
+ dl_url = f"https://drive.google.com/uc?export=download&id={fid}"
693
+ r = session.get(dl_url, stream=True, timeout=15)
694
+ if r.status_code == 200 and len(r.content) > 10000:
695
+ with open(os.path.join(output_folder, f"drive_img_{idx:03d}.jpg"), 'wb') as f:
696
+ f.write(r.content)
697
+ saved = True
698
+ except: pass
699
 
700
+ driver.quit()
701
+ return saved, page_title
702
+ except Exception as e:
703
+ if driver: driver.quit()
704
+ return False, "Error"
705
+
706
+ @staticmethod
707
+ async def scrape_drive(url, output_folder):
708
+ real_name = DownloadManager.get_drive_real_name(url)
709
+ # 1. المحاولة الأساسية باستخدام المتصفح الخفي (Selenium)
710
+ success, name = await asyncio.to_thread(DownloadManager.scrape_drive_selenium, url, output_folder)
711
+
712
+ # 2. خط الدفاع الأخير (Fallback) باستخدام gdown لو فشل المتصفح
713
+ if not success:
714
+ try:
715
+ print("⚠️ فشل السحب باستخدام Selenium، جاري التحويل إلى خطة الطوارئ (gdown)...")
716
+ if "folder" in url or "drive.google.com/drive/folders" in url:
717
+ res = await asyncio.to_thread(gdown.download_folder, url, output=output_folder, quiet=False, use_cookies=False)
718
+ if res: success = True
719
+ else:
720
+ res = await asyncio.to_thread(gdown.download, url, output=os.path.join(output_folder, "gdown_fallback.zip"), quiet=False, fuzzy=True)
721
+ if res: success = True
722
+
723
+ if success: name = real_name
724
+ except Exception as e:
725
+ print(f"❌ فشلت خطة الطوارئ gdown أيضاً: {e}")
726
+
727
+ return success, name
728
+
729
+ @staticmethod
730
+ def scrape_gofile_selenium(url, output_folder):
731
+ driver = None
732
+ try:
733
+ chrome_options = Options()
734
+ chrome_options.add_argument('--headless=new')
735
+ chrome_options.add_argument('--no-sandbox')
736
+ chrome_options.add_argument('--disable-dev-shm-usage')
737
+ service = Service(ChromeDriverManager().install())
738
+ driver = webdriver.Chrome(service=service, options=chrome_options)
739
+ driver.get(url)
740
+ WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.CSS_SELECTOR, ".contentName, .downloadButton")))
741
+ time.sleep(3)
742
+ try: page_title = driver.find_element(By.CSS_SELECTOR, ".contentName").text
743
+ except: page_title = "Gofile_Content"
744
+ links = driver.find_elements(By.TAG_NAME, 'a')
745
+ download_urls = [link.get_attribute('href') for link in links if link.get_attribute('href') and 'download' in link.get_attribute('href').lower()]
746
+ cookies = driver.get_cookies()
747
+ session = requests.Session()
748
+ for cookie in cookies: session.cookies.set(cookie['name'], cookie['value'])
749
+ saved = False
750
+ for idx, d_url in enumerate(list(set(download_urls))):
751
+ r = session.get(d_url, stream=True)
752
+ if r.status_code == 200:
753
+ cd = r.headers.get('content-disposition', '')
754
+ fname = re.findall("filename=(.+)", cd)
755
+ name = fname[0].strip('"') if fname else f"file_{idx}.zip"
756
+ with open(os.path.join(output_folder, name), 'wb') as f: f.write(r.content)
757
+ saved = True
758
+ driver.quit()
759
+ return saved, page_title
760
+ except:
761
+ if driver: driver.quit()
762
+ return False, "Error"
763
+
764
+ @staticmethod
765
+ def scrape_web_selenium(url, output_folder):
766
+ driver = None
767
+ try:
768
+ chrome_options = Options()
769
+ chrome_options.add_argument('--headless=new')
770
+ chrome_options.add_argument('--no-sandbox')
771
+ chrome_options.add_argument('--disable-dev-shm-usage')
772
+ service = Service(ChromeDriverManager().install())
773
+ driver = webdriver.Chrome(service=service, options=chrome_options)
774
+ driver.get(url)
775
+ time.sleep(5)
776
+ last_h = driver.execute_script("return document.body.scrollHeight")
777
+ for _ in range(30):
778
+ driver.execute_script("window.scrollBy(0, 800);")
779
+ time.sleep(0.5)
780
+ new_h = driver.execute_script("return window.pageYOffset + window.innerHeight")
781
+ if new_h >= last_h: break
782
+ last_h = driver.execute_script("return document.body.scrollHeight")
783
+ time.sleep(2)
784
+ elems = driver.find_elements(By.TAG_NAME, 'img')
785
+ urls = [e.get_attribute('src') or e.get_attribute('data-src') for e in elems]
786
+ urls = list(set([u for u in urls if u and u.startswith('http') and not any(x in u.lower() for x in ['logo','ad','banner','icon'])]))
787
+ saved_paths = []
788
+ req_headers = {'User-Agent': 'Mozilla/5.0'}
789
  for idx, u in enumerate(urls):
790
  try:
791
+ c = requests.get(u, headers=req_headers, timeout=10).content
792
  im = Image.open(io.BytesIO(c)).convert('RGB')
793
+ if im.width > 150 and im.height > 150:
794
+ path = os.path.join(output_folder, f"{idx:03d}.jpg")
 
795
  im.save(path)
796
  saved_paths.append(path)
797
  except: pass
 
798
  title = driver.title.split('|')[0].strip() if driver.title else "Web_Chapter"
799
  title = re.sub(r'[\\/*?:"<>|]', "", title)
800
  driver.quit()
801
  return saved_paths, title
802
  except Exception as e:
803
  if driver: driver.quit()
 
804
  return [], "Error"
805
 
806
  @staticmethod
807
  async def download(url, output_folder):
808
  success = False
809
  name = "Downloaded_Content"
 
 
810
  if "drive.google.com" in url:
811
+ success, name = await DownloadManager.scrape_drive(url, output_folder)
812
+ elif "gofile.io" in url:
813
+ success, name = await asyncio.to_thread(DownloadManager.scrape_gofile_selenium, url, output_folder)
 
 
 
 
 
 
814
  else:
815
  try:
816
  async with aiohttp.ClientSession() as s:
 
818
  if r.status == 200:
819
  cd = r.headers.get('Content-Disposition', '')
820
  if 'filename=' in cd: name = re.findall("filename=(.+)", cd)[0].strip('"')
821
+ else: name = "file.bin"
822
  with open(os.path.join(output_folder, name), 'wb') as f: f.write(await r.read())
823
  success = True
824
  except: pass
 
825
  DownloadManager.extract_archives(output_folder)
826
  has_images = any(f.lower().endswith(('.png','.jpg','.jpeg','.webp')) for r, d, files in os.walk(output_folder) for f in files)
827
  if success and has_images: return True, name
 
833
  subdirs = [d for d in os.listdir(folder) if os.path.isdir(os.path.join(folder, d))]
834
  if not subdirs:
835
  imgs = [os.path.join(folder, f) for f in os.listdir(folder) if f.lower().endswith(('.png','.jpg','.jpeg','.webp'))]
836
+ if imgs: chapters["Main"] = sorted(imgs)
 
837
  else:
838
+ for d in sorted(subdirs):
839
  d_path = os.path.join(folder, d)
840
  imgs = [os.path.join(d_path, f) for f in os.listdir(d_path) if f.lower().endswith(('.png','.jpg','.jpeg','.webp'))]
841
+ if imgs: chapters[d] = sorted(imgs)
842
  return chapters
843
 
844
  # ================================