Автоматически скрываем лишние истории в VK: простой браузерный скрипт
- воскресенье, 23 ноября 2025 г. в 00:00:03
Со временем во VK у меня набралось несколько тысяч друзей. Отчасти это осознанная стратегия: расширение сети контактов помогает продвигать свои проекты, находить коллаборации и тестировать идеи на более широкой аудитории.
Но есть обратная сторона. Лента историй превращается в хаотичную карусель:
люди, с которыми вы давно не общаетесь;
рабочие контакты;
случайные добавления «на всякий случай»;
тестовые или заброшенные аккаунты.
При этом истории для меня — про личный контекст: что происходит у близких друзей, семьи, небольшой группы людей, с которыми действительно хочется оставаться на связи. Удалять всех подряд из друзей не вариант, сеть всё ещё полезна. Хотелось другого решения:
Оставить большую сеть контактов для работы и при этом видеть истории только от небольшого круга людей.
В итоге я написал небольшой скрипт, который автоматизирует ту рутину, на которую руками я бы никогда не потратил столько времени.
Исходники и инструкция:
https://github.com/AleksPetrakov/vk-hide-stories-script/
Задача звучит просто:
скрывать истории почти от всех;
не трогать истории ограниченного набора людей:
по имени (как оно отображается в шапке истории);
по ID (из ссылки вида /id123456 или /nickname).
Это типичная работа для автоматизации:
Открыт просмотрщик историй VK, текущая история по центру.
Скрипт смотрит, кто автор текущей истории.
Если автор в списке исключений — историю пропускаем, переходим к следующей.
Если автора нет в списке — открываем меню истории и нажимаем «Скрыть из историй» с подтверждением.
Скрипт запускается один раз и дальше сам крутит цикл заданное количество итераций. После старта он продолжает работать даже в неактивной вкладке: можно переключиться в другие вкладки или приложения, а через какое-то время вернуться к VK уже с очищенной лентой историй.
Скрипт живёт в файле vk-stories-auto-hider.js. Это не расширение браузера, никаких установок не требуется. Достаточно один раз вставить код в консоль и настроить списки исключений.
На верхнем уровне внутри файла есть две ключевые части:
Настройки исключений.
Функция запуска цикла.
В начале файла находятся два массива:
// Список имён друзей, чьи истории НЕ нужно скрывать.
// Формат: 'Имя Фамилия', регистр не важен.
const EXCLUDED_NAMES = [
// 'Имя Фамилия',
];
// Список id друзей (из href="/idилиник"), чьи истории НЕ нужно скрывать.
const EXCLUDED_IDS = [
// 'id123456',
];Идея простая:
EXCLUDED_NAMES — удобно для близких людей, где имя очевидно и редко меняется.
EXCLUDED_IDS — для точного контроля, когда важен именно ID профиля, а имя может меняться.
Строки сравниваются без учёта регистра, перед этим нормализуются и обрезаются пробелы.
Основная функция выглядит примерно так:
async function hideVkStoriesWithExclusions(cyclesCount = 200) {
// ...
}Вызов:
hideVkStoriesWithExclusions(200);означает «попробовать обработать до 200 историй подряд», где под «обработать» понимается либо скрыть историю, либо пропустить её, если автор в списке исключений.
Ниже — упрощённый разбор логики. Полная версия со всеми проверками и логами есть в репозитории на GitHub.
VK помечает текущий элемент истории классами вроде:
.stories_item.multi_stories.activeили, как запасной вариант:
.stories_item.activeСкрипт ищет активный элемент:
function getActiveStoryElement() {
return (
document.querySelector('.stories_item.multi_stories.active') ||
document.querySelector('.stories_item.active')
);
}Дальше нужно понять, кто автор текущей истории. Для этого в шапке истории берётся:
имя — из элемента с классами StoryInfo__title StoryInfo__title--author;
ID — из href:
либо этой же ссылки с именем;
либо ссылки на аватарку автора (a.stories_author_avatar[href]).
Примерно так:
function getAuthorInfoFromActiveStory(activeStoryEl) {
if (!activeStoryEl) return { name: null, id: null };
const nameLink =
activeStoryEl.querySelector('.StoryInfo__title.StoryInfo__title--author') ||
activeStoryEl.querySelector('.StoryInfo__title--author');
const rawName = nameLink ? nameLink.textContent || '' : '';
const name = rawName.trim();
let rawHref = null;
if (nameLink && nameLink.getAttribute('href')) {
rawHref = nameLink.getAttribute('href');
} else {
const avatarLink = activeStoryEl.querySelector(
'a.stories_author_avatar[href]'
);
if (avatarLink) rawHref = avatarLink.getAttribute('href');
}
let id = null;
if (rawHref) {
const href = rawHref.trim();
if (href.startsWith('/')) {
const withoutSlash = href.slice(1);
const withoutQuery = withoutSlash.split('?')[0].split('#')[0];
const firstPart = withoutQuery.split('/')[0];
id = firstPart || null;
}
}
return { name, id };
}
Полученные name и id дальше нормализуются и сравниваются с массивами EXCLUDED_NAMES и EXCLUDED_IDS.
Проверка вынесена в отдельную функцию:
function normalizeString(str) {
return (str || '').normalize('NFC').trim().toLowerCase();
}
function isAuthorExcluded(authorInfo) {
const { name, id } = authorInfo;
const normalizedName = normalizeString(name);
const normalizedId = normalizeString(id);
const excludedNamesNormalized = EXCLUDED_NAMES.map(normalizeString);
const excludedIdsNormalized = EXCLUDED_IDS.map(normalizeString);
const byName =
!!normalizedName &&
excludedNamesNormalized.includes(normalizedName);
const byId =
!!normalizedId &&
excludedIdsNormalized.includes(normalizedId);
return byName || byId;
}Если автор в исключениях, история не скрывается. Вместо этого нужно аккуратно перейти к следующей истории.
Здесь важный момент: я специально не привязывался к конкретным кнопкам внутри интерфейса VK (например, к стрелкам). Вместо этого скрипт имитирует «человеческий» клик по области экрана чуть правее текущей истории.
Алгоритм:
Находим контейнер текущей истории .stories_item_cont.
Берём его размер через getBoundingClientRect().
Рассчитываем координату клика:
x — правая граница истории + 100 пикселей (но не дальше правого края окна);
y — вертикальный центр (window.innerHeight / 2).
Находим элемент под этой точкой через document.elementFromPoint(x, y).
Отправляем по этому элементу события mousedown, mouseup, click.
Код:
function goToNextStoryByScreenClick(activeStoryEl) {
if (!activeStoryEl) return false;
const cont = activeStoryEl.querySelector('.stories_item_cont');
if (!cont) return false;
const rect = cont.getBoundingClientRect();
let x = rect.right + 100;
const maxX = window.innerWidth - 10;
if (x > maxX) x = maxX;
if (x < 0) x = 0;
let y = window.innerHeight / 2;
if (y < 0) y = 0;
const maxY = window.innerHeight - 10;
if (y > maxY) y = maxY;
const target = document.elementFromPoint(x, y) || document.body;
const eventInit = {
bubbles: true,
cancelable: true,
view: window,
clientX: x,
clientY: y,
};
['mousedown', 'mouseup', 'click'].forEach((type) => {
const ev = new MouseEvent(type, eventInit);
target.dispatchEvent(ev);
});
return true;
}Такой подход менее хрупкий по отношению к внутренней разметке: даже если VK немного поменяет классы у кнопок, сам факт «клик справа от истории» с высокой вероятностью останется рабочим.
Если автор не в списке исключений, скрипт проделывает за пользователя три клика:
Открывает меню истории (иконка с тремя точками в шапке).
Нажимает пункт «Скрыть из историй».
Подтверждает действие в модальном окне.
Опорные элементы:
кнопка меню — по data-testid="story_header_menu_button";
пункт меню — по data-testid="story_header_menu_action_add_blacklist";
кнопка подтверждения — button.FlatButton.FlatButton--primary.FlatButton--size-m с текстом Скрыть из историй.
На практике это выглядит как последовательность mousedown → mouseup → click по каждому из элементов с небольшими задержками между шагами.
Один из приятных побочных эффектов: скрипт прекрасно живёт в фоне.
После запуска, например:
hideVkStoriesWithExclusions(200);можно:
оставить вкладку VK открытой;
переключиться на другую вкладку или вообще в другое приложение;
через какое-то время вернуться и увидеть, что часть историй уже скрыта.
Браузеры по-разному оптимизируют работу вкладок в фоне, но для такого типа задач этого достаточно: даже если таймеры чуть замедлятся, скрипт всё равно отработает до конца, пока вкладка не будет полностью выгружена или страница не перезагружена.
Краткая инструкция:
Открыть VK в браузере.
Открыть любую историю так, чтобы просмотрщик историй был активен и история была по центру.
Открыть консоль разработчика:
Chrome:
Windows / Linux: Ctrl + Shift + I → вкладка Console;
macOS: Cmd + Option + I → вкладка Console.
Открыть файл vk-stories-auto-hider.js из репозитория:
https://github.com/AleksPetrakov/vk-hide-stories-script/
Скопировать весь код и вставить его в консоль, нажать Enter.
При необходимости отредактировать массивы EXCLUDED_NAMES и EXCLUDED_IDS в начале файла.
Запустить:
hideVkStoriesWithExclusions(200);Оставить вкладку VK открытой и заняться своими делами. Спустя какое-то время часть историй исчезнет из ленты, а истории людей из списков исключений останутся и будут продолжать показываться.
Логичный вопрос: почему это скрипт в консоли, а не полноценное расширение с UI.
На текущем этапе плюсы такого формата для меня перевешивают:
минимальный порог входа — никакой установки, один файл;
легко прочитать и проверить, что именно делает код;
удобнее экспериментировать с селекторами и таймингами;
нет лишних разрешений и фона, который живёт в браузере постоянно.
Если эта утилита приживётся и будет полезна не только мне, вариант с расширением никуда не исчезает. Там уже можно думать про UI для управления списками, сохранение настроек, статистику и так далее.
Этот скрипт решает одну конкретную задачу: очистить ленту историй, не ломая при этом большую сеть контактов.
Очевидные следующие шаги:
сделать инструменты для более системного расширения сети контактов во VK (но без спама и агрессивной автоматизации);
попробовать перенести похожие идеи на другие социальные сети, где есть схожая проблема «шума»;
собрать небольшой набор утилит вокруг темы «гигиена социальной графа»: где-то чистим, где-то аккуратно растим.
Исходники, актуальная версия скрипта и документация — в репозитории:
https://github.com/AleksPetrakov/vk-hide-stories-script/