Skip to content

Commit 16540ce

Browse files
committed
first commit
0 parents  commit 16540ce

7 files changed

+377
-0
lines changed

.gitignore

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
build/
12+
develop-eggs/
13+
dist/
14+
downloads/
15+
eggs/
16+
.eggs/
17+
lib/
18+
lib64/
19+
parts/
20+
sdist/
21+
var/
22+
wheels/
23+
share/python-wheels/
24+
*.egg-info/
25+
.installed.cfg
26+
*.egg
27+
MANIFEST
28+
29+
# PyInstaller
30+
# Usually these files are written by a python script from a template
31+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
32+
*.manifest
33+
*.spec
34+
35+
# Installer logs
36+
pip-log.txt
37+
pip-delete-this-directory.txt
38+
39+
# Unit test / coverage reports
40+
htmlcov/
41+
.tox/
42+
.nox/
43+
.coverage
44+
.coverage.*
45+
.cache
46+
nosetests.xml
47+
coverage.xml
48+
*.cover
49+
*.py,cover
50+
.hypothesis/
51+
.pytest_cache/
52+
cover/
53+
54+
# Translations
55+
*.mo
56+
*.pot
57+
58+
# Django stuff:
59+
*.log
60+
local_settings.py
61+
db.sqlite3
62+
db.sqlite3-journal
63+
64+
# Flask stuff:
65+
instance/
66+
.webassets-cache
67+
68+
# Scrapy stuff:
69+
.scrapy
70+
71+
# Sphinx documentation
72+
docs/_build/
73+
74+
# PyBuilder
75+
.pybuilder/
76+
target/
77+
78+
# Jupyter Notebook
79+
.ipynb_checkpoints
80+
81+
# IPython
82+
profile_default/
83+
ipython_config.py
84+
85+
# pyenv
86+
# For a library or package, you might want to ignore these files since the code is
87+
# intended to run in multiple environments; otherwise, check them in:
88+
# .python-version
89+
90+
# pipenv
91+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
93+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
94+
# install all needed dependencies.
95+
#Pipfile.lock
96+
97+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
98+
__pypackages__/
99+
100+
# Celery stuff
101+
celerybeat-schedule
102+
celerybeat.pid
103+
104+
# SageMath parsed files
105+
*.sage.py
106+
107+
# Environments
108+
.env
109+
.venv
110+
env/
111+
venv/
112+
ENV/
113+
env.bak/
114+
venv.bak/
115+
116+
# Spyder project settings
117+
.spyderproject
118+
.spyproject
119+
120+
# Rope project settings
121+
.ropeproject
122+
123+
# mkdocs documentation
124+
/site
125+
126+
# mypy
127+
.mypy_cache/
128+
.dmypy.json
129+
dmypy.json
130+
131+
# Pyre type checker
132+
.pyre/
133+
134+
# pytype static type analyzer
135+
.pytype/
136+
137+
# Cython debug symbols
138+
cython_debug/
139+
140+
# Executable files
141+
exe/

README.md

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<div align="center">
2+
<img
3+
style="width: 165px; height: 165px"
4+
src="https://i.postimg.cc/VkSMVQrg/ba-logo.png"
5+
title="BitAnime"
6+
alt="BitAnime"
7+
/>
8+
<h3>BitAnime</h3>
9+
<p>
10+
A Python script that allows you to download all of an anime's episodes at once.
11+
</p>
12+
<a href="https://github.com/sh1nobuu/BitAnime/releases"> <strong>· Download executable version ·</strong></a>
13+
</div>
14+
15+
## About BitAnime
16+
17+
**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**.
18+
19+
## Installation
20+
21+
```console
22+
git clone https://github.com/sh1nobuu/BitAnime.git
23+
```
24+
25+
## Screenshot
26+
27+
<div align="center">
28+
<img src="https://i.postimg.cc/q76DzZ5y/ba-screenshot.png"
29+
title="BitAnime in action" alt="BitAnime Screenshot">
30+
</div>
31+
32+
## Dependencies
33+
34+
**BitAnime** is highly reliant on the python modules `requests`, `colorama`, `tqdm`, and `BeautifulSoup`.
35+
36+
```console
37+
pip install -r requirements.txt
38+
```
39+
40+
## Usage
41+
42+
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.
43+
44+
### Examples
45+
46+
##### One word title
47+
48+
- https://gogoanime.pe/category/bakemonogatari >> bakemonogatari
49+
- https://gogoanime.pe/category/steinsgate >> steinsgate
50+
51+
##### Multiple word title
52+
53+
- https://gogoanime.pe/category/shadows-house >> shadows-house
54+
- https://gogoanime.pe/category/kono-subarashii-sekai-ni-shukufuku-wo- >> kono-subarashii-sekai-ni-shukufuku-wo-

images/ba-logo.png

26.1 KB
Loading

images/ba-screenshot.PNG

21.2 KB
Loading

requirements.txt

356 Bytes
Binary file not shown.

src/backend.py

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import requests
2+
import os
3+
import shutil
4+
from bs4 import BeautifulSoup
5+
6+
folder_path = ""
7+
8+
9+
def get_path(folder):
10+
global folder_path
11+
folder_path = folder
12+
13+
14+
def get_links(name, episode_number, source=None):
15+
if source is not None:
16+
source_ep = f"https://gogoanime.pe/{name}-episode-"
17+
episode_links = [f"{source_ep}{i}" for i in range(1, int(episode_number) + 1)]
18+
episode_links.insert(0, source)
19+
else:
20+
source_ep = f"https://gogoanime.pe/{name}-episode-"
21+
episode_links = [f"{source_ep}{i}" for i in range(1, int(episode_number) + 1)]
22+
return episode_links
23+
24+
25+
def get_download_links(episode_links):
26+
download_links = []
27+
for episode_link in episode_links:
28+
episode_link_resp = requests.get(episode_link)
29+
soup = BeautifulSoup(episode_link_resp.content, "html.parser")
30+
links = soup.find("li", {"class": "dowloads"})
31+
for link in links:
32+
link = link.get("href")
33+
download_links.append(link)
34+
return download_links
35+
36+
37+
def get_download_urls(download_links, bool):
38+
download_urls = []
39+
for link in download_links:
40+
link = requests.get(link)
41+
soup = BeautifulSoup(link.content, "html.parser")
42+
download_link = soup.find_all("div", {"class": "dowload"})
43+
download_urls.append(download_link[0].a.get("href"))
44+
if bool:
45+
conv_download_urls = {
46+
episode_title: url for episode_title, url in enumerate(download_urls)
47+
}
48+
else:
49+
conv_download_urls = {
50+
episode_title + 1: url
51+
for episode_title, url in enumerate(download_urls)
52+
}
53+
conv_download_urls = sorted(set(conv_download_urls.items()))
54+
return conv_download_urls
55+
56+
57+
def download_episodes(url):
58+
header = {
59+
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0",
60+
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
61+
"Accept-Language": "en-US,en;q=0.5",
62+
"Accept-Encoding": "gzip, deflate",
63+
"Connection": "close",
64+
}
65+
url_resp = requests.get(url[1], headers=header, stream=True)
66+
file_name = os.path.join(folder_path, f"{url[0]}.mp4")
67+
with open(file_name, "wb") as file:
68+
shutil.copyfileobj(url_resp.raw, file)

src/bitanime.py

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# Dependencies
2+
3+
import requests
4+
import ctypes
5+
import os
6+
import backend as bd
7+
import colorama
8+
from tqdm.contrib.concurrent import thread_map
9+
from bs4 import BeautifulSoup
10+
from colorama import Fore
11+
12+
colorama.init(autoreset=True)
13+
ctypes.windll.kernel32.SetConsoleTitleW("BitAnime")
14+
15+
16+
def bitanime():
17+
again = True
18+
while again:
19+
print(
20+
f""" {Fore.LIGHTBLUE_EX}
21+
____ _ _ _ _
22+
| __ )(_) |_ / \ _ __ (_)_ __ ___ ___
23+
| _ \| | __| / _ \ | '_ \| | '_ ` _ \ / _ \\
24+
| |_) | | |_ / ___ \| | | | | | | | | | __/
25+
|____/|_|\__/_/ \_\_| |_|_|_| |_| |_|\___|
26+
{Fore.LIGHTYELLOW_EX}
27+
By: sh1nobu
28+
Github: https://github.com/sh1nobuu/BitAnime
29+
"""
30+
)
31+
"""
32+
Ask user for input and then check if the anime provided exists or if not, loop
33+
"""
34+
check = True
35+
while check:
36+
name = input(f"Enter anime name >> ").lower()
37+
if "-" in name:
38+
title = name.replace("-", " ").title().strip()
39+
else:
40+
title = name.title().strip()
41+
source = f"https://gogoanime.pe/category/{name}"
42+
resp = requests.get(source)
43+
if resp.status_code == 200:
44+
print(f"{Fore.LIGHTGREEN_EX}====================================")
45+
check = False
46+
else:
47+
print(
48+
f"{Fore.LIGHTRED_EX}Error 404: Anime not found. Please try again."
49+
)
50+
check = True
51+
"""
52+
Get how many episode/s the anime has
53+
"""
54+
soup = BeautifulSoup(resp.content, "html.parser")
55+
episode_number = soup.find("ul", {"id": "episode_page"})
56+
episode_number = episode_number.get_text().split("-")[1].strip()
57+
"""
58+
Print the anime name, episode, and the link of the anime
59+
"""
60+
print(f"Title: {Fore.LIGHTCYAN_EX}{title}")
61+
print(f"Episode/s: {Fore.LIGHTCYAN_EX}{episode_number}")
62+
print(f"Link: {Fore.LIGHTCYAN_EX}{source}")
63+
print(f"{Fore.LIGHTGREEN_EX}====================================")
64+
"""
65+
Create a download folder for the anime
66+
"""
67+
folder = os.path.join(os.getcwd(), title)
68+
if not os.path.exists(folder):
69+
os.mkdir(folder)
70+
"""
71+
Check if the anime has episode 0 or not
72+
"""
73+
source = f"https://gogoanime.pe/{name}"
74+
resp = requests.get(source)
75+
soup = BeautifulSoup(resp.content, "html.parser")
76+
episode_zero = soup.find("h1", {"class": "entry-title"})
77+
if episode_zero is None:
78+
# Episode 0 does exist
79+
episode_links = bd.get_links(name, episode_number, source)
80+
download_links = bd.get_download_links(episode_links)
81+
download_urls = bd.get_download_urls(download_links, True)
82+
print(f"Downloading {Fore.LIGHTCYAN_EX}{len(download_urls)} episode/s")
83+
print(f"{Fore.LIGHTGREEN_EX}====================================")
84+
print(download_urls)
85+
bd.get_path(folder)
86+
thread_map(
87+
bd.download_episodes, download_urls, ncols=75, total=len(download_urls)
88+
)
89+
os.startfile(folder)
90+
91+
else:
92+
# Episode 0 does not exist
93+
episode_links = bd.get_links(name, episode_number)
94+
download_links = bd.get_download_links(episode_links)
95+
download_urls = bd.get_download_urls(download_links, False)
96+
print(
97+
f"Downloading {Fore.LIGHTCYAN_EX}{len(download_urls)}{Fore.RESET} episode/s"
98+
)
99+
print(f"{Fore.LIGHTGREEN_EX}====================================")
100+
bd.get_path(folder)
101+
thread_map(
102+
bd.download_episodes, download_urls, ncols=75, total=len(download_urls)
103+
)
104+
os.startfile(folder)
105+
use_again = input("Do you want to download other anime? (y|n) >> ").lower()
106+
if use_again == "y":
107+
again = True
108+
os.system("cls")
109+
else:
110+
again = False
111+
112+
113+
if __name__ == "__main__":
114+
bitanime()

0 commit comments

Comments
 (0)