Добавлены аннотации типов для методов в классах. Исправлены некоторые ошибки в методах и улучшена читаемость кода.
This commit is contained in:
@@ -1,11 +1,12 @@
|
|||||||
import csv
|
import csv
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
from typing import Any
|
||||||
from cerberus import Validator
|
from cerberus import Validator
|
||||||
|
|
||||||
class CsvManager:
|
class CsvManager:
|
||||||
'''Класс для работы с csv файлами во время парсинга'''
|
'''Класс для работы с csv файлами во время парсинга'''
|
||||||
|
|
||||||
def __init__(self, newline: str = '', encoding: str = 'utf8', delimiter: str = ';'):
|
def __init__(self, newline: str = '', encoding: str = 'utf8', delimiter: str = ';') -> None:
|
||||||
'''Конструктор
|
'''Конструктор
|
||||||
|
|
||||||
newline: новая строка в csv файле
|
newline: новая строка в csv файле
|
||||||
@@ -24,7 +25,7 @@ class CsvManager:
|
|||||||
self.encoding = encoding
|
self.encoding = encoding
|
||||||
self.delimiter = delimiter
|
self.delimiter = delimiter
|
||||||
|
|
||||||
def pprint(self, data: any) -> None:
|
def pprint(self, data: Any) -> None:
|
||||||
'''Выводим данные в удобочитаемом виде
|
'''Выводим данные в удобочитаемом виде
|
||||||
|
|
||||||
data: данные которые надо вывести'''
|
data: данные которые надо вывести'''
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import json
|
import json
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
from typing import Any
|
||||||
from cerberus import Validator
|
from cerberus import Validator
|
||||||
|
|
||||||
class JsonManager:
|
class JsonManager:
|
||||||
'''Класс для работы с json файлами во время парсинга'''
|
'''Класс для работы с json файлами во время парсинга'''
|
||||||
|
|
||||||
def __init__(self, encoding: str = 'utf8'):
|
def __init__(self, encoding: str = 'utf8') -> None:
|
||||||
'''Конструктор
|
'''Конструктор
|
||||||
|
|
||||||
encoding: кодировка открываемого файла'''
|
encoding: кодировка открываемого файла'''
|
||||||
@@ -18,13 +19,13 @@ class JsonManager:
|
|||||||
|
|
||||||
self.encoding = encoding
|
self.encoding = encoding
|
||||||
|
|
||||||
def pprint(self, data: any) -> None:
|
def pprint(self, data: Any) -> None:
|
||||||
'''Выводим данные в удобочитаемом виде
|
'''Выводим данные в удобочитаемом виде
|
||||||
|
|
||||||
data: данные которые надо вывести'''
|
data: данные которые надо вывести'''
|
||||||
pprint(data)
|
pprint(data)
|
||||||
|
|
||||||
def load(self, pathToJsonFile: str) -> json:
|
def load(self, pathToJsonFile: str) -> Any:
|
||||||
'''Получаем данные из json файла
|
'''Получаем данные из json файла
|
||||||
|
|
||||||
pathToJsonFile: путь до json файла'''
|
pathToJsonFile: путь до json файла'''
|
||||||
@@ -40,7 +41,7 @@ class JsonManager:
|
|||||||
src = json.load(jsonFile)
|
src = json.load(jsonFile)
|
||||||
return src
|
return src
|
||||||
|
|
||||||
def dump(self, pathToJsonFile: str, data: any) -> None:
|
def dump(self, pathToJsonFile: str, data: Any) -> None:
|
||||||
'''Записываем данные в json файл
|
'''Записываем данные в json файл
|
||||||
|
|
||||||
pathToJsonFile: путь до json файла
|
pathToJsonFile: путь до json файла
|
||||||
|
|||||||
+14
-12
@@ -5,6 +5,7 @@ from selenium import webdriver
|
|||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
from typing import Any, Optional
|
||||||
import requests
|
import requests
|
||||||
from os import mkdir, listdir
|
from os import mkdir, listdir
|
||||||
from os.path import exists
|
from os.path import exists
|
||||||
@@ -14,14 +15,14 @@ class Pars:
|
|||||||
'''Модуль для работы с запросами и bs4'''
|
'''Модуль для работы с запросами и bs4'''
|
||||||
|
|
||||||
|
|
||||||
def __validation(self, schema, expected):
|
def __validation(self, schema: dict, expected: dict) -> None:
|
||||||
'''Валидация введённых данных для методов'''
|
'''Валидация введённых данных для методов'''
|
||||||
v = Validator(schema)
|
v = Validator(schema)
|
||||||
if not v.validate(expected):
|
if not v.validate(expected):
|
||||||
raise ValueError(v.errors)
|
raise ValueError(v.errors)
|
||||||
|
|
||||||
|
|
||||||
def exists(self, path: str) -> dict:
|
def exists(self, path: str) -> bool:
|
||||||
'''Возвращает True если указанный файл или папка сущуствует, иначе — False'''
|
'''Возвращает True если указанный файл или папка сущуствует, иначе — False'''
|
||||||
schema = {'path': {'type': 'string'}}
|
schema = {'path': {'type': 'string'}}
|
||||||
expected = {'path': path}
|
expected = {'path': path}
|
||||||
@@ -30,7 +31,7 @@ class Pars:
|
|||||||
return exists(path)
|
return exists(path)
|
||||||
|
|
||||||
|
|
||||||
def listdir(self, path: str) -> dict:
|
def listdir(self, path: str) -> list:
|
||||||
'''Возвращает список файлов в указанной директории'''
|
'''Возвращает список файлов в указанной директории'''
|
||||||
schema = {'path': {'type': 'string'}}
|
schema = {'path': {'type': 'string'}}
|
||||||
expected = {'path': path}
|
expected = {'path': path}
|
||||||
@@ -39,7 +40,7 @@ class Pars:
|
|||||||
return listdir(path)
|
return listdir(path)
|
||||||
|
|
||||||
|
|
||||||
def mkdir(self, nameDir: str):
|
def mkdir(self, nameDir: str) -> None:
|
||||||
'''Создаёт папку если её ещё нет
|
'''Создаёт папку если её ещё нет
|
||||||
|
|
||||||
nameDir: название папки которая будет создана'''
|
nameDir: название папки которая будет создана'''
|
||||||
@@ -51,7 +52,7 @@ class Pars:
|
|||||||
mkdir(nameDir)
|
mkdir(nameDir)
|
||||||
|
|
||||||
|
|
||||||
def returnBs4Object(self, pathToFile: str, encoding: str = 'utf8', parser: str = 'lxml'):
|
def returnBs4Object(self, pathToFile: str, encoding: str = 'utf8', parser: str = 'lxml') -> BeautifulSoup:
|
||||||
'''Возвращаем объект beautifulsoup
|
'''Возвращаем объект beautifulsoup
|
||||||
|
|
||||||
pathToFile: путь до html файла
|
pathToFile: путь до html файла
|
||||||
@@ -75,7 +76,7 @@ class Pars:
|
|||||||
return soup
|
return soup
|
||||||
|
|
||||||
|
|
||||||
def getTexts(self, arr: list, needFix: bool = False) -> list:
|
def getTexts(self, arr: list, needFix: bool = False) -> Optional[list]:
|
||||||
'''Возвращаем текст из элементов bs4
|
'''Возвращаем текст из элементов bs4
|
||||||
|
|
||||||
arr: список объектов bs4 из которых будет извлекаться текст
|
arr: список объектов bs4 из которых будет извлекаться текст
|
||||||
@@ -109,7 +110,7 @@ class Pars:
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def getAttributes(self, arr: list, att: str) -> list:
|
def getAttributes(self, arr: list, att: str) -> Optional[list]:
|
||||||
'''Возвращаем список значений атрибутов
|
'''Возвращаем список значений атрибутов
|
||||||
|
|
||||||
arr: список объектов bs4 из которых будет извлекаться атрибут
|
arr: список объектов bs4 из которых будет извлекаться атрибут
|
||||||
@@ -135,14 +136,14 @@ class Pars:
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def pprint(self, data: any) -> None:
|
def pprint(self, data: Any) -> None:
|
||||||
'''Выводим данные в удобочитаемом виде
|
'''Выводим данные в удобочитаемом виде
|
||||||
|
|
||||||
data: данные которые надо вывести'''
|
data: данные которые надо вывести'''
|
||||||
pprint(data)
|
pprint(data)
|
||||||
|
|
||||||
|
|
||||||
def getStaticPage(self, pathToSaveFile: str, url: str, writeMethod: str = 'w', headers: dict = None) -> int:
|
def getStaticPage(self, pathToSaveFile: str, url: str, writeMethod: str = 'w', headers: Optional[dict] = None) -> int:
|
||||||
'''Сохраняем статическую страницу и возвращаем статус ответа от сервера
|
'''Сохраняем статическую страницу и возвращаем статус ответа от сервера
|
||||||
|
|
||||||
pathToSaveFile: путь, куда сохранится полученный файл
|
pathToSaveFile: путь, куда сохранится полученный файл
|
||||||
@@ -186,6 +187,7 @@ class Pars:
|
|||||||
try:
|
try:
|
||||||
# Отправляем запрос
|
# Отправляем запрос
|
||||||
req = requests.get(url, headers=headers)
|
req = requests.get(url, headers=headers)
|
||||||
|
req.raise_for_status()
|
||||||
|
|
||||||
# Записываем данные
|
# Записываем данные
|
||||||
if writeMethod == 'w':
|
if writeMethod == 'w':
|
||||||
@@ -203,12 +205,12 @@ class Pars:
|
|||||||
return req.status_code # Возвращаем статус ответа от сервера
|
return req.status_code # Возвращаем статус ответа от сервера
|
||||||
|
|
||||||
except requests.exceptions.HTTPError as httpErr:
|
except requests.exceptions.HTTPError as httpErr:
|
||||||
raise RuntimeError(f"HTTP ошибка: {httpErr}") from http_err
|
raise RuntimeError(f"HTTP ошибка: {httpErr}") from httpErr
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise RuntimeError(e) from e
|
raise RuntimeError(e) from e
|
||||||
|
|
||||||
|
|
||||||
def __scrollAndSave(self, driver, timeSleep, pathToSaveFile):
|
def __scrollAndSave(self, driver: webdriver.Chrome, timeSleep: int, pathToSaveFile: str) -> None:
|
||||||
# Прокручиваем страницу до самого низа
|
# Прокручиваем страницу до самого низа
|
||||||
lastHeight = driver.execute_script("return document.body.scrollHeight")
|
lastHeight = driver.execute_script("return document.body.scrollHeight")
|
||||||
while True:
|
while True:
|
||||||
@@ -256,7 +258,7 @@ class Pars:
|
|||||||
self.__scrollAndSave(driver, timeSleep, pathToSaveFile)
|
self.__scrollAndSave(driver, timeSleep, pathToSaveFile)
|
||||||
|
|
||||||
|
|
||||||
def gpsa(self, pathToSaveFile: str, url: str, timeSleep=2):
|
def gpsa(self, pathToSaveFile: str, url: str, timeSleep: int = 2) -> None:
|
||||||
'''Получаем страницу в полуавтоматическом режиме
|
'''Получаем страницу в полуавтоматическом режиме
|
||||||
gpsa - get page semi-automatically
|
gpsa - get page semi-automatically
|
||||||
|
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ class ProgressBarManager:
|
|||||||
color: цвет прогресс-бара
|
color: цвет прогресс-бара
|
||||||
fill: заполнитель для сделанной части
|
fill: заполнитель для сделанной части
|
||||||
width: размер прогресс-бара в символах'''
|
width: размер прогресс-бара в символах'''
|
||||||
def __init__(self, max, message='Процесс работы', color='green', fill='#', width=32):
|
def __init__(self, max: int, message: str = 'Процесс работы', color: str = 'green', fill: str = '#', width: int = 32) -> None:
|
||||||
self.bar = Bar(max=max, message=message, color=color, fill=fill, suffix='%(index)d/%(max)d (%(percent)d%%)', width=width)
|
self.bar = Bar(max=max, message=message, color=color, fill=fill, suffix='%(index)d/%(max)d (%(percent)d%%)', width=width)
|
||||||
|
|
||||||
def next(self):
|
def next(self) -> None:
|
||||||
'''Запускаем следущую итерацию прогресс-бара'''
|
'''Запускаем следущую итерацию прогресс-бара'''
|
||||||
self.bar.next()
|
self.bar.next()
|
||||||
|
|
||||||
def finish(self):
|
def finish(self) -> None:
|
||||||
'''Завершаем работу класса'''
|
'''Завершаем работу класса'''
|
||||||
self.bar.finish()
|
self.bar.finish()
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
import time
|
import time
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
class TimerManager:
|
class TimerManager:
|
||||||
'''Класс для отслеживания времени работы'''
|
'''Класс для отслеживания времени работы'''
|
||||||
def __init__(self):
|
def __init__(self) -> None:
|
||||||
'''Инициализация'''
|
'''Инициализация'''
|
||||||
self.startTime = 0
|
self.startTime = 0
|
||||||
self.endTime = 0
|
self.endTime = 0
|
||||||
@@ -17,7 +18,7 @@ class TimerManager:
|
|||||||
self.endTime = time.time()
|
self.endTime = time.time()
|
||||||
self.workTime = self.endTime - self.startTime
|
self.workTime = self.endTime - self.startTime
|
||||||
|
|
||||||
def getWorkTime(self, format :str = 'seconds', ndigits :int = None) -> int:
|
def getWorkTime(self, format: str = 'seconds', ndigits: Optional[int] = None) -> float:
|
||||||
'''Возвращает время в нужном формате'''
|
'''Возвращает время в нужном формате'''
|
||||||
time_units = {
|
time_units = {
|
||||||
'seconds': 1,
|
'seconds': 1,
|
||||||
@@ -30,7 +31,7 @@ class TimerManager:
|
|||||||
raise ValueError('Для замера времени обязательно надо использовать метод "start" ДО выполнения кода')
|
raise ValueError('Для замера времени обязательно надо использовать метод "start" ДО выполнения кода')
|
||||||
|
|
||||||
if self.endTime == 0:
|
if self.endTime == 0:
|
||||||
raise ValueError('Для замера времени обязательно надо использовать метод "stop" ПОСЛЕ выполнения кода')
|
raise ValueError('Для замера времени обязательно надо использовать метод "end" ПОСЛЕ выполнения кода')
|
||||||
|
|
||||||
if format not in time_units:
|
if format not in time_units:
|
||||||
raise ValueError(f"Неподдерживаемый формат '{format}'. Должен быть один из {list(time_units.keys())}")
|
raise ValueError(f"Неподдерживаемый формат '{format}'. Должен быть один из {list(time_units.keys())}")
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ class ZipManager:
|
|||||||
- 'hard': Увеличенное сжатие
|
- 'hard': Увеличенное сжатие
|
||||||
- 'maximum': Максимальное сжатие
|
- 'maximum': Максимальное сжатие
|
||||||
"""
|
"""
|
||||||
def __init__(self, compression :str = 'normal'):
|
def __init__(self, compression: str = 'normal') -> None:
|
||||||
self.compression = self.setСompression(compression)
|
self.compression = self.setCompression(compression)
|
||||||
|
|
||||||
def setСompression(self, compressionStr):
|
def setCompression(self, compressionStr: str) -> int:
|
||||||
if compressionStr == 'none':
|
if compressionStr == 'none':
|
||||||
return zipfile.ZIP_STORED
|
return zipfile.ZIP_STORED
|
||||||
elif compressionStr == 'normal':
|
elif compressionStr == 'normal':
|
||||||
@@ -25,7 +25,7 @@ class ZipManager:
|
|||||||
else:
|
else:
|
||||||
raise ValueError("Некорректное значение compression. Допустимы значения none, normal, hard, maximun")
|
raise ValueError("Некорректное значение compression. Допустимы значения none, normal, hard, maximun")
|
||||||
|
|
||||||
def zipFile(self, filePath:str, zipFilePath:str):
|
def zipFile(self, filePath: str, zipFilePath: str) -> None:
|
||||||
"""Архивируем один файл
|
"""Архивируем один файл
|
||||||
|
|
||||||
filePath (str): Путь к файлу, который нужно заархивировать
|
filePath (str): Путь к файлу, который нужно заархивировать
|
||||||
@@ -35,7 +35,7 @@ class ZipManager:
|
|||||||
with zipfile.ZipFile(zipFilePath, 'w', compression=self.compression) as zipf:
|
with zipfile.ZipFile(zipFilePath, 'w', compression=self.compression) as zipf:
|
||||||
zipf.write(filePath, os.path.basename(filePath))
|
zipf.write(filePath, os.path.basename(filePath))
|
||||||
|
|
||||||
def zipFolder(self, folderPath:str, zipFilePath:str):
|
def zipFolder(self, folderPath: str, zipFilePath: str) -> None:
|
||||||
"""Архивируем папку
|
"""Архивируем папку
|
||||||
|
|
||||||
folderPath (str): Путь к папке, которую нужно заархивировать
|
folderPath (str): Путь к папке, которую нужно заархивировать
|
||||||
|
|||||||
Reference in New Issue
Block a user