188 lines
6.8 KiB
Python
Executable File
188 lines
6.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
|
||
"""Скрипт для скачивания голых и не только девушек с блога blog.stanis.ru"""
|
||
|
||
import re
|
||
import shutil
|
||
import os.path
|
||
import requests
|
||
from bs4 import BeautifulSoup
|
||
|
||
__author__ = "Alexander Popov"
|
||
__version__ = "1.0.2"
|
||
__license__ = "Unlicense"
|
||
|
||
# Путь к директории для загрузки изображений
|
||
DOWNLOAD_DIRECTORY = "./images"
|
||
|
||
|
||
def resume_load():
|
||
"""Возвращает список последних 20 загруженных файлов"""
|
||
|
||
# Проверяет наличие файла .resume
|
||
if not os.path.exists(
|
||
"{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):
|
||
"""Сохраняет список последних 20 загруженных файлов"""
|
||
|
||
donwloaded_list.sort()
|
||
with open(
|
||
"{0}/.resume".format(
|
||
DOWNLOAD_DIRECTORY,
|
||
),
|
||
"w",
|
||
encoding="utf-8",
|
||
) as f:
|
||
for item in donwloaded_list[-20:]:
|
||
f.write("{0}\n".format(item))
|
||
|
||
|
||
def get_images_links(page):
|
||
"""В качестве аргумента получает номер страницы
|
||
и возвращает списком адреса всех изображений"""
|
||
|
||
# На сайте фильтр изображений настроен через cookies
|
||
# Так что устанавливаем их в нужное положение
|
||
cookies = dict(block="951")
|
||
|
||
# Загружаем страницу и подсовываем её парсеру с необходимыми параметрами
|
||
r = requests.get(
|
||
"http://blog.stanis.ru/?back={0}".format(
|
||
page,
|
||
),
|
||
cookies=cookies,
|
||
)
|
||
soup = BeautifulSoup(
|
||
r.text.encode("cp1251"), "html.parser", from_encoding="windows-1251"
|
||
)
|
||
|
||
# Получаем все теги <img> на странице
|
||
img_tags = soup.findAll("img", src=re.compile("img/*"))
|
||
|
||
# Получаем все адреса изображений и сохраняем их в список img_links
|
||
img_links = list()
|
||
for image in img_tags:
|
||
img_links.append(image["src"].split("/")[1])
|
||
|
||
return img_links
|
||
|
||
|
||
def image_download(image):
|
||
"""В качестве аргумента получает уникальное имя изображения,
|
||
скачивает и сохраняет его на диск"""
|
||
|
||
response = requests.get(
|
||
"https://blog.stanis.ru/imgs/{0}".format(
|
||
image,
|
||
),
|
||
stream=True,
|
||
)
|
||
|
||
image_size = int(response.headers.get("Content-Length", 0))
|
||
|
||
if (
|
||
os.path.exists("{0}/{1}".format(DOWNLOAD_DIRECTORY, image))
|
||
and int(os.path.getsize("{0}/{1}".format(DOWNLOAD_DIRECTORY, image)))
|
||
== image_size
|
||
):
|
||
pass
|
||
else:
|
||
with open("{0}/{1}".format(DOWNLOAD_DIRECTORY, image), "wb") as out_image:
|
||
shutil.copyfileobj(
|
||
response.raw,
|
||
out_image,
|
||
)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
"""Главный цикл программы"""
|
||
|
||
resume_files = resume_load()
|
||
|
||
current_page = 0
|
||
downloaded_counter = 0
|
||
|
||
WHILE_BREAK = False
|
||
|
||
while True:
|
||
try:
|
||
# Получаем адреса изображений и сортируем их в порядке возрастания
|
||
images = get_images_links(current_page)
|
||
images.sort()
|
||
|
||
# Костыль
|
||
if WHILE_BREAK:
|
||
break
|
||
|
||
# По очереди скачиваем изображения
|
||
for image in images:
|
||
# На сайте могут обновляться изображения,
|
||
# когда находятся варианты более лучшего
|
||
# качества и разрешения.
|
||
# К именам таких файлов добавляется _NUM,
|
||
# где NUM - количество изменений,
|
||
# например 1356_3.jpg
|
||
|
||
# Файл .resume хранит последние 20 загруженных файлов.
|
||
# Бывает иногда, что изображение удаляется
|
||
# и может получиться так, что сохраненное имя в .resume
|
||
# будет отсутсвовать на странице, что будет в холостую
|
||
# продолжать работу скрипта.
|
||
|
||
# Файлы на странице расположены в обратном порядке,
|
||
# для этого перед их загрузкой и сохранением в .resume
|
||
# списки сортируются от меньшего к большему.
|
||
|
||
# По этому было принято решение, удалять часть _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:
|
||
WHILE_BREAK = True
|
||
break
|
||
|
||
current_page += 1
|
||
except KeyboardInterrupt:
|
||
print("Загружено {0} файлов.".format(downloaded_counter))
|
||
quit()
|