Compare commits

...

4 Commits

Author SHA1 Message Date
c0c013c31b
fix return message 2022-09-16 02:55:28 +03:00
ca50802d3f
add spinner 2022-09-16 02:12:15 +03:00
a5233d3d28
total downloaded notify 2022-09-16 02:07:38 +03:00
eb1ce5db14
remove resume feature 2022-09-16 02:01:52 +03:00
2 changed files with 59 additions and 92 deletions

View File

@ -1,2 +1,3 @@
requests==2.28.1 requests==2.28.1
beautifulsoup4==4.11.1 beautifulsoup4==4.11.1
click==8.1.3

View File

@ -7,62 +7,45 @@ import shutil
import os.path import os.path
import requests import requests
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
import click
__author__ = "Alexander Popov" __author__ = "Alexander Popov"
__version__ = "1.0.2" __version__ = "1.0.3"
__license__ = "Unlicense" __license__ = "Unlicense"
# Путь к директории для загрузки изображений # Путь к директории для загрузки изображений
DOWNLOAD_DIRECTORY = "./images" DOWNLOAD_DIRECTORY = "./images"
# Количество загружаемых страниц
DOWNLOAD_PAGES = 0
def resume_load(): def print_version(ctx, param, value):
"""Возвращает список последних 20 загруженных файлов""" if not value or ctx.resilient_parsing:
return
# Проверяет наличие файла .resume click.echo("Версия: {0}".format(__version__))
if not os.path.exists( ctx.exit()
"{0}/.resume".format(
DOWNLOAD_DIRECTORY,
)
):
# Создаёт директорию для загрузки сисек
if not os.path.exists(DOWNLOAD_DIRECTORY):
os.mkdir(DOWNLOAD_DIRECTORY)
# Создаёт файл .resume и пишет в него 0
with open(
"{0}/.resume".format(
DOWNLOAD_DIRECTORY,
),
"w",
) as f:
f.write("0")
return [0]
else:
with open(
"{0}/.resume".format(
DOWNLOAD_DIRECTORY,
),
"r",
) as f:
lines = [int(line.split("\n")[0]) for line in f][-20:]
return lines
def resume_save(donwloaded_list): @click.command(add_help_option=False)
"""Сохраняет список последних 20 загруженных файлов""" @click.option(
"--directory",
donwloaded_list.sort() default="./images",
with open( help="Путь к директории для загрузки изображений.",
"{0}/.resume".format( )
DOWNLOAD_DIRECTORY, @click.option("--pages", default=0, help="Количество загружаемых страниц.")
), @click.option(
"w", "--version",
encoding="utf-8", "-v",
) as f: is_flag=True,
for item in donwloaded_list[-20:]: callback=print_version,
f.write("{0}\n".format(item)) is_eager=True,
help="Отобразить версию программы.",
)
@click.help_option("--help", "-h", help="Показать эту справку")
def click(directory, pages, version):
DOWNLOAD_DIRECTORY = directory
DOWNLOAD_PAGES = pages
main(DOWNLOAD_DIRECTORY, DOWNLOAD_PAGES)
def get_images_links(page): def get_images_links(page):
@ -109,12 +92,10 @@ def image_download(image):
image_size = int(response.headers.get("Content-Length", 0)) image_size = int(response.headers.get("Content-Length", 0))
if ( if (
os.path.exists("{0}/{1}".format(DOWNLOAD_DIRECTORY, image)) not os.path.exists("{0}/{1}".format(DOWNLOAD_DIRECTORY, image))
and int(os.path.getsize("{0}/{1}".format(DOWNLOAD_DIRECTORY, image))) or int(os.path.getsize("{0}/{1}".format(DOWNLOAD_DIRECTORY, image)))
== image_size != image_size
): ):
pass
else:
with open("{0}/{1}".format(DOWNLOAD_DIRECTORY, image), "wb") as out_image: with open("{0}/{1}".format(DOWNLOAD_DIRECTORY, image), "wb") as out_image:
shutil.copyfileobj( shutil.copyfileobj(
response.raw, response.raw,
@ -122,15 +103,16 @@ def image_download(image):
) )
if __name__ == "__main__": def main(download_directory, download_pages):
"""Главный цикл программы""" """Главный цикл программы"""
if not os.path.exists(download_directory):
resume_files = resume_load() os.mkdir(download_directory)
current_page = 0 current_page = 0
downloaded_counter = 0 downloaded_counter = 0
WHILE_BREAK = False spinner = ["◢◣◤◥", "◰◳◲◱", "◴◷◶◵", "◐◓◑◒", "|/-\\"]
spinner_id = 0
while True: while True:
try: try:
@ -138,50 +120,34 @@ if __name__ == "__main__":
images = get_images_links(current_page) images = get_images_links(current_page)
images.sort() images.sort()
# Костыль # Проверка на количество загруженных страниц
if WHILE_BREAK: # аргумент --pages
break if current_page >= download_pages and download_pages != 0:
print("\nВсего загружено {0} файлов.".format(downloaded_counter))
quit()
# По очереди скачиваем изображения # По очереди скачиваем изображения
for image in images: for image in images:
# На сайте могут обновляться изображения, image_download(image)
# когда находятся варианты более лучшего downloaded_counter += 1
# качества и разрешения.
# К именам таких файлов добавляется _NUM,
# где NUM - количество изменений,
# например 1356_3.jpg
# Файл .resume хранит последние 20 загруженных файлов. print(
# Бывает иногда, что изображение удаляется "\r{spinner} Загружено {total_files} файлов.".format(
# и может получиться так, что сохраненное имя в .resume total_files=downloaded_counter, spinner=spinner[2][spinner_id]
# будет отсутсвовать на странице, что будет в холостую ),
# продолжать работу скрипта. end="",
)
# Файлы на странице расположены в обратном порядке, if spinner_id < 3:
# для этого перед их загрузкой и сохранением в .resume spinner_id += 1
# списки сортируются от меньшего к большему.
# По этому было принято решение, удалять часть _NUM
# из имени файла при сохранение в .resume.
# Один хуй никто не будет парсить сайт с самого начала,
# чтобы скачать сиськи в более высоком качестве.
# Если в списке resume присутствует текущий загружаемый файл
# тогда цикл программы останавливается.
# P.S. смотри на костыль WHILE_BREAK
if not int(image.split(".")[0].split("_")[0]) in resume_files:
image_download(image)
resume_files.insert(
0,
int(image.split(".")[0].split("_")[0]),
)
downloaded_counter += 1
resume_save(resume_files)
else: else:
WHILE_BREAK = True spinner_id = 0
break
current_page += 1 current_page += 1
except KeyboardInterrupt: except KeyboardInterrupt:
print("Загружено {0} файлов.".format(downloaded_counter)) print("\nВсего загружено {0} файлов.".format(downloaded_counter))
quit() quit()
if __name__ == "__main__":
click()