def __init__(self, browser: webdriver): self._browser = browser self.products = [] self.errors = [] div_products = self._browser.find_elements_by_xpath(self.locators['divProducts']) for div_product in div_products: html = etree.parse(StringIO(div_product.get_property('outerHTML')), parser=etree.HTMLParser()) # Название товара name_element = BaseElement(self.locators['txbName'], context=div_product) # Цена за единицу продукта price_per_product = html.xpath(self.locators['txbPricePerProduct'])[0].text # Поле с количеством quantity_element = BaseElement(self.locators['inpQuantity'], context=div_product) # Итогова цена за товар price_amount = convert_price_from_str_to_float(html.xpath(self.locators['txbPriceAmount'])[0].text) try: # Итоговая цена без скидки price_amount_old = convert_price_from_str_to_float( html.xpath(self.locators['txbPriceAmountOld'])[0].text) except IndexError: price_amount_old = None # Элемент удаления товара из корзины delete_element = BaseElement(self.locators['btnDelete'], context=div_product) # Сообщение о количестве товара в магазине try: count_message = html.xpath(self.locators['txbProductCount'])[0].text except IndexError: count_message = None self.products.append({ 'name': name_element.text + self._get_params(html), # название товара 'price_per_product': convert_price_from_str_to_float(price_per_product), # цена за единицу продукта 'quantity': int(quantity_element.ge().get_property('value')), # количество товара 'price_amount': price_amount, # итогова цена за товар 'price_amount_old': price_amount_old, # итоговая цена без скидки 'count_message': count_message, # сообщение о количеством товара в магазине 'elements': { 'name': name_element, # элемент название товара 'quantity': quantity_element, # элемент количество товара 'delete': delete_element # элемент удаления товара из корзины } }) self._error_in_quantity(self.products[-1]['name'], quantity_element, count_message)
def _error_in_quantity(self, product_name: str, inp_quantity: BaseElement, count_message: str) -> None: """ Поле количество указанного товара """ error = 0 if "isError__" in inp_quantity.ge().get_attribute('class'): error += 1 if count_message: error += 1 if error == 2: self.errors.append(('product_quantity', product_name))
def open_item_by_names_in_left_menu(self, menu_item: str, sub_menu_item: str) -> None: """ Открыть раздел сайта по имени раздела и пункта в левом меню """ menu_item_parent_element = BaseElement( self.base_admin_shop_locators['txbMenu'].format(menu_item) + "/..") if 'is-open' not in menu_item_parent_element.ge().get_attribute( 'class'): # Если родительская категория не раскрыта, раскрываю BaseElement(self.base_admin_shop_locators['txbMenu'].format( menu_item)).click() # Открываю подменю BaseElement(self.base_admin_shop_locators['txbSubMenu'].format( sub_menu_item)).click()
def _parse_page(self) -> dict: """ Распарсить страницу товара """ elements = {} # Определение контекста, для парсинга информации на странице div_description = BaseElement(self.locators['locDescription']) div_description_html = etree.parse(StringIO( div_description.ge().get_property('outerHTML')), parser=etree.HTMLParser()) # Название товара name = div_description_html.xpath( self.locators['txtName'])[0].text.strip() # Артикул vendor_code = None temp = div_description_html.xpath(self.locators['txtVendorCode']) if temp[0].text is not None: temp = temp[0].text.strip() if temp: vendor_code = { 'text': re.sub(r"\s+", " ", temp), 'code': re.search(r":\s*(.*)$", temp).group(1).rstrip() } # Цена и цена от.. price = None price_from = None temp = div_description_html.xpath(self.locators['txtPrice']) if temp[0].text is not None: if "от" in temp[0].text or (temp[0].getparent().text is not None and "от" in temp[0].getparent().text): price_from = convert_price_from_str_to_float( temp[0].text.replace("\xa0", " ")) else: price = convert_price_from_str_to_float(temp[0].text) # Цена со скидкой price_discount = None temp = div_description_html.xpath(self.locators['txtPriceDiscount']) if len(temp): temp = temp[0].text if temp: price_discount = convert_price_from_str_to_float(temp) # Параметры params = None div_params = div_description_html.xpath(self.locators['locParams']) if len(div_params): params = [] for div_param in div_params: # id параметра param_id = int( div_param.xpath( self.locators['locParamId'])[0].attrib['name']) # выбранное значнеие selected = div_param.xpath( self.locators['txtParamSelected'])[0].text # Значения values = [] div_values = div_param.xpath(self.locators['locParamValues']) for div_value in div_values: # Проверяем отображение значения параметра try: disabled = True if div_value.attrib[ 'disabled'] else False except KeyError: disabled = False values.append({ 'id': int(div_value.attrib['data-value']), # id значения 'name': div_value.text, # имя значения 'disabled': disabled, # отображается ли он }) params.append({ 'id': param_id, # id параметра 'selected': selected, # выбранное значение 'values': values, # словарь значений }) # Поле с количеством quantity = None temp = div_description_html.xpath(self.locators['inpQuantity']) if len(temp): quantity = int(temp[0].attrib['value']) # количество elements['quantity_minus'] = BaseElement( self.locators['btnQuantityMinus']) elements['quantity'] = BaseElement(self.locators['inpQuantity']) elements['quantity_plus'] = BaseElement( self.locators['btnQuantityPlus']) # Кнопка button = None temp = div_description_html.xpath(self.locators['btnAdd'] + "/span") if len(temp): button_text = temp[0].text.strip() if "Заказать" in button_text: button_type = 'preOrder' else: button_type = 'addToCard' button = { 'text': button_text, # текст внутри 'type': button_type, # тип } # Элемент кнопка elements['button'] = BaseElement(self.locators['btnAdd']) else: temp = div_description_html.xpath(self.locators['btnPreOrder'] + "/span") if len(temp): button = { 'text': temp[0].text.strip(), # текст внутри 'type': 'preOrder', # тип } # Элемент кнопка elements['button'] = BaseElement(self.locators['btnPreOrder']) # Количестве товара count = None temp = div_description_html.xpath(self.locators['locCount']) if len(temp): text = temp[0].xpath("string()").strip() if text: text = re.sub(r"\s+", " ", text) count = { 'text': text, # текст сообщения 'number': int( div_description_html.xpath(self.locators['locCount'] + "/span")[0].text), } result = { 'name': name, # название товара 'vendor_code': vendor_code, # артикул 'price': price, # цена 'price_from': price_from, # цена от.. 'price_discount': price_discount, # цена со скидкой 'params': params, # словарь параметров 'quantity': quantity, # количество 'button': button, # словарь кнопки 'count': count, # словарь количества товара в наличии 'elements': elements # словарь элементов } return result
def _get_order(self) -> dict: order = {} div_order_data = BaseElement(self.locators['locOrderData']) html = etree.parse(StringIO( div_order_data.ge().get_property('outerHTML')), parser=etree.HTMLParser()) div_fields = html.xpath(self.locators['locOrderDataFields']) temp = div_fields[0].text order['number'] = re.search(r"(\d{6})", temp).group(0) temp = div_fields[1].text order['date'] = re.search(r"Дата:\s*(.*)$", temp).group(1) temp = div_fields[2].text order['type'] = re.search(r"Тип:\s*(.*)$", temp).group(1) order['status'] = div_fields[3].xpath( self.locators['btnOrderDataField'])[0].attrib['title'] order['delivery'] = div_fields[4].xpath( self.locators['btnOrderDataField'])[0].attrib['title'] order['payment'] = div_fields[5].xpath( self.locators['btnOrderDataField'])[0].attrib['title'] order['promocode'] = div_fields[-1].xpath( self.locators['btnOrderDataField'])[0].attrib['title'] if len(order['promocode']) != 3: order['promocode'] = re.search(r"^(.*)\s-\s.*$", order['promocode']).group(1) order['form'] = [] # for div_field in div_fields[6:-1]: # order['form'].append(div_field.xpath(self.locators['inpOrderDataFields'])[0].attrib['value']) order['products'] = [] order_table = BaseElement(self.locators['locOrderTable']) html = etree.parse(StringIO( order_table.ge().get_property('outerHTML')), parser=etree.HTMLParser()) tr_elements = html.xpath(".//tr")[:-5] for tr_element in tr_elements: vendor_code = tr_element.xpath( ".//span[@class='vendor-code']")[0].text order['products'].append({ 'name': tr_element.xpath(".//td[@class='sku']")[0].text + "|" + vendor_code, 'price_per_product': convert_price_from_str_to_float( tr_element.xpath(".//td[@class='sku-price']") [0].attrib['value']), 'quantity': int( tr_element.xpath(".//td[@class='sku-quantit']") [0].attrib['value']), 'price_amount': convert_price_from_str_to_float( tr_element.xpath(".//td[@class='total-cost']")[0].text), }) order['delivery_tax'] = convert_price_from_str_to_float( html.xpath(self.locators['inpDeliveryTax'])[0].attrib['value']) order['discount'] = convert_price_from_str_to_float( html.xpath(self.locators['inpDiscount'])[0].attrib['value']) order['markup'] = convert_price_from_str_to_float( html.xpath(self.locators['inpMarkup'])[0].attrib['value']) order['total_amount'] = convert_price_from_str_to_float( html.xpath(self.locators['txbTotalAmount'])[0].text) return order