Untitled

 avatar
user_9974085
python
a year ago
6.7 kB
3
Indexable
import requests
import bs4
import re
import os

from typing import Callable


def get_amount_of_authors_works(page_text: str) -> int:
	"""
	Вычисляет количество произведений автора
		Параметры:
			page_text (str): html-код страницы
		Возвращаемое значение:
			amount (int): количество произведений автора
	"""

	amount = int(re.search(r'Произведений: <b>(\d+)', page_text)[1])
	return amount


def get_authors_books(authors_books: list) -> list:
	"""
	Получает все сборники автора, а также количество произведений в сборнике и ссылки на них
		Параметры:
			authors_books (list): html-код списка сборников автора
		Возвращаемое значение:
			book_list (list): список списков, состоящих из названия, количества произведений и ссылки на сборник
	"""
	book_list = []
	for books in authors_books:

		soup = bs4.BeautifulSoup(str(books), 'html.parser')
		books_href = soup.a['href']

		temp_list = []
		for data in soup:
			text_split = data.text.split()
			name = " ".join(text_split[:-1])
			amount = text_split[-1]
			temp_list.extend([name, amount])

		temp_list.append(books_href)
		book_list.append(temp_list)
	return book_list


def get_works_from_books(amount: int, href: str, nickname: str) -> list:
	"""
	Получает все произведения автора из сборника, а также ссылки на них
		Параметры:
			amount (int): количество произведений в сборнике
			href (str): ссылка на сборник
			nickname (str): ник автора
		Возвращаемое значение:
			works_list (list): список списков, состоящих из названия и ссылки на произведение
	"""
	works_list = []
	session = requests.Session()
	for work_num in range(0, amount, 50):
		href = f'https://stihi.ru/avtor/{nickname}&s={work_num}&{href}'
		all_works_page = session.get(href).text
		soup = bs4.BeautifulSoup(all_works_page, 'html.parser')
		all_authors_works = soup.findAll('a', class_='poemlink')
		for data in all_authors_works:
			works_href = data['href']
			works_name = data.text
			works_list.append([works_href, works_name])

	return works_list


def get_text_of_each_authors_work(href: str) -> str:
	"""
	Получает текст произведения
		Параметры:
			href (str): ссылка на произведение автора
		Возвращаемое значение:
			text (str): текст произведения автора
	"""
	works_url = f'https://stihi.ru{href}'

	works_page = requests.get(works_url).text

	soup = bs4.BeautifulSoup(works_page, 'html.parser')
	works_page_text = soup.find('div', class_='text')

	text = works_page_text.text
	return text


def sanitize_name_of_work(name_of_work: str) -> str:
	"""
	Удаляет из названия произведения символы, которые нельзя использовать для наименования файлов
		Параметры:
			name_of_work (str): оригинальное название произведения
		Возвращаемое значение:
			clear_name (str): отредактированное название произведения
	"""
	forbidden_characters = r'''\/:*?"<>|'''
	clear_name = name_of_work.translate({ord(i): None for i in forbidden_characters})
	return clear_name


def check_name(func: Callable, old_name: str, end: str) -> str:
	"""
	Проверяет доступность имени файла/директории, если имя недоступно, то изменяет его, добавляя (1), (2) и т.д. к имени файла
		Параметры:
			func (Callable): функция, проверяющая доступность имени файла/директории
			old_name (str): оригинальное название файла/директории
			end (str): окончание названия, в случае с файлом нужно добавить .txt, в случае с директорией остается пустым
		Возвращаемое значение:
			new_name (str): отредактированное название файла/директории
	"""
	i = 1
	new_name = old_name
	while func(f'{new_name}{end}'):
		new_name = old_name + f' ({i})'
		i += 1
	return new_name


def create_files(works_list: list) -> None:
	"""
	Создает файлы с текстом произведений
		Параметры:
			works_list (list): список произведений автора
	"""
	for work in works_list:
		works_name = sanitize_name_of_work(work[1])
		works_text = get_text_of_each_authors_work(work[0])

		name = check_name(os.path.isfile, works_name, '.txt')

		with open(f'{name}.txt', 'w+') as file:
			file.write(works_text)


def main():

	author_nickname = input('Введите никнейм автора: ')

	# author_nickname = 'azhou' # MOCK NICKNAME

	author_page_url = f'https://stihi.ru/avtor/{author_nickname}'

	author_page_text = requests.get(author_page_url).text

	if 'Автор не найден' in author_page_text:
		print('Такой автор не найден на сайте stihi.ru, проверьте корректность ввода')
		return

	amount_of_authors_works = get_amount_of_authors_works(author_page_text)

	soup = bs4.BeautifulSoup(author_page_text, 'html.parser')
	all_authors_books = soup.findAll('div', id='bookheader')

	author_book_list = get_authors_books(all_authors_books)

	dir_name = check_name(os.path.isdir, author_nickname, '')

	os.mkdir(dir_name)
	os.chdir(dir_name)

	for book in author_book_list:
		if not os.path.isdir(book[0]):
			os.mkdir(book[0])
		os.chdir(book[0])

		amount_of_books_works = int(book[1].strip('()'))
		amount_of_authors_works -= amount_of_books_works
		books_href_end = '&' + book[2].split('&')[1]

		list_of_works_in_book = get_works_from_books(amount_of_books_works, books_href_end, author_nickname)

		create_files(list_of_works_in_book)

		os.chdir('..')

	list_of_works = get_works_from_books(amount_of_authors_works, '', author_nickname)

	create_files(list_of_works)


if __name__ == '__main__':
	main()
Editor is loading...
Leave a Comment