diff --git a/.gitignore b/.gitignore index 5028265..4bfd3bc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ token.txt -.docx \ No newline at end of file +.docx +src/__pycache__/ +result.txt +.idea/ +.DS_Store \ No newline at end of file diff --git a/README.md b/README.md index 29bc15f..add2b65 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -# work -Генератор автоматического отчета о проведенных indoor измерениях +# WB +Парсинг позиций с ВБ и сохранение их в БД diff --git a/db/positions.db b/db/positions.db new file mode 100644 index 0000000..8df286e Binary files /dev/null and b/db/positions.db differ diff --git a/responses/142400300.txt b/responses/142400300.txt new file mode 100644 index 0000000..4551064 --- /dev/null +++ b/responses/142400300.txt @@ -0,0 +1,54 @@ +16:03:2023 20:26:42 +None(None) +None(None) +386(4) +171(2) +74(1) +499(5) +None(None) +423(5) +460(5) +4876(49) +3326(34) +233(3) +4730(48) +4740(48) +4740(48) +279(3) +5088(51) +5086(51) +1545(16) +368(4) +1300(14) +423(5) +460(5) +170(2) +None(None) +4730(48) +None(None) +4973(50) +5105(52) +3393(34) +None(None) +1894(19) +2073(21) +None(None) +None(None) +None(None) +4413(45) +None(None) +None(None) +3301(34) +None(None) +47(1) +544(6) +1969(20) +2(1) +1097(11) +2058(21) +1191(12) +912(10) +101(2) +1524(16) +48(1) +98(1) diff --git a/responses/142400304.txt b/responses/142400304.txt new file mode 100644 index 0000000..a34e3c4 --- /dev/null +++ b/responses/142400304.txt @@ -0,0 +1,55 @@ +16:03:2023 21:23:09 +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) +None(None) diff --git a/responses/145934856.txt b/responses/145934856.txt new file mode 100644 index 0000000..46f96a5 --- /dev/null +++ b/responses/145934856.txt @@ -0,0 +1,59 @@ +16:03:2023 10:04:55 +None(None) +None(None) +1840(19) +371(4) +2313(24) +1819(19) +4587(46) +None(None) +1303(14) +None(None) +896(9) +1422(15) +3432(35) +3703(38) +None(None) +None(None) +None(None) +4951(50) +None(None) +None(None) +1109(12) +None(None) +1303(14) +None(None) +367(4) +4914(50) +3703(38) +None(None) +808(9) +725(8) +None(None) +None(None) +425(5) +2546(26) +None(None) +89(1) +7(1) +1(1) +399(4) +568(6) +None(None) +None(None) +1448(15) +40(1) +32(1) +74(1) +314(4) +200(3) +190(2) +63(1) +109(2) +None(None) +None(None) +190(2) +113(2) +599(6) +262(3) +None(None) diff --git a/sql_queries/create_db.sql b/sql_queries/create_db.sql new file mode 100644 index 0000000..0cb2d95 --- /dev/null +++ b/sql_queries/create_db.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS Positions + ( + date TEXT PRIMARY KEY, + item_ID INTEGER, + request TEXT, + item_position INTEGER + ) \ No newline at end of file diff --git a/src/142400300.txt b/src/142400300.txt deleted file mode 100644 index b88f2f5..0000000 --- a/src/142400300.txt +++ /dev/null @@ -1 +0,0 @@ -сумка женская \ No newline at end of file diff --git a/src/constants.py b/src/constants.py index 8f56ae5..4e433b7 100644 --- a/src/constants.py +++ b/src/constants.py @@ -1,4 +1,5 @@ USER_REQUESTS = "142400300.txt" -DEFAULT_ITEM_ID = 142400300 -MAX_PAGE = 60 -HEADER = {'Accept': "*/*", 'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"} \ No newline at end of file +DEFAULT_ITEM_ID = 145934856 +MAX_PAGE = 20 +HEADER = {'Accept': "*/*", 'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"} +MAX_LIMIT = 300 diff --git a/src/data.json b/src/data.json deleted file mode 100644 index e69de29..0000000 diff --git a/src/db_class.py b/src/db_class.py new file mode 100644 index 0000000..5f65aca --- /dev/null +++ b/src/db_class.py @@ -0,0 +1,43 @@ +import sqlite3 +import os + + +class PositionsDB: + + def __init__(self): + self.db_path = 'db/positions.db' + self.connect = sqlite3.connect(self.db_path) + self.cursor = self.connect.cursor() + + def create_db(self): + query = f""" + CREATE TABLE IF NOT EXISTS Positions + ( + id INTEGER PRIMARY KEY, + date TEXT, + item_ID INTEGER, + request TEXT, + item_position INTEGER + ) + """ + self.cursor.execute(query) + return self + + def select_all(self): + query = f""" SELECT * FROM Positions """ + result = self.cursor.execute(query) + print(self.cursor.fetchall()) + return result + + def insert_row(self, data_dict: dict): + query = f""" INSERT OR REPLACE INTO Positions (date, item_ID, request, item_position) + VALUES ('{data_dict.get('date')}', {data_dict.get('item_ID')}, + '{data_dict.get('request')}', {data_dict.get('position')}) + """ + self.cursor.execute(query) + + def commit(self): + self.connect.commit() + + def disconnect(self): + self.connect.close() diff --git a/src/get_external.py b/src/get_external.py index 7886633..08d3a05 100644 --- a/src/get_external.py +++ b/src/get_external.py @@ -1,13 +1,31 @@ import os -from constants import * class InfoImport: - def __init__(self, item_id=DEFAULT_ITEM_ID, user_request=None, user_requests_list=None): - self.item_id = item_id - self.user_request = user_request - self.user_requests_list = user_requests_list + def __init__(self): + self.mode = 1 + self.item_id = None + self.user_request = None + self.user_requests_list = None + + def select_mode(self): + mode = -1 + while 0 > mode or mode > 4: + print('Выберите режим работы:\n' + '0 - Выход из программы\n' + '1 - Одиночный запрос для одного артикула\n' + '2 - Одиночный запрос для нескольких артикулов\n' + '3 - Множественный запрос для одного артикула\n' + '4 - Множественный запрос для нескольких артикулов\n') + mode = input('Введите цифру от 0 до 4: ') + try: + mode = int(mode) + except ValueError: + mode = -1 + print('Это не цифра\n') + self.mode = mode + return self def get_user_request(self): request = input("Enter user request: ") @@ -21,15 +39,44 @@ def get_item_id(self): except ValueError: return 1 + def get_items(self): + self.item_id = [] + path = f'user_requests/items.txt' + if not os.path.isfile(path): + return 1 + with open(path, "r") as file: + self.item_id = [x for x in file.readlines()] + + items = [] + for item in self.item_id: + try: + items.append(int(item)) + except ValueError: + pass + + self.item_id = items + return self.item_id + def get_user_requests_list(self): - path = f'{self.item_id}.txt' + path = f'user_requests/{self.item_id}.txt' if not os.path.isfile(path): return 1 self.user_requests_list = [] - with open(path, "r") as file: + with open(path, "r", encoding='utf-8') as file: for line in file.readlines(): self.user_requests_list.append(line.replace(" ", "+").replace("\n", "")) if len(self.user_requests_list) > 0: return self.user_requests_list return 1 + def get_common_requests_list(self): + path = f'user_requests/common.txt' + if not os.path.isfile(path): + return 1 + self.user_requests_list = [] + with open(path, "r", encoding='utf-8') as file: + for line in file.readlines(): + self.user_requests_list.append(line.replace(" ", "+").replace("\n", "")) + if len(self.user_requests_list) > 0: + return self.user_requests_list + return 1 diff --git a/src/main.py b/src/main.py index 9b881b3..5995928 100644 --- a/src/main.py +++ b/src/main.py @@ -1,14 +1,183 @@ -from get_external import InfoImport -from wb_parser import Request +from wb_parser import Request, WBParser, Mode from constants import * +import os +import time +from datetime import datetime +from db_class import PositionsDB -info = InfoImport() +# user = InfoImport() # info.get_user_request() # print(info.user_request) # print(info.get_user_requests_list()) +# for request_text in user_requests: +# for current_page in range(1, 3, 3): +# r = Request(DEFAULT_ITEM_ID, request_text, current_page).get_request() +# #d = r.get_data() +# print(r.request) -request_text = info.get_user_request() -for current_page in range(1, 3, 3): - r = Request(DEFAULT_ITEM_ID, request_text, current_page).get_request() - #d = r.get_data() - print(r.request) + +def wait(): + print('Ждем 20 сек, т.к. превышено количество запросов') + for i in range(20): + print(f'Ждем {i}сек') + time.sleep(1) + + +def get_all_requests_positions(item_id, user_requests): + if isinstance(user_requests, list): + positions_list = [] + counter = 0 + req_len = len(user_requests) + for request_text in user_requests: + counter += 1 + if counter % 10 == 0: + wait() + positions_list.append(get_one_request_position(item_id, request_text)) + print(f'{counter}/{req_len}') + return positions_list + else: + return get_one_request_position(item_id, user_requests) + + +def get_one_request_position(item_id, request_text): + for current_page in range(1, MAX_PAGE): + request = Request(item_id, request_text, current_page).get_request() + response = request.get_data() + if response is not None: + position = WBParser(request.item_id, response).get_position() + if position != -1: + return position + (current_page - 1) * MAX_LIMIT + + return None + + +def clear_terminal(): + # os.system('cls' if os.name == 'nt' else 'clear') + # print(chr(27) + "[2J") + # os.system('clear') + print("\033c\033[3J") + + +def get_page(position): + try: + return int(position / 100) + 1 + except TypeError: + return None + + +def mode_1(usr, db): + print('It\'s mode_1') + item_id = usr.get_item_id() + if item_id == 0: + return 0 + request = usr.get_user_request() + if request == 0: + return 0 + position = get_all_requests_positions(item_id, request) + page = get_page(position) + date = datetime.now().strftime("%d:%m:%Y") + row_db = update_dict(date, item_id, request, position) + print(f'item_id = {item_id}, request = {request}, position = {position}, page = {page}\n') + db.insert_row(row_db) + + +def mode_2(usr, db): + print('It\'s mode_2') + if isinstance(usr.item_id, int) or isinstance(usr.item_id, str) or usr.item_id is None: + usr.get_items() + print(usr.item_id) + if len(usr.item_id) == 0: + print('Нет значений в файле Items.txt') + return 0 + request = usr.get_user_request() + if request == '0': + return 0 + positions = {} + for item in usr.item_id: + position = get_one_request_position(item, request) + page = get_page(position) + positions.update({item: position}) + date = datetime.now().strftime("%d:%m:%Y") + row_db = update_dict(date, item, request, position) + print(f'item_id = {item}, request = {request}, position = {position}, page = {page}\n') + db.insert_row(row_db) + + +def mode_3(usr, db): + print('It\'s mode_3') + item_id = usr.get_item_id() + if item_id == 1: + return 0 + requests = usr.get_user_requests_list() + if requests == 1: + return 0 + positions = get_all_requests_positions(item_id, requests) + i = 0 + for position in positions: + page = get_page(position) + date = datetime.now().strftime("%d:%m:%Y") + row_db = update_dict(date, item_id, requests[i], position) + print(f'request = {requests[i]}, position={position}, page = {page}') + db.insert_row(row_db) + i += 1 + save_file(item_id, positions) + return 0 + + +def mode_4(usr, db): + print('It\'s mode_4') + items_id = usr.get_items() + requests = usr.get_common_requests_list() + for item in items_id: + positions = get_all_requests_positions(item, requests) + i = 0 + for position in positions: + page = get_page(position) + date = datetime.now().strftime("%d:%m:%Y") + row_db = update_dict(date, item, requests[i], position) + print(f'item_id = {item}, request = {requests[i]}, position={position}, page = {page}') + db.insert_row(row_db) + i += 1 + save_file(item, positions) + return 0 + + +def save_file(file_name, data): + path = f'responses/{file_name}.txt' + dt = datetime.now().strftime("%d:%m:%Y %H:%M:%S") + with open(path, 'w') as file: + file.write(str(dt)+'\n') + for one_pos in data: + page = get_page(one_pos) + file.write(f'{one_pos}({page})\n') + + +def update_dict(date, item_ID, request, position): + if position is None: + position = 'NULL' + request = request.replace('+', ' ') + row_db = {'date': date, 'item_ID': item_ID, 'request': request, 'position': position} + #row_db.update({'date': date, 'item_ID': item_ID, 'request': request, 'position': position}) + return row_db + +def main(): + usr = Mode() + usr.select_mode() + db = PositionsDB().create_db() + + while usr.mode != 0: + if usr.mode == 1: + mode_1(usr, db) + elif usr.mode == 2: + mode_2(usr, db) + elif usr.mode == 3: + mode_3(usr, db) + elif usr.mode == 4: + mode_4(usr, db) + usr.select_mode() + + db.commit() + db.disconnect() + + +main() diff --git a/src/wb_parser.py b/src/wb_parser.py index 23cb6d5..8f1cb57 100644 --- a/src/wb_parser.py +++ b/src/wb_parser.py @@ -1,13 +1,7 @@ from constants import * import requests - - -class WBParser: - - def __init__(self, item_id, requests_list, last_page): - self.item_id = item_id - self.requests_list = requests_list - self.last_page = last_page +from get_external import InfoImport +import time class Request: @@ -21,13 +15,91 @@ def __init__(self, item_id, request_text, page): def get_request(self): self.request = f'https://search.wb.ru/exactmatch/ru/female/v4/search?appType=1&couponsGeo=2,12,3,18,15,21' \ f'&curr=rub&dest=123585734&emp=0&lang=ru&locale=ru&pricemarginCoeff=2.0&' \ - f'query={self.request_text}&page={self.page}&limit=300&' \ + f'query={self.request_text}&page={self.page}&limit={MAX_LIMIT}&' \ f'reg=1®ions=80,64,38,4,115,83,33,68,70,69,30,86,75,40,1,66,31,48,110,22,71' \ f'&resultset=catalog&sort=popular&spp=50&sppFixGeo=4&suppressSpellcheck=false' return self def get_data(self): response = requests.get(self.request, headers=HEADER) - data = response.json() - # data_list = get_data_from_json_request(data) - return data + if response.status_code == 200: + data = response.json() + if len(data) == 5: + return data + return None + + +class WBParser: + + def __init__(self, item_id, data): + self.item_id = item_id + self.data = data + + def get_position(self): + position = 0 + for data in self.data['data']['products']: + position += 1 + if data['id'] == self.item_id: + return position + return -1 + + +class Mode(InfoImport): + + def __init__(self): + super().__init__() + self.request = None + self.position = None + self.page = None + + def mode_1(self): + print('It\'s mode_1') + self.item_id = self.get_item_id() + if self.item_id == 0: + return 0 + self.request = self.get_user_request() + if self.request == 0: + return 0 + self.position = self.get_all_requests_positions() + self.page = self.get_page() + print(f'item_id = {self.item_id}, request = {self.request}, position = {self.position}, page = {self.page}\n') + + def get_one_request_position(self, request_text): + for current_page in range(1, MAX_PAGE): + request = Request(self.item_id, request_text, current_page).get_request() + response = request.get_data() + if response is not None: + position = WBParser(self.item_id, response).get_position() + print(position) + if position != -1: + return position + (current_page - 1) * MAX_LIMIT + return None + + def get_all_requests_positions(self): + if isinstance(self.request, list): + positions_list = [] + counter = 0 + req_len = len(self.request) + for request_text in self.request: + counter += 1 + if counter % 10 == 0: + self.wait() + positions_list.append(self.get_one_request_position(request_text)) + print(f'{counter}/{req_len}') + return positions_list + else: + self.position = self.get_one_request_position(self.request) + return self.position + + @staticmethod + def wait(): + print('Ждем 20 сек, т.к. превышено количество запросов') + for i in range(20): + print(f'Ждем {i}сек') + time.sleep(1) + + def get_page(self): + try: + return int(self.position / 100) + 1 + except TypeError: + return None diff --git a/test.docx b/test.docx deleted file mode 100644 index 0014e54..0000000 Binary files a/test.docx and /dev/null differ diff --git a/user_requests/142400300.txt b/user_requests/142400300.txt new file mode 100644 index 0000000..4799466 --- /dev/null +++ b/user_requests/142400300.txt @@ -0,0 +1,53 @@ +Сумка +Сумка женская +Сумка женская черная +Сумка черная +Сумка женская маленькая черная +Сумка женская маленькая +Сумка маленькая +Сумка женская через плечо +Сумка через плечо +Сумка через плечо черная +Сумка женская через плечо черная +Сумка через плечо маленькая +Сумка женская через плечо маленькая +Сумка кросс боди +Сумка кросс-боди +Сумка кросс-боди женская +Сумка кросс-боди черная +Сумка кросс-боди маленькая +Сумка кросс-боди женская маленькая +Сумка женская на плечо кросс-боди +Сумка женская через плечо кросс-боди маленькая +сумка на плечо женская +сумка на плечо +Сумка на плечо черная +Сумка на плечо маленькая +Сумка женская на плечо маленькая +Сумка для подростков +Сумка женская для подростков +Сумка для подростков маленькая +Сумка для подростков черная +Сумка женская полукруглаяя +Сумка на широком ремешке +Сумка женская с широким ремешком +сумка клатч +сумка клатч черная +сумка клатч средняя +Сумка женская кросс-боди через плечо +Сумка женская экокожа +Сумка модная +Сумка женская классическая +Сумка женская деловая +Сумка полумесяц +Сумка миниатюрная +Мини сумка +Сумка полукруглая +Сумка через плечо с широким ремешком +Сумка женская через плечо с широким ремешком +Сумка на одно плечо +Сумка женская на одно плечо +Сумка мессенджер +мини сумка через плечо +сумка луна +сумка женская луна \ No newline at end of file diff --git a/user_requests/142400304.txt b/user_requests/142400304.txt new file mode 100644 index 0000000..6f0bcd7 --- /dev/null +++ b/user_requests/142400304.txt @@ -0,0 +1,54 @@ +Сумка +Сумка женская +Сумка женская коричневая +Сумка черная +Сумка женская маленькая коричневая +Сумка женская маленькая +Сумка маленькая +Сумка женская через плечо +Сумка через плечо +Сумка через плечо коричневая +Сумка женская через плечо коричневая +Сумка через плечо маленькая +Сумка женская через плечо маленькая +Сумка кросс боди +Сумка кросс-боди +Сумка кросс-боди женская +Сумка кросс-боди коричневая +Сумка кросс-боди маленькая +Сумка кросс-боди женская маленькая +Сумка женская на плечо кросс-боди +Сумка женская через плечо кросс-боди маленькая +сумка на плечо женская +сумка на плечо +Сумка на плечо коричневая +Сумка на плечо маленькая +Сумка женская на плечо маленькая +Сумка для подростков +Сумка женская для подростков +Сумка для подростков маленькая +Сумка для подростков коричневая +Сумка женская полукруглаяя +Сумка на широком ремешке +Сумка женская с широким ремешком +сумка коричневая +сумка клатч коричневая +сумка клатч средняя +Сумка женская кросс-боди через плечо +Сумка женская экокожа +Сумка модная +Сумка женская классическая +Сумка женская деловая +Сумка полумесяц +Сумка миниатюрная +Мини сумка +Сумка полукруглая +Сумка через плечо с широким ремешком +Сумка женская через плечо с широким ремешком +Сумка на одно плечо +Сумка женская на одно плечо +Сумка мессенджер +мини сумка через плечо +сумка луна +сумка женская луна + diff --git a/user_requests/145934856.txt b/user_requests/145934856.txt new file mode 100644 index 0000000..ab610c6 --- /dev/null +++ b/user_requests/145934856.txt @@ -0,0 +1,58 @@ +Сумка +Сумка женская +Сумка женская черная +Сумка черная +Сумка черная большая +Сумка женская большая черная +Сумка женская большая +Сумка большая +Сумка женская через плечо +Сумка через плечо +Сумка через плечо черная +Сумка женская через плечо черная +Сумка через плечо большая +Сумка женская через плечо большая +Сумка кросс боди +Сумка кросс-боди +Сумка кросс-боди женская +Сумка кросс-боди черная +Сумка кросс-боди большая +Сумка кросс-боди женская большая +Сумка женская на плечо кросс-боди +Сумка женская через плечо кросс-боди большая +Сумка на плечо женская +Сумка на плечо +Сумка на плечо черная +Сумка на плечо большая +Сумка женская на плечо большая +Сумка женская полукруглаяя +Сумка на широком ремешке +Сумка женская с широким ремешком +Сумка женская кросс-боди через плечо +Сумка женская экокожа +Сумка модная +Сумка женская классическая +Сумка женская деловая +Сумка полумесяц +Сумка полумесяц женская +Сумка полукруглая +Сумка через плечо с широким ремешком +Сумка женская через плечо с широким ремешком +Сумка на одно плечо +Сумка женская на одно плечо +Сумка мессенджер +сумка луна +сумка женская луна +Сумка женская средняя черная +Сумка женская средняя +Сумка средняя +Сумка через плечо средняя +Сумка женская через плечо средняя +Сумка кросс-боди средняя +Сумка кросс-боди женская средняя +Сумка женская через плечо кросс-боди средняя +Сумка на плечо средняя +Сумка женская на плечо средняя +Сумка средних размеров +Сумка хобо +Сумка хобо женская diff --git a/user_requests/146711905.txt b/user_requests/146711905.txt new file mode 100644 index 0000000..df1cffb --- /dev/null +++ b/user_requests/146711905.txt @@ -0,0 +1 @@ +сумка женская через плечо \ No newline at end of file diff --git a/user_requests/common.txt b/user_requests/common.txt new file mode 100644 index 0000000..925e688 --- /dev/null +++ b/user_requests/common.txt @@ -0,0 +1,3 @@ +Сумка +Сумка женская +Сумка женская черная diff --git a/user_requests/items.txt b/user_requests/items.txt new file mode 100644 index 0000000..5091fdf --- /dev/null +++ b/user_requests/items.txt @@ -0,0 +1,3 @@ +MINKL Items: +142400300 +145934856 \ No newline at end of file