Skip to content

Commit 5d78af8

Browse files
committed
Bug fix и рефактор Wildberries
1 parent a7dc776 commit 5d78af8

File tree

2 files changed

+24
-33
lines changed

2 files changed

+24
-33
lines changed

parsers/wildberries_parser.py

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import re
21
import time
32
import random
43
from tqdm import tqdm
@@ -51,18 +50,6 @@ def _get_goods_links(self, number_of_goods: Union[Literal['max'], int] = 10) ->
5150
self.page.goto(self.page.get_by_text(text=href_next_page).get_attribute(tag_href))
5251
self._get_goods_links(number_of_goods)
5352

54-
@staticmethod
55-
def __parse_seller_descr(descr: str) -> tuple:
56-
"""Парсинг доп информации о поставщике - уровень поставщика, сколько товаров продано, сколько времени на рынке
57-
version = 0.1
58-
"""
59-
descr = descr.replace("\n", " ")
60-
level = re.search(r".+(?= У)", descr)
61-
level = level.group(0) if level else None
62-
sold_goods = re.search(r"(?:(?<= )|(?<=^))[\d\s]+(?= Т)", descr).group(0)
63-
on_market = re.search(r"(?<=[он] ).+(?= Н)", descr).group(0)
64-
return level, sold_goods, on_market
65-
6653
def _get_good_descr(self, page_link: str) -> None:
6754
"""Сбор информации о товаре на его странице
6855
version = 0.2
@@ -80,8 +67,7 @@ def _get_good_descr(self, page_link: str) -> None:
8067
product.price = self.page.query_selector('ins[class="price-block__final-price wallet"]')
8168
product.old_price = self.page.query_selector('del[class="price-block__old-price"]')
8269
product.score = self.page.query_selector('div[class="product-page__common-info"]')
83-
product.reviews = self.page.query_selector('span[class="product-review__count-review '
84-
'j-wba-card-item-show j-wba-card-item-observe"]')
70+
product.reviews = self.page.query_selector('span[data-wba-location="reviews"]')
8571
product.category = self.page.query_selector('div[class="breadcrumbs__container"]')
8672
seller_goods_data_link = "href{:selectedNomenclature^brandAndSubjectUrl}{on $analitic.proceedAndSave 'IBC'}"
8773
product.seller_goods = self.page.query_selector(f'a[data-link="{seller_goods_data_link}"]')
@@ -91,9 +77,8 @@ def _get_good_descr(self, page_link: str) -> None:
9177
time.sleep(random.uniform(.3, .6))
9278
if self.page.is_visible(seler_info_div): # проверяем, что есть блок с описанием продавца
9379
self.page.hover(seler_info_div) # наведение мышкой на значок подробностей о продавце
94-
seller_status = self.page.locator('.seller-params__list').inner_text()
80+
product.parse_seller_descr(self.page.locator('.seller-params__list'))
9581
product.seller_score = self.page.query_selector('span[class="address-rate-mini"]')
96-
product.seller_lvl, product.sold_goods, product.on_market = self.__parse_seller_descr(seller_status)
9782
self.page.click('text="Все характеристики и описание"')
9883
self.page.wait_for_timeout(random.randint(150, 400)) # ждём, когда прогрузится открытый блок описания
9984
product.description = self.page.query_selector('p[class="option__text"]')

parsers_dataclasses/wildberries_dataclasses.py

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,26 @@
77
@dataclass
88
class WildberriesProduct:
99

10-
__version__ = "0.2"
10+
__version__ = "0.3"
1111
__base_link = "https://www.wildberries.ru"
1212

1313
page_link: str = field(init=True) # ссылка на страницу товара
1414
title: str = field(init=True) # название товара
1515
seller: str = field(init=False) # название продавца
16-
seller_score: Optional[float] = field(init=False, default=None) # средняя оценка продавцы
16+
seller_score: Optional[float] = field(init=False, default=None) # средняя оценка продавца
1717
brand: Optional[str] = field(init=False) # бренд товара
1818
article: int = field(init=False) # артикул товара
19-
price_wb_wallet: int = field(init=False) # цена товара с wb кошельком
20-
price: int = field(init=False) # цена товара со скидкой
21-
old_price: int = field(init=False) # старая цена товара
19+
price_wb_wallet: Optional[int] = field(init=False) # цена товара с wb кошельком
20+
price: Optional[int] = field(init=False) # цена товара со скидкой
21+
old_price: Optional[int] = field(init=False) # старая цена товара
2222
score: Optional[float] = field(init=False) # средняя оценка товара
2323
reviews: Optional[int] = field(init=False) # количество отзывов на товар
2424
category: Optional[str] = field(init=False) # категория товара
2525
seller_goods: Optional[str] = field(init=False) # ссылка на товары бренда
2626
same_category: str = field(init=False) # ссылка на товары той же категории
2727
refund: Optional[str] = field(init=False) # возможность возврата
2828
seller_lvl: Optional[str] = field(init=False, default=None) # уровень продавца
29-
sold_goods: Optional[str] = field(init=False, default=None) # сколько товаров было продано продавцом
29+
sold_goods: Optional[int] = field(init=False, default=None) # сколько товаров было продано продавцом
3030
on_market: Optional[str] = field(init=False, default=None) # сколько продавец на рынке
3131
description: str = field(init=False) # описание товара
3232

@@ -35,7 +35,7 @@ def dict(self):
3535
return {k: v for k, v in asdict(self).items()}
3636

3737
def __setattr__(self, key: str, value: Optional[Union[str, ElementHandle]]):
38-
"""version = 0.3"""
38+
"""version = 0.4"""
3939
if key in ("seller", "title", "refund", "description"):
4040
value = self.__inner_text(value)
4141
elif key in ("price_wb_wallet", "price", "old_price", "reviews"):
@@ -45,18 +45,14 @@ def __setattr__(self, key: str, value: Optional[Union[str, ElementHandle]]):
4545
elif key == "article":
4646
value = int(self.__inner_text(value))
4747
elif key == "brand":
48-
value = self.__inner_text(value.query_selector('a'))
49-
value = value if value != '' else None
48+
value = value if (value := self.__inner_text(value.query_selector('a'))) != '' else None
5049
elif key == "score":
51-
value = self.__inner_text(value)
52-
value = re.search(r'[\d\s\.]+(?=\n)', value) if value else None
53-
value = float(value.group(0)) if value else None
50+
value = re.search(r'[\d\s\.]+(?=\n)', value) if (value := self.__inner_text(value)) else None
51+
value = float(value[0]) if value else None
5452
elif key == "seller_score":
5553
value = float(self.__inner_text(value))
5654
elif key == "category":
5755
value = self.__inner_text(value).replace('\n', '/')
58-
elif key == "sold_goods":
59-
value = self.__format_number(value)
6056
super().__setattr__(key, value)
6157

6258
@staticmethod
@@ -77,6 +73,16 @@ def __href(value: Optional[ElementHandle]) -> Optional[str]:
7773
@staticmethod
7874
def __format_number(number: str) -> Optional[int]:
7975
"""Форматирование целочисленных атрибутов с присутствием нечисловых символов
80-
version = 0.2.1
76+
version = 0.3
77+
"""
78+
return int(number) if (number := re.sub(r'[^\d]', '', number) if number else None) else None
79+
80+
def parse_seller_descr(self, seller_data: Optional[ElementHandle]) -> None:
81+
"""Парсинг доп информации о поставщике - уровень поставщика, сколько товаров продано, сколько времени на рынке
82+
version = 0.1
8183
"""
82-
return int(re.sub(r'[^\d]', '', number)) if number else None
84+
if seller_data:
85+
level = re.search(r".+(?= У)", seller_data := seller_data.inner_text().replace("\n", " "))
86+
self.seller_lvl = level[0] if level else None
87+
self.sold_goods = int(re.sub(r'[^\d]', '', re.search(r"(?:(?<= )|(?<=^))[\d\s]+(?= Т)", seller_data)[0]))
88+
self.on_market = re.search(r"(?<=[он] ).+(?= Н)", seller_data)[0]

0 commit comments

Comments
 (0)