diff --git a/ipars/ParsManagerCode.py b/ipars/ParsManagerCode.py index 828c7ee..69ffb60 100644 --- a/ipars/ParsManagerCode.py +++ b/ipars/ParsManagerCode.py @@ -13,11 +13,14 @@ from cerberus import Validator class Pars: '''Модуль для работы с запросами и bs4''' + def __validation(self, schema, expected): + '''Валидация введённых данных для методов''' v = Validator(schema) if not v.validate(expected): raise ValueError(v.errors) + def listdir(self, path: str) -> dict: '''Возвращает список файлов в указанной директории''' schema = {'path': {'type': 'string'}} @@ -26,9 +29,10 @@ class Pars: return listdir(path) + def mkdir(self, nameDir: str): '''Создаёт папку если её ещё нет - + nameDir: название папки которая будет создана''' schema = {'nameDir': {'type': 'string'}} expected = {'nameDir': nameDir} @@ -37,6 +41,7 @@ class Pars: if not exists(nameDir): mkdir(nameDir) + def returnBs4Object(self, pathToFile: str, encoding: str = 'utf8', parser: str = 'lxml'): '''Возвращаем объект beautifulsoup @@ -44,6 +49,7 @@ class Pars: encoding: кодировка открытия html файла parser: парсер, который будет использоваться для работы''' + schema = { 'pathToFile': {'type': 'string'}, 'encoding': {'type': 'string'}, @@ -52,17 +58,21 @@ class Pars: expected = {'pathToFile': pathToFile, 'encoding': encoding, 'parser': parser} sels.__validation(schema, expected) + + # Открываем файл и возвращаем объяект bs4 на его основе with open(pathToFile, encoding=encoding) as file: src = file.read() soup = BeautifulSoup(src, parser) return soup + def getTexts(self, arr: list, needFix: bool = 0) -> list: '''Возвращаем текст из элементов bs4 arr: список объектов bs4 из которых будет извлекаться текст needFix (0/1): если этот параметр установлен как True, то из текста будут удалены \\n, \\t и пробелы с концов''' + schema = { 'arr': {'type': 'list'}, 'needFix': {'type': 'boolean'}, @@ -70,9 +80,12 @@ class Pars: expected = {'arr': arr, 'needFix': needFix} self.__validation(schema, expected) + result = [] for item in arr: data = item.text + + # Удаляем пробелы в начале и конце строки, табуляцию, переносы строки if needFix: data = data.strip() data = data.replace('\t', '') @@ -86,12 +99,14 @@ class Pars: return None return result + def getAttributes(self, arr: list, att: str) -> list: '''Возвращаем список значений атрибутов arr: список объектов bs4 из которых будет извлекаться атрибут att: строка с названием атрибута по которому будет осуществляться поиск''' + schema = { 'arr': {'type': 'list'}, 'att': {'type': 'string'} @@ -110,12 +125,14 @@ class Pars: return None return result + def pprint(self, data: any) -> None: '''Выводим данные в удобочитаемом виде data: данные которые надо вывести''' pprint(data) + def getStaticPage(self, pathToSaveFile: str, url: str, writeMethod: str = 'w', headers: dict = None) -> int: '''Сохраняем статическую страницу и возвращаем статус ответа от сервера @@ -124,8 +141,8 @@ class Pars: writeMethod: метод записи данных в файл. "w" записывает текст, "wb" — байты headers: заголовки запроса к серверу''' + # Устанавливаем случайный user-agent если пользователь не указал свой if headers is None: - # Получаем случайный user agent software_names = [ SoftwareName.FIREFOX.value, SoftwareName.CHROME.value, @@ -141,7 +158,6 @@ class Pars: ] user_agent_rotator = UserAgent(software_names=software_names, operating_systems=operating_systems, limit=10) user_agent = user_agent_rotator.get_random_user_agent() - headers = { "Accept": "*/*", "User-Agent": user_agent @@ -182,6 +198,7 @@ class Pars: except Exception as e: raise RuntimeError(e) from e + def __scrollAndSave(self, driver, timeSleep, pathToSaveFile): # Прокручиваем страницу до самого низа lastHeight = driver.execute_script("return document.body.scrollHeight") @@ -199,6 +216,7 @@ class Pars: with open(pathToSaveFile, "w", encoding="utf-8") as file: file.write(htmlContent) + def getDynamicPage(self, pathToSaveFile: str, url: str, closeWindow: bool = True, timeSleep: int = 2) -> None: '''Получаем динамическую страницу @@ -207,6 +225,7 @@ class Pars: closeWindow (False/True): если указана единица, то браузер открывается в фоновом режиме, 0 — открывается как обычное приложение timeSleep: время ожидания в секундах браузера перед тем как скролить страницу дальше''' + schema = { 'pathToSaveFile': {'type': 'string'}, 'url': {'type': 'string'}, @@ -217,7 +236,7 @@ class Pars: self.__validation(schema, expected) - # Устанавливаем опции для Chrome WebDriver + # Ставим настройку на запуск баузера в фоновом режиме, если closeWindow = True options = Options() if closeWindow: options.add_argument('--headless') @@ -227,6 +246,7 @@ class Pars: driver.get(url) self.__scrollAndSave(driver, timeSleep, pathToSaveFile) + def gpsa(self, pathToSaveFile: str, url: str, timeSleep=2): '''Получаем страницу в полуавтоматическом режиме gpsa - get page semi-automatically @@ -235,6 +255,7 @@ class Pars: url: ссылка на сайт timeSleep: время ожидания браузера перед тем как скролить страницу дальше''' + schema = { 'pathToSaveFile': {'type': 'string'}, 'url': {'type': 'string'}, @@ -243,7 +264,8 @@ class Pars: expected = {'pathToSaveFile': pathToSaveFile, 'url': url, 'timeSleep': timeSleep} self.__validation(schema, expected) + with webdriver.Chrome() as driver: driver.get(url) - a = input('Нажми ENTER когда закончишь') + a = input('Нажми ENTER когда окажешься на нужной тебе странице') self.__scrollAndSave(driver, timeSleep, pathToSaveFile)