mirror of
https://github.com/karl0ss/GoGoDownloader.git
synced 2025-05-13 10:18:12 +01:00
first commit
This commit is contained in:
commit
16540ce084
141
.gitignore
vendored
Normal file
141
.gitignore
vendored
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# Executable files
|
||||||
|
exe/
|
54
README.md
Normal file
54
README.md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<div align="center">
|
||||||
|
<img
|
||||||
|
style="width: 165px; height: 165px"
|
||||||
|
src="https://i.postimg.cc/VkSMVQrg/ba-logo.png"
|
||||||
|
title="BitAnime"
|
||||||
|
alt="BitAnime"
|
||||||
|
/>
|
||||||
|
<h3>BitAnime</h3>
|
||||||
|
<p>
|
||||||
|
A Python script that allows you to download all of an anime's episodes at once.
|
||||||
|
</p>
|
||||||
|
<a href="https://github.com/sh1nobuu/BitAnime/releases"> <strong>· Download executable version ·</strong></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## About BitAnime
|
||||||
|
|
||||||
|
**BitAnime** is a python script that allows you to download anime in large batches. It can also be used to download anime films. **BitAnime** gets its content from [gogoanime](https://gogoanime.pe/). If you get a **404** error, please look up the correct anime name on [gogoanime](https://gogoanime.pe/). This application can only download **1**-**99** episodes at the time. At the moment, the quality of the episodes that will be downloaded is different for every anime. For **older anime**, the quality will be **360p** to **480p**, for **newer anime** the quality will be **720p** to **1080p**.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```console
|
||||||
|
git clone https://github.com/sh1nobuu/BitAnime.git
|
||||||
|
```
|
||||||
|
|
||||||
|
## Screenshot
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<img src="https://i.postimg.cc/q76DzZ5y/ba-screenshot.png"
|
||||||
|
title="BitAnime in action" alt="BitAnime Screenshot">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
**BitAnime** is highly reliant on the python modules `requests`, `colorama`, `tqdm`, and `BeautifulSoup`.
|
||||||
|
|
||||||
|
```console
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
The anime name is separated by "-". You can either type it manually, or go to [gogoanime.pe](https://gogoanime.pe/) and search for the anime you want to download and copy the name from the URL.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
##### One word title
|
||||||
|
|
||||||
|
- https://gogoanime.pe/category/bakemonogatari >> bakemonogatari
|
||||||
|
- https://gogoanime.pe/category/steinsgate >> steinsgate
|
||||||
|
|
||||||
|
##### Multiple word title
|
||||||
|
|
||||||
|
- https://gogoanime.pe/category/shadows-house >> shadows-house
|
||||||
|
- https://gogoanime.pe/category/kono-subarashii-sekai-ni-shukufuku-wo- >> kono-subarashii-sekai-ni-shukufuku-wo-
|
BIN
images/ba-logo.png
Normal file
BIN
images/ba-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
BIN
images/ba-screenshot.PNG
Normal file
BIN
images/ba-screenshot.PNG
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
BIN
requirements.txt
Normal file
BIN
requirements.txt
Normal file
Binary file not shown.
68
src/backend.py
Normal file
68
src/backend.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import requests
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
folder_path = ""
|
||||||
|
|
||||||
|
|
||||||
|
def get_path(folder):
|
||||||
|
global folder_path
|
||||||
|
folder_path = folder
|
||||||
|
|
||||||
|
|
||||||
|
def get_links(name, episode_number, source=None):
|
||||||
|
if source is not None:
|
||||||
|
source_ep = f"https://gogoanime.pe/{name}-episode-"
|
||||||
|
episode_links = [f"{source_ep}{i}" for i in range(1, int(episode_number) + 1)]
|
||||||
|
episode_links.insert(0, source)
|
||||||
|
else:
|
||||||
|
source_ep = f"https://gogoanime.pe/{name}-episode-"
|
||||||
|
episode_links = [f"{source_ep}{i}" for i in range(1, int(episode_number) + 1)]
|
||||||
|
return episode_links
|
||||||
|
|
||||||
|
|
||||||
|
def get_download_links(episode_links):
|
||||||
|
download_links = []
|
||||||
|
for episode_link in episode_links:
|
||||||
|
episode_link_resp = requests.get(episode_link)
|
||||||
|
soup = BeautifulSoup(episode_link_resp.content, "html.parser")
|
||||||
|
links = soup.find("li", {"class": "dowloads"})
|
||||||
|
for link in links:
|
||||||
|
link = link.get("href")
|
||||||
|
download_links.append(link)
|
||||||
|
return download_links
|
||||||
|
|
||||||
|
|
||||||
|
def get_download_urls(download_links, bool):
|
||||||
|
download_urls = []
|
||||||
|
for link in download_links:
|
||||||
|
link = requests.get(link)
|
||||||
|
soup = BeautifulSoup(link.content, "html.parser")
|
||||||
|
download_link = soup.find_all("div", {"class": "dowload"})
|
||||||
|
download_urls.append(download_link[0].a.get("href"))
|
||||||
|
if bool:
|
||||||
|
conv_download_urls = {
|
||||||
|
episode_title: url for episode_title, url in enumerate(download_urls)
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
conv_download_urls = {
|
||||||
|
episode_title + 1: url
|
||||||
|
for episode_title, url in enumerate(download_urls)
|
||||||
|
}
|
||||||
|
conv_download_urls = sorted(set(conv_download_urls.items()))
|
||||||
|
return conv_download_urls
|
||||||
|
|
||||||
|
|
||||||
|
def download_episodes(url):
|
||||||
|
header = {
|
||||||
|
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0",
|
||||||
|
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
|
||||||
|
"Accept-Language": "en-US,en;q=0.5",
|
||||||
|
"Accept-Encoding": "gzip, deflate",
|
||||||
|
"Connection": "close",
|
||||||
|
}
|
||||||
|
url_resp = requests.get(url[1], headers=header, stream=True)
|
||||||
|
file_name = os.path.join(folder_path, f"{url[0]}.mp4")
|
||||||
|
with open(file_name, "wb") as file:
|
||||||
|
shutil.copyfileobj(url_resp.raw, file)
|
114
src/bitanime.py
Normal file
114
src/bitanime.py
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
# Dependencies
|
||||||
|
|
||||||
|
import requests
|
||||||
|
import ctypes
|
||||||
|
import os
|
||||||
|
import backend as bd
|
||||||
|
import colorama
|
||||||
|
from tqdm.contrib.concurrent import thread_map
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from colorama import Fore
|
||||||
|
|
||||||
|
colorama.init(autoreset=True)
|
||||||
|
ctypes.windll.kernel32.SetConsoleTitleW("BitAnime")
|
||||||
|
|
||||||
|
|
||||||
|
def bitanime():
|
||||||
|
again = True
|
||||||
|
while again:
|
||||||
|
print(
|
||||||
|
f""" {Fore.LIGHTBLUE_EX}
|
||||||
|
____ _ _ _ _
|
||||||
|
| __ )(_) |_ / \ _ __ (_)_ __ ___ ___
|
||||||
|
| _ \| | __| / _ \ | '_ \| | '_ ` _ \ / _ \\
|
||||||
|
| |_) | | |_ / ___ \| | | | | | | | | | __/
|
||||||
|
|____/|_|\__/_/ \_\_| |_|_|_| |_| |_|\___|
|
||||||
|
{Fore.LIGHTYELLOW_EX}
|
||||||
|
By: sh1nobu
|
||||||
|
Github: https://github.com/sh1nobuu/BitAnime
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
Ask user for input and then check if the anime provided exists or if not, loop
|
||||||
|
"""
|
||||||
|
check = True
|
||||||
|
while check:
|
||||||
|
name = input(f"Enter anime name >> ").lower()
|
||||||
|
if "-" in name:
|
||||||
|
title = name.replace("-", " ").title().strip()
|
||||||
|
else:
|
||||||
|
title = name.title().strip()
|
||||||
|
source = f"https://gogoanime.pe/category/{name}"
|
||||||
|
resp = requests.get(source)
|
||||||
|
if resp.status_code == 200:
|
||||||
|
print(f"{Fore.LIGHTGREEN_EX}====================================")
|
||||||
|
check = False
|
||||||
|
else:
|
||||||
|
print(
|
||||||
|
f"{Fore.LIGHTRED_EX}Error 404: Anime not found. Please try again."
|
||||||
|
)
|
||||||
|
check = True
|
||||||
|
"""
|
||||||
|
Get how many episode/s the anime has
|
||||||
|
"""
|
||||||
|
soup = BeautifulSoup(resp.content, "html.parser")
|
||||||
|
episode_number = soup.find("ul", {"id": "episode_page"})
|
||||||
|
episode_number = episode_number.get_text().split("-")[1].strip()
|
||||||
|
"""
|
||||||
|
Print the anime name, episode, and the link of the anime
|
||||||
|
"""
|
||||||
|
print(f"Title: {Fore.LIGHTCYAN_EX}{title}")
|
||||||
|
print(f"Episode/s: {Fore.LIGHTCYAN_EX}{episode_number}")
|
||||||
|
print(f"Link: {Fore.LIGHTCYAN_EX}{source}")
|
||||||
|
print(f"{Fore.LIGHTGREEN_EX}====================================")
|
||||||
|
"""
|
||||||
|
Create a download folder for the anime
|
||||||
|
"""
|
||||||
|
folder = os.path.join(os.getcwd(), title)
|
||||||
|
if not os.path.exists(folder):
|
||||||
|
os.mkdir(folder)
|
||||||
|
"""
|
||||||
|
Check if the anime has episode 0 or not
|
||||||
|
"""
|
||||||
|
source = f"https://gogoanime.pe/{name}"
|
||||||
|
resp = requests.get(source)
|
||||||
|
soup = BeautifulSoup(resp.content, "html.parser")
|
||||||
|
episode_zero = soup.find("h1", {"class": "entry-title"})
|
||||||
|
if episode_zero is None:
|
||||||
|
# Episode 0 does exist
|
||||||
|
episode_links = bd.get_links(name, episode_number, source)
|
||||||
|
download_links = bd.get_download_links(episode_links)
|
||||||
|
download_urls = bd.get_download_urls(download_links, True)
|
||||||
|
print(f"Downloading {Fore.LIGHTCYAN_EX}{len(download_urls)} episode/s")
|
||||||
|
print(f"{Fore.LIGHTGREEN_EX}====================================")
|
||||||
|
print(download_urls)
|
||||||
|
bd.get_path(folder)
|
||||||
|
thread_map(
|
||||||
|
bd.download_episodes, download_urls, ncols=75, total=len(download_urls)
|
||||||
|
)
|
||||||
|
os.startfile(folder)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Episode 0 does not exist
|
||||||
|
episode_links = bd.get_links(name, episode_number)
|
||||||
|
download_links = bd.get_download_links(episode_links)
|
||||||
|
download_urls = bd.get_download_urls(download_links, False)
|
||||||
|
print(
|
||||||
|
f"Downloading {Fore.LIGHTCYAN_EX}{len(download_urls)}{Fore.RESET} episode/s"
|
||||||
|
)
|
||||||
|
print(f"{Fore.LIGHTGREEN_EX}====================================")
|
||||||
|
bd.get_path(folder)
|
||||||
|
thread_map(
|
||||||
|
bd.download_episodes, download_urls, ncols=75, total=len(download_urls)
|
||||||
|
)
|
||||||
|
os.startfile(folder)
|
||||||
|
use_again = input("Do you want to download other anime? (y|n) >> ").lower()
|
||||||
|
if use_again == "y":
|
||||||
|
again = True
|
||||||
|
os.system("cls")
|
||||||
|
else:
|
||||||
|
again = False
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
bitanime()
|
Loading…
x
Reference in New Issue
Block a user