Skip to content

Commit bf82da0

Browse files
committed
Изменил логику парсинга товаров (без сохранения ссылок на страницы)
1 parent c96c052 commit bf82da0

File tree

2 files changed

+62
-71
lines changed

2 files changed

+62
-71
lines changed

parsers/wildberries_parser.py

Lines changed: 43 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,55 @@
11
import re
22
import time
3-
from typing import Optional
3+
import random
4+
from tqdm import tqdm
5+
from typing import Optional, Union, Literal
46
from playwright.sync_api import sync_playwright
57
from playwright._impl._errors import TimeoutError
6-
from tqdm import tqdm
78
from helpers.parsers_helpers import open_scroller
9+
from getuseragent import UserAgent
810

911
from parsers_dataclasses import WildberriesProduct
1012

1113

1214
class Wildberries:
1315

14-
__version__ = "0.1.1"
16+
__version__ = "0.1.2"
1517

1618
def __init__(self):
17-
"""version = 0.1.1"""
19+
"""version = 0.2"""
1820
self.page = None
19-
self.pages_links: list[str | Optional[int]] = []
20-
self.goods_links: list[str] = []
21+
self.goods_links: set[str] = set()
2122
self.parsing_result: list[dict] = []
22-
self.base_link = "https://www.wildberries.ru/"
23+
self.base_link = "https://www.wildberries.ru"
2324
self.scroller = open_scroller()
24-
self.PAGE_SCROLL_SIZE = 15
25-
26-
def _get_goods_links(self, page_link: str) -> list[str]:
27-
"""Нахождение всех ссылок на товары на всей странице
28-
version = 0.1
29-
"""
30-
self.page.goto(page_link)
31-
self.page.wait_for_selector(".catalog-page")
32-
for _ in range(self.PAGE_SCROLL_SIZE): # прокрутка до конца страницы
33-
self.page.evaluate(self.scroller)
34-
time.sleep(1) # остановка для полной загрузки страницы
35-
elements = self.page.query_selector_all('div.product-card-list a[draggable="false"]')
36-
elements = list(map(lambda el: el.get_attribute('href'), elements))
37-
return elements
3825

39-
def _get_next_page_link(self, page_link: str) -> None:
40-
"""Получение ссылки на следующую страницу с текущей
41-
version = 0.1
42-
"""
43-
self.page.goto(page_link)
44-
self.page.wait_for_selector(".catalog-page")
45-
for _ in range(self.PAGE_SCROLL_SIZE): # прокрутка до конца страницы
46-
self.page.evaluate(self.scroller)
47-
try:
48-
self.page.wait_for_selector('text="Следующая страница"', timeout=3_000)
49-
element = self.page.get_by_text(text="Следующая страница")
50-
self.pages_links.append(element.get_attribute('href'))
51-
except TimeoutError: # если страницы для поиска закончились
52-
self.pages_links.append(0)
53-
54-
def _get_all_pages_links(self, number_of_pages):
55-
"""Добавление в список всех ссылок на страницы
56-
version = 0.1
26+
def _get_goods_links(self, number_of_goods: Union[Literal['max'], int] = 10) -> None:
27+
"""Сбор всех ссылок на товары. Либо собирается максимальное количество товаров, либо явно
28+
указанное количество (по умолчанию=10).
29+
version = 0.2
5730
"""
58-
self.pages_links.append(self.page.url) # ссылка на первую страницу каталога
59-
if number_of_pages > 1:
60-
for i in range(number_of_pages - 1):
61-
page_link = self.pages_links[i]
62-
if isinstance(page_link, str):
63-
self._get_next_page_link(page_link) # получение ссылки на следующую страницу
64-
else: # если страницы для поиска закончились (меньше заданного кол-ва)
65-
self.pages_links.pop() # удаление нуля в конце
31+
tag_href = 'href'
32+
href_next_page = "Следующая страница"
33+
selector_next_page = f':text("{href_next_page}")'
34+
self.page.wait_for_selector('.catalog-page')
35+
while not self.page.is_visible('.custom-slider__list'): # пока не видно блок с рекомендуемыми товарами
36+
self.page.evaluate(self.scroller) # прокрутка до конца страницы
37+
links = self.page.query_selector_all('div.product-card-list a[draggable="false"]')
38+
links = set(map(lambda link: link.get_attribute(tag_href), links))
39+
if number_of_goods == 'max':
40+
self.goods_links.update(links)
41+
if self.page.is_visible(selector_next_page):
42+
self.page.goto(self.page.get_by_text(text=href_next_page).get_attribute(tag_href))
43+
self._get_goods_links(number_of_goods)
44+
else:
45+
for link in links:
46+
if len(self.goods_links) < number_of_goods:
47+
self.goods_links.add(link)
48+
else:
6649
break
50+
if len(self.goods_links) < number_of_goods and self.page.is_visible(selector_next_page):
51+
self.page.goto(self.page.get_by_text(text=href_next_page).get_attribute(tag_href))
52+
self._get_goods_links(number_of_goods)
6753

6854
@staticmethod
6955
def __parse_seller_descr(descr: str) -> tuple:
@@ -115,25 +101,23 @@ def _get_good_descr(self, page_link: str) -> None:
115101
# создание итогового словаря по товару
116102
self.parsing_result.append(product.dict())
117103

118-
def find_all_goods(self, keyword: str, number_of_pages: int) -> None:
104+
def find_all_goods(self, keyword: str, number_of_goods: Union[Literal['max'], int] = 10) -> None:
119105
"""Поиск всех ссылок на товары по ключевому слову
120-
version = 0.1.1
106+
version = 0.1.2
121107
"""
122108
with sync_playwright() as playwright:
123-
browser = playwright.chromium.launch(headless=True)
124-
context = browser.new_context()
109+
browser = playwright.chromium.launch(headless=True, args=['--disable-blink-features=AutomationControlled'])
110+
context = browser.new_context(user_agent=UserAgent().Random())
125111
self.page = context.new_page()
126-
self.page.goto(self.base_link, timeout=1000, wait_until="load") # открытие ссылки сайта
127-
self.page.wait_for_selector('input[id="searchInput"]') # поиск поля input
128-
search_input = self.page.locator('input[id="searchInput"]') # помещение курсора в input
129-
search_input.fill(keyword, timeout=300)
130-
search_input.press('Enter') # запуск процесса поиска
112+
self.page.goto(self.base_link)
113+
time.sleep(1)
114+
input_field = self.page.get_by_placeholder("Найти на Wildberries").first
115+
input_field.type(keyword, delay=random.uniform(.1, .5))
116+
input_field.press(key='Enter', delay=random.randint(100, 500)) # запуск процесса поиска
131117
try: # проверка, что по запросу ничего не найдено
132118
self.page.wait_for_selector('text="Попробуйте поискать по-другому или сократить запрос"', timeout=1_000)
133119
except TimeoutError: # если по запросу найдены товары
134-
self._get_all_pages_links(number_of_pages) # получение ссылок на все страницы по поиску
135-
for link in self.pages_links:
136-
self.goods_links.extend(self._get_goods_links(link))
120+
self._get_goods_links(number_of_goods) # получение ссылок на все страницы по поиску
137121
finally:
138122
browser.close()
139123

test/test_wildberries.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,29 +23,36 @@ def __test_product(self, link):
2323
pp.pprint(self.wb.parsing_result[0])
2424
browser.close()
2525

26-
def test_one_page(self):
26+
def test_one_good(self):
2727
time.sleep(1)
2828
self.wb.find_all_goods(self.keyword, 1)
29-
self.assertEqual(1, len(self.wb.pages_links))
30-
self.assertNotEqual(0, len(self.wb.goods_links))
29+
self.assertEqual(1, len(self.wb.goods_links))
3130

32-
def test_ten_goods(self):
31+
def test_many_goods(self):
3332
time.sleep(1)
34-
self.wb.find_all_goods(self.keyword, 1)
35-
self.wb.goods_links = self.wb.goods_links[:10]
36-
self.assertIsNotNone(self.wb.describe_all_goods())
33+
self.wb.find_all_goods(self.keyword, 150)
34+
self.assertEqual(150, len(self.wb.goods_links))
3735

3836
def test_empty_page(self):
3937
time.sleep(1)
40-
self.wb.find_all_goods(self.error_keyword, 1)
41-
self.assertEqual(0, len(self.wb.pages_links))
38+
self.wb.find_all_goods(self.error_keyword)
39+
self.assertEqual(0, len(self.wb.goods_links))
40+
41+
def test_max_goods(self):
42+
time.sleep(1)
43+
self.wb.find_all_goods(self.keyword, 'max')
44+
self.assertNotEqual([], self.wb.goods_links)
4245

43-
def test_two_pages(self):
46+
def test_overmuch_goods(self):
4447
time.sleep(1)
45-
self.wb.find_all_goods(self.keyword, 2)
46-
self.assertEqual(2, len(self.wb.pages_links))
48+
self.wb.find_all_goods(self.keyword, 1500)
4749
self.assertNotEqual([], self.wb.goods_links)
4850

51+
def test_describe_all_goods(self):
52+
time.sleep(1)
53+
self.wb.find_all_goods(self.keyword)
54+
self.assertEqual(10, len(self.wb.describe_all_goods()))
55+
4956
def test_one_product(self):
5057
time.sleep(1)
5158
self.__test_product("https://www.wildberries.ru/catalog/228691002/detail.aspx")

0 commit comments

Comments
 (0)