Верстакфорум практиков
рекламаiprazon: приватные серверные адреса IPv4 и SOCKS5, безлимитный трафик, бесплатный тест до 2 часов
ФорумСбор данных

Разметка на сайте поменялась, разбор посыпался

scrapy_boy
scrapy_boy
Участник
сообщений 530
с окт
15 июля, 14:42первое сообщение

Ночной прогон отработал, отчитался зелёным, страниц забрано столько же, ошибок ноль. Утром смотрю выгрузку: наличие пустое во всех сорока тысячах строк.

Полез руками, сайт переехал на новую вёрстку. Селектор был такой:

nalichie = doc.select_one("div.product-info__stock span.value")

Класса такого больше нет вообще. Обидно даже не то, что сломалось, обидно, что прогон об этом промолчал.

grepwalker
grepwalker
Знаток
сообщений 1330
с мая
22 декабря, 17:59#2

Молчал он потому, что вы его так написали. Пустое поле для скрипта штатная ситуация: товара нет в наличии, поле пустое, живём дальше.

Считайте долю заполнения по каждому полю и сравнивайте с прошлым прогоном. Упало с девяноста восьми процентов до нуля, значит у вас поломка. Распродажа так не выглядит.

dolya = sum(1 for t in tovary if t["nalichie"]) / len(tovary)
if dolya < 0.7:
    raise SystemExit(f"наличие заполнено на {dolya:.0%}, разбор сломан")
Света Панина
Света Панина
Новичок
сообщений 160
с мар, второй сезон
1 мая, 08:16#3

у нас классы вообще каждую неделю разные, там какие-то буквы с цифрами в конце

scrapy_boy
scrapy_boy
Участник
сообщений 530
с окт
8 октября, 11:33#4
Света Панина: классы каждую неделю разные

Вот и у меня теперь так. Классы вида product-info__stock ушли, вместо них какая-то каша из шести знаков. Цепляться за неё бессмысленно, следующая сборка сайта её поменяет.

За что вообще цепляться на таких сайтах?

Артём Пчёлкин
Артём Пчёлкин
Ветеран
сообщений 2310
с янв
15 марта, 14:50#5

Порядок надёжности примерно такой, сверху самое живучее.

Первое, размеченные данные внутри страницы. Загляните в исходник, поищите блок script с типом application/ld+json. Там лежит готовая карточка товара с ценой и наличием, и лежит она не для вас: её читают поисковики, поэтому магазин трогает её крайне неохотно и меняет вместе с вёрсткой примерно никогда.

import json
for s in doc.select('script[type="application/ld+json"]'):
    d = json.loads(s.text)
    if d.get("@type") == "Product":
        nalichie = d["offers"]["availability"]

Второе, встроенное состояние. Современный магазин почти всегда кладёт в страницу свой набор данных для отрисовки, ищите в исходнике имя товара поиском и смотрите, в каком виде оно встречается. Часто рядом обнаруживается вся карточка одним куском, включая поля, которых на витрине вообще не видно.

Третье, обращения самой страницы. Открываете вкладку с сетью, обновляете карточку, смотрите, откуда витрина берёт остатки. Нередко это отдельный запрос по идентификатору товара, и вам вообще перестаёт быть нужен разбор вёрстки.

Четвёртое, атрибуты вида data-testid или itemprop. Они привязаны к смыслу, а сборщик стилей их не переименовывает.

И только пятым пунктом классы. Причём короткие осмысленные классы живут годами, а вот генерированные вида css-1qx3z меняются при каждой сборке фронта, цепляться за них бесполезно.

ostrov
ostrov
Участник
сообщений 505
с окт
22 августа, 17:07#6

Про генерированные подпишусь. У меня разбор к такому сайту переписывался трижды, пока не дошло, что имена классов там вообще не часть сайта, они складываются на сборке из хеша куска стилей. Поменяли отступ в кнопке, поменялось имя класса у половины страницы.

Держу теперь набор из десяти карточек как канарейку. Перед основным прогоном разбираю их и сверяю с сохранёнными значениями. Расхождение означает, что сайт переехал, и прогон не стартует.

pingpong
pingpong
Новичок
сообщений 105
с июн, второй сезон
1 января, 08:24#7

канарейка это сильно, забираю

scrapy_boy
scrapy_boy
Участник
сообщений 530
с окт
8 июня, 11:41#8

Переписал за вечер. Наличие и цену беру из размеченного блока, вёрстку трогаю только для описания и картинок, которых в разметке нет.

Сверху повесил две проверки: канарейка на десяти карточках перед стартом и доля заполнения по каждому полю после разбора. Прогнал ночью, доля по наличию девяносто семь процентов, канарейка сошлась.

Отдельно проверил на старой сохранённой странице: разбор по размеченному блоку читает и её тоже. Выходит, эта часть у них не менялась даже при полной смене вёрстки.