Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import requests
- import os
- from bs4 import BeautifulSoup
- from rich.console import Console
- from rich.panel import Panel
- from rich.progress import Progress
- import cloudscraper
- import re
- from urllib.parse import urlparse, parse_qs, unquote
- import time
- import urllib3
- import requests.packages.urllib3.util.ssl_
- import sys
- import socket
- # Configurações iniciais
- socket.setdefaulttimeout(30)
- if hasattr(sys, 'getandroidapilevel'):
- socket._MAXLINE = 65536 * 8
- requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS = 'ALL:@SECLEVEL=1'
- # Diretório base para downloads
- BASE_DOWNLOAD_DIR = "/storage/emulated/0/downloads/"
- os.system('clear' if os.name == 'posix' else 'cls')
- class AnimeFinder:
- def __init__(self):
- self.console = Console()
- self.base_url = "https://animefire.plus/pesquisar/"
- self.headers = {
- 'User-Agent': "Mozilla/5.0 (Linux; Android 14; 22071219CG Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/132.0.6834.56 Mobile Safari/537.36"
- }
- self.scraper = cloudscraper.create_scraper()
- def _format_anime_name(self, anime_name):
- return anime_name.strip().replace(" ", "-").lower()
- def search_anime(self, anime_name):
- try:
- formatted_name = self._format_anime_name(anime_name)
- url = f"{self.base_url}{formatted_name}"
- response = self.scraper.get(url, headers=self.headers, timeout=30)
- response.raise_for_status()
- soup = BeautifulSoup(response.content, 'html.parser')
- anime_cards = soup.find_all('div', class_='divCardUltimosEps')
- if not anime_cards:
- self.console.print("[bold red]Nenhum resultado encontrado.[/bold red]")
- return []
- return self._display_results(anime_cards)
- except Exception as e:
- self.console.print(f"[bold red]Erro: {str(e)}[/bold red]")
- return []
- def _display_results(self, anime_cards):
- results = []
- for i, card in enumerate(anime_cards, 1):
- title = self._extract_text(card, 'h3', 'animeTitle')
- full_link = self._extract_full_link(card, 'a')
- results.append({
- 'title': title,
- 'link': full_link
- })
- self.console.print("\nEscolha o número do anime:", style="bold blue")
- for i, result in enumerate(results, 1):
- self.console.print(f"[cyan]{i}. {result['title']}[/cyan]")
- return results
- def _extract_text(self, soup, tag, class_name):
- element = soup.find(tag, class_=class_name)
- return element.text.strip() if element else None
- def _extract_full_link(self, soup, tag):
- element = soup.find(tag)
- return element.get('href') if element else None
- def sanitize_filename(filename):
- # Remove caracteres inválidos
- invalid_chars = r'[<>:"/\\|?*]'
- return re.sub(invalid_chars, '', filename)
- def create_anime_directory(anime_name):
- # Cria diretório do anime
- safe_name = sanitize_filename(anime_name)
- anime_dir = os.path.join(BASE_DOWNLOAD_DIR, safe_name)
- os.makedirs(anime_dir, exist_ok=True)
- return anime_dir
- def fetch_and_display_anime_info(url):
- scraper = cloudscraper.create_scraper()
- response = scraper.get(url, timeout=30)
- response.raise_for_status()
- soup = BeautifulSoup(response.text, 'html.parser')
- anime_info = {
- "titulos": {
- "principal": soup.find('h1', class_='quicksand400').text.strip() if soup.find('h1', class_='quicksand400') else 'N/A',
- "alternativo": soup.find_all('h6', class_='text-gray')[0].text.strip() if soup.find_all('h6', class_='text-gray') else 'N/A',
- "japones": soup.find_all('h6', class_='text-gray')[-1].text.strip() if len(soup.find_all('h6', class_='text-gray')) > 1 else 'N/A'
- },
- "avaliacao": {
- "score": soup.find('h4', id='anime_score').text.strip() if soup.find('h4', id='anime_score') else 'N/A',
- "total_votos": soup.find('h6', id='anime_votos').text.strip() if soup.find('h6', id='anime_votos') else 'N/A'
- },
- "sinopse": extract_sinopse(soup),
- "midia": {
- "imagem_capa": extract_img_capa(soup)
- },
- "generos": [
- genero.text.strip()
- for genero in soup.find_all('a', class_='spanGenerosLink')
- ],
- "episodios": len(soup.find_all('a', class_='lEp'))
- }
- return anime_info
- def extract_sinopse(soup):
- sinopse_tag = soup.find('div', class_='divSinopse mb-3 mt-3 ml-2 ml-sm-1 ml-md-2 mr-2')
- sinopse = sinopse_tag.find('span', class_='spanAnimeInfo').text.strip() if sinopse_tag else 'N/A'
- return sinopse
- def extract_img_capa(soup):
- img_tag = soup.find('img', class_='transitioning_src')
- if img_tag:
- return img_tag.get('data-src', img_tag.get('src'))
- return 'N/A'
- def save_anime_info(anime_info, download_dir, filename):
- # Salva informações do anime na pasta de download
- try:
- file_path = os.path.join(download_dir, f"{filename}.txt")
- with open(file_path, 'w', encoding='utf-8') as f:
- f.write("=== Informações do Anime ===\n\n")
- f.write(f"Título Principal: {anime_info['titulos']['principal']}\n")
- f.write(f"Título Alternativo: {anime_info['titulos']['alternativo']}\n")
- f.write(f"Título Japonês: {anime_info['titulos']['japones']}\n\n")
- f.write(f"Avaliação: {anime_info['avaliacao']['score']}\n")
- f.write(f"Total de Votos: {anime_info['avaliacao']['total_votos']}\n\n")
- f.write("Sinopse:\n")
- f.write(f"{anime_info['sinopse']}\n\n")
- f.write("Gêneros:\n")
- f.write(", ".join(anime_info['generos']) + "\n\n")
- f.write(f"Total de Episódios: {anime_info['episodios']}\n")
- return True
- except Exception as e:
- Console().print(f"[bold red]Erro ao salvar informações: {str(e)}[/bold red]")
- return False
- class AnimeDownloader:
- def __init__(self):
- self.scraper = cloudscraper.create_scraper(
- browser={
- 'browser': 'chrome',
- 'platform': 'android',
- 'desktop': False
- }
- )
- self.console = Console()
- self.headers = {
- 'User-Agent': "Mozilla/5.0 (Linux; Android 14; 22071219CG Build/UP1A.231005.007; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/132.0.6834.56 Mobile Safari/537.36"
- }
- def get_episode_links(self, anime_url):
- try:
- response = self.scraper.get(anime_url, headers=self.headers)
- response.raise_for_status()
- soup = BeautifulSoup(response.content, 'html.parser')
- episodes = soup.find_all('a', class_='lEp')
- episode_links = [(ep.text.strip(), ep['href']) for ep in episodes]
- return episode_links
- except Exception as e:
- self.console.print(f"[bold red]Erro ao obter episódios: {str(e)}[/bold red]")
- return []
- def select_episodes(self, episodes):
- # Mostra opções para seleção de episódios
- self.console.print("\n[bold cyan]Escolha uma opção:[/bold cyan]")
- self.console.print("1. Baixar todos os episódios", style="bold blue")
- self.console.print("2. Selecionar episódios específicos", style="bold blue")
- choice = input("\nEscolha uma opção (1-2): ").strip()
- if choice == "1":
- return episodes
- elif choice == "2":
- # Mostra episódios para seleção
- self.console.print("\n[bold cyan]Escolha os episódios para download:[/bold cyan]")
- for i, (ep_name, _) in enumerate(episodes, 1):
- self.console.print(f"[cyan]{i}. {ep_name}[/cyan]")
- while True:
- self.console.print("\n[bold cyan]Digite os números dos episódios separados por vírgula (ex: 1,3,5):[/bold cyan]")
- choice = input("\nEscolha os episódios: ").strip()
- try:
- ep_numbers = [int(x.strip()) for x in choice.split(",")]
- return [episodes[i-1] for i in ep_numbers if 1 <= i <= len(episodes)]
- except (ValueError, IndexError):
- self.console.print("[bold red]Entrada inválida! Tente novamente.[/bold red]")
- else:
- self.console.print("[bold red]Opção inválida! Tente novamente.[/bold red]")
- return self.select_episodes(episodes)
- def get_download_link(self, episode_url):
- try:
- response = self.scraper.get(episode_url, headers=self.headers)
- response.raise_for_status()
- soup = BeautifulSoup(response.content, 'html.parser')
- download_button = soup.find('a', id='dw')
- if not download_button:
- self.console.print("[bold red]Botão de download não encontrado[/bold red]")
- return None, None
- download_page_url = download_button['href']
- response = self.scraper.get(download_page_url, headers=self.headers)
- response.raise_for_status()
- soup = BeautifulSoup(response.content, 'html.parser')
- hd_link = soup.find('a', attrs={'download': True})
- if hd_link:
- download_url = hd_link['href']
- parsed_url = urlparse(download_url)
- query_params = parse_qs(parsed_url.query)
- filename = query_params.get('title', ['episode.mp4'])[0]
- filename = unquote(filename)
- filename = sanitize_filename(filename)
- if not filename.endswith('.mp4'):
- filename += '.mp4'
- return download_url, filename
- self.console.print("[bold red]Link de download não encontrado[/bold red]")
- return None, None
- except Exception as e:
- self.console.print(f"[bold red]Erro ao obter link de download: {str(e)}[/bold red]")
- return None, None
- def download_episode(self, url, filename, download_dir):
- try:
- self.console.print(f"[bold blue]Iniciando download do episódio: {filename}[/bold blue]")
- session = requests.Session()
- session.verify = False
- requests.packages.urllib3.disable_warnings()
- retry_count = 3
- while retry_count > 0:
- try:
- response = session.get(url, stream=True, headers=self.headers, timeout=30)
- break
- except (requests.exceptions.RequestException, urllib3.exceptions.RequestError) as e:
- retry_count -= 1
- if retry_count == 0:
- raise e
- time.sleep(2)
- total_size = int(response.headers.get('content-length', 0))
- file_path = os.path.join(download_dir, filename)
- chunk_size = 1024 * 1024 # 1MB chunks
- with open(file_path, 'wb') as file:
- with Progress() as progress:
- task = progress.add_task("[green]Baixando...", total=total_size)
- for data in response.iter_content(chunk_size=chunk_size):
- file.write(data)
- progress.update(task, advance=len(data))
- self.console.print(f"\n[bold green]Download completo: {filename}[/bold green]")
- return True
- except Exception as e:
- self.console.print(f"[bold red]Erro no download: {str(e)}[/bold red]")
- return False
- def main():
- finder = AnimeFinder()
- downloader = AnimeDownloader()
- console = Console()
- while True:
- try:
- console.print(Panel.fit(
- "🌟 [bold blue]Anime Scraper[/bold blue] 🌟\n[bold blue]Anime downloader by goofynn7[/bold blue]",
- border_style="bold blue"
- ))
- console.print("\n[bold cyan]Selecione uma opção:[/bold cyan]")
- console.print("1. Buscar anime", style="bold blue")
- console.print("2. Sair", style="bold blue")
- choice = input("\nEscolha uma opção (1-2): ").strip()
- if choice == "1":
- anime_name = input("\nDigite o nome do anime: ").strip()
- if not anime_name:
- console.print("[bold yellow]Por favor, digite um nome de anime.[/bold yellow]")
- continue
- results = finder.search_anime(anime_name)
- if results:
- choice = input("\nDigite o número do anime (ou 'voltar' para nova busca): ").strip()
- if choice.lower() == 'voltar':
- continue
- try:
- choice_index = int(choice) - 1
- if 0 <= choice_index < len(results):
- selected_anime = results[choice_index]
- selected_anime_url = selected_anime['link']
- anime_info = fetch_and_display_anime_info(selected_anime_url)
- download_dir = create_anime_directory(selected_anime['title'])
- safe_filename = sanitize_filename(selected_anime['title'])
- if save_anime_info(anime_info, download_dir, safe_filename):
- console.print("[bold green]Informações do anime salvas com sucesso![/bold green]")
- episodes = downloader.get_episode_links(selected_anime_url)
- if episodes:
- console.print(f"[bold blue]Encontrados {len(episodes)} episódios[/bold blue]")
- episodes_to_download = downloader.select_episodes(episodes)
- if episodes_to_download:
- for ep_name, ep_url in episodes_to_download:
- download_url, filename = downloader.get_download_link(ep_url)
- if download_url:
- downloader.download_episode(download_url, filename, download_dir)
- else:
- console.print(f"[bold red]Não foi possível obter o link de download para {ep_name}[/bold red]")
- time.sleep(1)
- else:
- console.print("[bold yellow]Nenhum episódio selecionado para download.[/bold yellow]")
- else:
- console.print("[bold red]Seleção inválida![/bold red]")
- except ValueError:
- console.print("[bold red]Por favor, insira um número válido.[/bold red]")
- elif choice == "2":
- console.print("[bold green]Obrigado por usar o Anime Finder![/bold green]")
- break
- else:
- console.print("[bold red]Opção inválida![/bold red]")
- except KeyboardInterrupt:
- console.print("\n[bold green]Programa encerrado pelo usuário.[/bold green]")
- break
- except Exception as e:
- console.print(f"[bold red]Erro inesperado: {str(e)}[/bold red]")
- continue
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement