Порядок надёжности примерно такой, сверху самое живучее.
Первое, размеченные данные внутри страницы. Загляните в исходник, поищите блок 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 меняются при каждой сборке фронта, цепляться за них бесполезно.