Тут работают два разных механизма, поэтому и лечится в два приёма.
Первый. Когда сервер отдаёт text/* без указания кодировки, requests по старому соглашению подставляет ISO-8859-1. Байты при этом целые, а буквы получаются латинские с крышечками, это ваш первый случай. apparent_encoding спрашивает определитель, тот считает частоты байтов и отвечает догадкой. На связном русском тексте догадка почти всегда верная, на короткой карточке из трёх слов и артикула определитель промахивается. Отсюда ваши тридцать штук.
Второй приём надёжнее. Берите тот порядок, по которому идёт браузер: отметка в начале файла, потом заголовок ответа, потом meta внутри самой страницы. Последнюю ступень requests пропускает, хотя именно там у половины старых движков и написана правда.
Проще всего отдать эту работу разборщику, он умеет читать meta сам:
from lxml import html as lh
doc = lh.document_fromstring(r.content) # именно content, байты
Обратите внимание на r.content. Как только вы взяли r.text, байты уже превращены в буквы по чужой догадке, и дальше спасать нечего.