Задача довольно обыденная, нужно собирать цены ~1000 наименований товаров из поисковой выдачи маркетплейса Onoz раз в день...
В кратце опишу работу скрипта: из файла products.txt берется наименование товара для поискового запроса, собираются ссылки из поисковой выдачи, каждая открывается и оттуда берутся нужные данные и так далее по циклу.
Площадка использует защиту cloudflare, антибот и антидудос получилось обойти с помощью selenium undetected_chromedriver. Но при парсинге где-то 10 - 15 позиций парсинг останавливается, браузер фризится и от сервера не приходят ответы. Через некоторое время приходит timeout exception.
При этом, если в этой зависшей копии chromedriver попробовать открыть какую-либо ссылку onoz, ничего не выходит - данные тупо не передаются с сервера, а например google открывается. Соответственно проблемы с интернетом сразу отбрасываются, трабл именно в ограничении сервера, видимо какими-то алгоритмами вычисляется работа скрипта.
Если тут же перезапустить скрипт, то он как ни в чем не бывало продолжает собирать эти несчастные 10-15 позиции и снова фризится. Подскажите, может кто сталкивался с такой проблемой как это можно решить? Может с помощью сторожевой функции, которая будет перезапускать скрипт в случае простоя?
import os
import time
import random
import undetected_chromedriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import TimeoutException
from settings import LIMIT
total_start_time = time.time()
driver = undetected_chromedriver.Chrome()
def ONOZ_scraping(ONOZROW):
with open('ONOZ_links.txt', encoding="utf-8") as file:
links = [line.strip() for line in file.readlines()]
start_time = time.time()
values = [[]]
column_index = ONOZCOLUMN
for link in links:
driver.get(link)
time.sleep(random.uniform(1, 1.5))
price_element = driver.find_element(By.CLASS_NAME, ONOZPRICE).find_element(By.TAG_NAME, 'span').text.replace(' ', '').strip('₽').replace(' ', '')
print(f"Цена {link} — {price_element} рублей.")
values[0].extend([link, price_element])
end_time = time.time()
elapsed_time = round(end_time - start_time, 1)
print(f"{elapsed_time} сек.")
def ONOZ_collect():
with open('products.txt', encoding="utf-8") as file:
links = [line.strip() for line in file.readlines()]
# Получаем номер строки, с которой нужно начать парсинг
ONOZROW = 1
if os.path.isfile('ONOZ_row.txt'):
with open('ONOZ_row.txt', 'r') as f:
ONOZROW = int(f.read().strip())
try:
for i, link in enumerate(links[ONOZROW-1:], start=ONOZROW):
driver.get(f'https://www.ONOZ.ru/search/?from_global=true&sorting=ONOZ_card_price&text={link}')
time.sleep(1.5)
main_element = driver.find_element(By.CLASS_NAME, ONOZCARD)
elements = main_element.find_elements(By.XPATH, "./div")
limit = LIMIT
# Проходим по каждому элементу, извлекаем из него ссылку и обрезаем ее
ONOZ_links = []
for o, element in enumerate(elements):
if o >= limit:
break
try:
ONOZ_link = element.find_element(By.TAG_NAME, "a").get_attribute("href").split("/")[:5]
ONOZ_link = "/".join(ONOZ_link)
ONOZ_links.append(ONOZ_link)
except NoSuchElementException:
print("Элемент не найден")
with open('ONOZ_links.txt', 'w', encoding="utf-8") as file:
for ONOZ_link in ONOZ_links:
if ONOZ_link.strip():
file.write(f"{ONOZ_link.strip()}\n")
print(f"#{i} Сбор ссылок на ONOZ по товару {link} завершен.")
ONOZ_scraping(i)
with open('ONOZ_row.txt', 'w') as f:
f.write(str(i))
except TimeoutException:
raise
driver.quit()
total_end_time = time.time()
total_elapsed_time = round((total_end_time - total_start_time) / 60, 1)
print(f" Парсинг завершен. Длительность парсинга: {total_elapsed_time} мин.")
ONOZ_collect()