Natalia Kurinna

+5
с 2020
2 подписчика
26 подписок

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

3

В данной статье не рассматриваются правовые и этические вопросы, связанные с парсингом. Она сосредоточена на технических аспектах предотвращения обнаружения. Ниже перечислены наиболее распространенные проблемы, с которыми вы можете столкнуться при парсинге. Конечно, каждый веб сайт имеет свои особенности, которые необходимо учитывать при создании п…

4
","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Установите тег на срабатывание триггера DOM Ready.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Измените строку, которая начинается с var selectMenu = ..., чтобы селектор соответствовал элементу, который вы хотите отслеживать непосредственно в вашем случае.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Если CSS селекторы вам незнакомы, вы можете прочитать о них здесь или использовать document.getElementById (), или другой метод DOM, который вам больше подходит. Независимо от используемого вами селектора, вам нужно задать именно элемент select в переменной selectMenu, чтобы это решение работало.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Вышеописанный тег создает пользовательский слушатель изменений 'change', который срабатывает при изменении значения отслеживаемого элемента. Этот метод также отлично применим к отслеживанию форм, так как вы можете использовать этот тип слушателя для трекинга полей форм, чтобы определить, изменил ли пользователь значение внутри.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Итак, когда наш слушатель обнаруживает событие 'change', обратный вызов помещает в dataLayer объект, который содержит кастомное событие selectionMade и ссылку на объект для опции, выбранной пользователем.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Чтобы ваш тег каждый раз срабатывал при выборе, вам понадобится пользовательское событие, который выглядит следующим образом:

"}},{"type":"media","cover":true,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"54d908f4-a8d6-3030-5547-1fb54432f2da","width":948,"height":398,"size":274918,"type":"png","color":"dee1e2","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Далее, в зависимости от того, как был настроен элемент option, вы можете использовать одну из следующих переменных уровня данных:

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"397ade90-aa98-2379-a011-d757425cdb3c","width":627,"height":636,"size":307235,"type":"png","color":"e7edf4","hash":"","external_service":[]}}}]}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"46c1ae7a-37aa-a52d-d0ca-3d33fe7af7d7","width":779,"height":460,"size":234445,"type":"png","color":"dadbdb","hash":"","external_service":[]}}}]}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"dadc3c22-36f7-3eda-a8c5-ef787d65f2a4","width":763,"height":469,"size":255534,"type":"png","color":"dfe2e2","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Вот и все! Когда пользователь делает выбор - первая захватывает значение атрибута value выбранной опции. Если же value нет, она захватывает текст. Вторая - захватывает текст, даже если опция имеет атрибут value.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Таким образом вы можете отслеживать клики по любым выпадающим меню или спискам.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Если же вы вам нужно отслеживать клики по какому-либо произвольному элементу и у вас это не получается с помощью стандартных триггеров - попробуйте этот способ.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Эту статью в оригинале и другие полезные статьи по digital аналитике вы можете найти на англоязычном блоге Симо Ахавы.

"}}],"summaryContent":null,"isExistSummaryContent":false,"warningFromEditor":null,"warningFromEditorTitle":null,"counters":{"comments":0,"favorites":1,"reposts":0,"views":10,"hits":340,"reads":null,"online":0},"dateFavorite":0,"hitsCount":340,"isCommentsEnabled":true,"isLikesEnabled":true,"isRemovedByUserRequest":false,"isFavorited":false,"isPinned":false,"repostId":null,"repostData":null,"subscribedToTreads":false,"isEditorial":false,"isAudioAvailable":false,"audioUrl":null,"isAudioAvailableToGenerate":false,"commentEditor":{"enabled":true,"who":null,"text":"","until":null,"reason":null,"type":"everybody"},"isBlur":false,"isPublished":true,"isDisabledAd":false,"withheld":[],"ogTitle":null,"ogDescription":null,"url":"https://vc.ru/id440788/143099-kak-otslezhivat-kliki-po-vypadayushim-menyu-spiskam","author":{"id":440788,"name":"Natalia Kurinna","nickname":null,"description":null,"uri":"","avatar":{"type":"image","data":{"uuid":"8f3384f1-3319-ca6a-6615-08b064b15e2e","width":690,"height":798,"size":1686201,"type":"png","color":"ab9893","hash":"0763cbcbcbd32d0b","external_service":[]}},"cover":null,"achievements":[{"title":"Год на vc.ru","code":"registration_1_year","description":"Первый год с vc.ru. Получена 24 июля 2025.","previewUuid":"0d11c244-49de-50e7-894e-b9b27945d42b","formats":{"glb":"https://static.vc.ru/achievements/fish.glb","usdz":"https://static.vc.ru/achievements/fish.usdz"},"viewData":{"contentColor":"#C67AA3","textMaxWidth":0.634765625,"textX":0.5888671875,"textY":0.54296875,"logoX":0.5859375,"logoY":0.6669921875,"logoXNoText":0.6044921875,"logoYNoText":0.5439453125},"id":4987394,"userId":440788,"count":0,"shareImage":"https://api.vc.ru/achievements/share/4987394"},{"title":"3 года на vc.ru","code":"registration_3_years","description":"Провёл 3 года вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"d9d72ac5-bcb5-55e0-8c72-b99251e5cdd9","formats":{"glb":"https://static.vc.ru/achievements/shark.glb","usdz":"https://static.vc.ru/achievements/shark.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.5205078125,"textY":0.341796875,"logoX":0.5205078125,"logoY":0.4609375,"logoXNoText":0.5,"logoYNoText":0.3662109375},"id":1363307,"userId":440788,"count":0,"shareImage":"https://api.vc.ru/achievements/share/1363307"},{"title":"5 лет на vc.ru","code":"registration_5_years","description":"Провёл 5 лет вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"a9140d54-73b8-5f40-afa8-449fbaafd42b","formats":{"glb":"https://static.vc.ru/achievements/whale.glb","usdz":"https://static.vc.ru/achievements/whale.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.533203125,"textY":0.658203125,"logoX":0.533203125,"logoY":0.77734375,"logoXNoText":0.4375,"logoYNoText":0.66015625},"id":136599,"userId":440788,"count":0,"shareImage":"https://api.vc.ru/achievements/share/136599"}],"lastModificationDate":1764981758,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":true,"badgeId":null,"isDonationsEnabled":false,"isPlusGiftEnabled":true,"isUnverifiedBlogForCompanyWithoutPro":false,"isRemovedByUserRequest":false,"isFrozen":false,"isDisabledAd":false,"isPlus":false,"isVerified":false,"isPro":false,"yandexMetricaId":null,"badge":null,"isOnline":false,"tgChannelShortname":null,"isUnsubscribable":true,"type":1,"subtype":"personal_blog"},"subsite":{"id":440788,"name":"Natalia Kurinna","nickname":null,"description":null,"uri":"","avatar":{"type":"image","data":{"uuid":"8f3384f1-3319-ca6a-6615-08b064b15e2e","width":690,"height":798,"size":1686201,"type":"png","color":"ab9893","hash":"0763cbcbcbd32d0b","external_service":[]}},"cover":null,"achievements":[{"title":"Год на vc.ru","code":"registration_1_year","description":"Первый год с vc.ru. Получена 24 июля 2025.","previewUuid":"0d11c244-49de-50e7-894e-b9b27945d42b","formats":{"glb":"https://static.vc.ru/achievements/fish.glb","usdz":"https://static.vc.ru/achievements/fish.usdz"},"viewData":{"contentColor":"#C67AA3","textMaxWidth":0.634765625,"textX":0.5888671875,"textY":0.54296875,"logoX":0.5859375,"logoY":0.6669921875,"logoXNoText":0.6044921875,"logoYNoText":0.5439453125},"id":4987394,"userId":440788,"count":0,"shareImage":"https://api.vc.ru/achievements/share/4987394"},{"title":"3 года на vc.ru","code":"registration_3_years","description":"Провёл 3 года вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"d9d72ac5-bcb5-55e0-8c72-b99251e5cdd9","formats":{"glb":"https://static.vc.ru/achievements/shark.glb","usdz":"https://static.vc.ru/achievements/shark.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.5205078125,"textY":0.341796875,"logoX":0.5205078125,"logoY":0.4609375,"logoXNoText":0.5,"logoYNoText":0.3662109375},"id":1363307,"userId":440788,"count":0,"shareImage":"https://api.vc.ru/achievements/share/1363307"},{"title":"5 лет на vc.ru","code":"registration_5_years","description":"Провёл 5 лет вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"a9140d54-73b8-5f40-afa8-449fbaafd42b","formats":{"glb":"https://static.vc.ru/achievements/whale.glb","usdz":"https://static.vc.ru/achievements/whale.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.533203125,"textY":0.658203125,"logoX":0.533203125,"logoY":0.77734375,"logoXNoText":0.4375,"logoYNoText":0.66015625},"id":136599,"userId":440788,"count":0,"shareImage":"https://api.vc.ru/achievements/share/136599"}],"lastModificationDate":1764981758,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":true,"badgeId":null,"isDonationsEnabled":false,"isPlusGiftEnabled":true,"isUnverifiedBlogForCompanyWithoutPro":false,"isRemovedByUserRequest":false,"isFrozen":false,"isDisabledAd":false,"isPlus":false,"isVerified":false,"isPro":false,"yandexMetricaId":null,"badge":null,"isOnline":false,"tgChannelShortname":null,"isUnsubscribable":true,"type":1,"subtype":"personal_blog"},"reactions":{"counters":[],"reactionId":0},"isNews":false,"source":null,"clusters":[],"donations":{"amount":0,"isDonated":false},"commentsSeenCount":null}},{"type":"entry","data":{"id":137909,"customUri":null,"subsiteId":440788,"title":"Девять CSS-селекторов на заметку начинающему веб аналитику","date":1593374731,"dateModified":1593374731,"blocks":[{"type":"text","cover":true,"hidden":false,"anchor":"","data":{"text":"

Свободный перевод. Ссылка на оригинальную статью Симо Ахава: #GTMTips: 10 Useful CSS Selectors.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Использование CSS-селекторов в Google Tag Manager — без сомнения, одна из его самых полезных опций. Это дает непревзойденную гибкость, особенно в сочетании с триггерами кликов и форм.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

CSS-селекторы позволяют проверять HTML-элемент на соответствие заданному вами селектору. Таким образом, когда вы используете триггер клика или формы, вы можете проверить соответствуют ли встроенные переменные клика или формы определенному селектору, и убедиться, что действие произошло именно с тем элементом, который вам нужен.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Вы можете использовать CSS-селекторы в любом JavaScript (или CSS), который развертываете у себя на сайте или в GTM, но, полагаю, наиболее типичным вариантом использования будет условие триггера «соответствует селектору CSS». Оно позволяет оценить элемент, по которому кликнули. Ниже более подробно об этом.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Итак, вы хотите отправлять событие по условию, что клик произошел по определенному HTML-элементу. Чтобы реализовать это, вам потребуется триггер клика или формы. В рамках данного триггера нужно выбрать опцию «Некоторые клики» и добавить свое условие.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Например, приведенный ниже триггер сопоставит элемент, который был нажат, с CSS-селектором и сработает только в том случае, если выбранный элемент является прямым потомком элемента с идентификатором myDiv.

"}},{"type":"media","cover":true,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"03fd8a96-3702-e9bf-0b4c-a4af832e3e31","width":1185,"height":454,"size":343444,"type":"png","color":"e1e2e2","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Помимо того, что CSS-селекторы используются для создания триггеров, сами по себе они тоже могут вам очень пригодиться. Разумеется, они нужны в таблицах стилей, но их также можно использовать с такими DOM-методами как querySelector() и querySelectorAll(), а также с matches() (для поддержки кросс-браузерности могут потребоваться некоторые дополнительные настройки).

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Ниже перечислены девять CSS-селекторов, с помощью которых вы сможете настроить отслеживание большинства распространенных видов событий для сайта.

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"1. Общие селекторы"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Следующие селекторы используются для точного определения элементов на основе их атрибутов или их позиции в DOM. Их можно комбинировать, размещая один за другим. Например, div[title=”someTitle”][data-gtm-event=”someEvent”] будет соответствовать любому элементу div, который имеет атрибуты title и data-gtm-event.

"}},{"type":"list","cover":false,"hidden":false,"anchor":"","data":{"items":[".someClass — соответствует элементу с классом “someClass”, например <div class=”someClass”>.","#someId — соответствует элементу с id “someId”, например <span id=”someId”>.","element — соответствует любому HTML-элементу с названием “element”. Например, “div” соответствует любому div элементу на странице, а “div#myId” будет соответствовать <div id=”myId”>.","element element — соответствует любому HTML-элементу, который является потомком предыдущего.Чтобы соответствие сработало, между элементами не обязательно должно соблюдаться отношение родитель-потомок — первый элемент просто должен предшествовать второму в том же дереве. Например, “span.myClass div#myId” соответствует любому div#myId, который является потомком span.myClass. Вы можете добавить столько ссылок в цепочку, сколько захотите. Наприме, “div#main ol li”, будет соответствовать любому li, который является потомком ol, который является потомком div#main.","element > element — соответствует любому HTML-элементу, который является прямым потомком предыдущего элемента. Например, “div#myId > a#contactUs” соответствует <a id=”contactUs”>, который является прямым потомком <div id=”myId”>.","selector, selector — два селектора, разделенные запятой работают в триггерах по логике или-или. Таким образом, вы можете указать несколько селекторов, и если один из них совпадает, триггер сработает."],"type":"UL"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Эти универсальные селекторы являются основой практически всего, что вы делаете с CSS-селекторами.

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"2. a[href^=”tel:”]"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Этот селектор соответствует любой ссылке (<a>), у которой атрибут href начинается с “tel:”, например: <a href=”tel:01010101\">. С помощью этого селектора вы можете трекать клики по номеру телефона.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Вот так вы можете адаптировать его для трекинга кликов по имейлам: a[href^=”mailto:”]

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"3. a[href*=”example.com”]"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Этот селектор соответствует любой ссылке, у которой атрибут href содержит “example.com”. Таким образом, можно использовать его, чтобы отсеять (или включить) клики по внутренним ссылкам на сайте.

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"4. a[href$=”.pdf”]"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Этот селектор соответствует любой ссылке, у которой атрибут href заканчивается на «.pdf». Вы можете просто заменить «.pdf» на любой тип файла, который хотите отслеживать.

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"5. div.someElement a"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Общие селекторы уже рассмотрены выше, но есть очень важный момент, который хотелось бы отметить.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Когда вы работаете с триггером «Клик/Все элементы», рекомендую добавить проверку соответствия для каждого элемента, который вы хотите отслеживать:

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Click Element соответствует CSS-селектору

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

a[href*=”example.com”], a[href*=”example.com”] *

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Другими словами, после вашего селектора добавьте еще один, который соответствует любому его потомку. Иногда это необходимо, поскольку триггер Все элементы фиксирует непосредственно только тот элемент, по которому кликнули. Но в виду вложенности структуры DOM, вы можете столкнуться с неожиданной штукой. Например, если у вас есть такая ссылка:

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"\n\nsome@email.com\n\n","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Клик по ссылке фактически придется на <span/>, и обычный триггер клика по ссылке в данном случае не будет работать. Используя селектор a[href=”mailto:some@email.com”], a[href=”mailto:some@email.com”] *, вы захватываете как клики на ссылку, так и на любых ее потомков (включая <span/>).

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"6. form#myForm option: checked"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Часто в формах присутствуют чекбоксы, радиокнопки, списки выбора. Вы можете использовать псевдо-селектор :checked, чтобы трекать такие элементы. Например, form#myForm option:checked ищет любой элемент <option>, выбранный в форме. Таким образом вы можете использовать этот селектор для идентификации выбранной опции в раскрывающихся списках и других элементах, где присутствует этот псевдо-класс.

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"7. a:not()"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Псевдо-селектор :not срабатывает если условие, что элемент не содержит заданное значение, возвращает true. Например, селектор вроде a:not([href*=”example.com”]) будет трекать клики по любым ссылкам, которые не содержат “example.com” в href.

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"8. ol > li:first-child"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Селектор: first-child соответствует первому дочернему элементу по отношении к заданному. Например, ol > li:first-child будет соответствовать первому элементу из списка

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Другие похожие селекторы — :last-child (соответствует последнему дочернему элементу) и :nth-child(N) (соответствует Н-ному дочернему элементу, например :nth-child(3) будет соответствовать третьему дочернему элементу относительно родительского элемента).

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"9. a[data-gtm-event]"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Квадратные скобки обозначают атрибуты. Если вы пропустите знак равенства (=), то можете просто проверить, имеет ли элемент данный атрибут. Например, селектор a[data-gtm-event] будет соответствовать любой ссылке с атрибутом data-gtm-event, независимо от значения этого атрибута.

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"10. body > div.site-container > div > div > main… ARGH"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Десятый пункт — совет, а не селектор. Старайтесь избегать длинных и сложных цепочек селекторов. Чем длиннее цепочка, чем больше вы используете отсылок на прямые отношения родителей и потомков(>) — тем больше точек отказа вы добавляете в ваш селектор.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Все, что нужно, чтобы ваш селектор перестал работать — изменение всего лишь одного элемента в длинном пути DOM, который указывает на ваш элемент. Особенно если об этом не вкурсе ваши старательные фронтенд разработчики.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Старайтесь всегда находить наиболее общий селектор, но который все еще достаточно точно соответствует тому, который вы пытаетесь захватить.

"}},{"type":"delimiter","cover":false,"hidden":false,"anchor":"","data":{"type":"default"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Надеюсь кому-нибудь это пригодилось)

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Если у вас есть полезные кейсы и селекторы, которые вас выручали, и которыми вы хотели бы поделиться — буду рада расширить ими этот список.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

#css #html

"}}],"summaryContent":null,"isExistSummaryContent":false,"warningFromEditor":null,"warningFromEditorTitle":null,"counters":{"comments":1,"favorites":15,"reposts":0,"views":10,"hits":3533,"reads":null,"online":0},"dateFavorite":0,"hitsCount":3533,"isCommentsEnabled":true,"isLikesEnabled":true,"isRemovedByUserRequest":false,"isFavorited":false,"isPinned":false,"repostId":null,"repostData":null,"subscribedToTreads":false,"isEditorial":false,"isAudioAvailable":false,"audioUrl":null,"isAudioAvailableToGenerate":false,"commentEditor":{"enabled":true,"who":null,"text":"","until":null,"reason":null,"type":"everybody"},"isBlur":false,"isPublished":true,"isDisabledAd":false,"withheld":[],"ogTitle":null,"ogDescription":null,"url":"https://vc.ru/dev/137909-devyatcss-selektorov-na-zametku-nachinayushemu-veb-analitiku","author":{"id":440788,"name":"Natalia Kurinna","nickname":null,"description":null,"uri":"","avatar":{"type":"image","data":{"uuid":"8f3384f1-3319-ca6a-6615-08b064b15e2e","width":690,"height":798,"size":1686201,"type":"png","color":"ab9893","hash":"0763cbcbcbd32d0b","external_service":[]}},"cover":null,"achievements":[{"title":"Год на vc.ru","code":"registration_1_year","description":"Первый год с vc.ru. Получена 24 июля 2025.","previewUuid":"0d11c244-49de-50e7-894e-b9b27945d42b","formats":{"glb":"https://static.vc.ru/achievements/fish.glb","usdz":"https://static.vc.ru/achievements/fish.usdz"},"viewData":{"contentColor":"#C67AA3","textMaxWidth":0.634765625,"textX":0.5888671875,"textY":0.54296875,"logoX":0.5859375,"logoY":0.6669921875,"logoXNoText":0.6044921875,"logoYNoText":0.5439453125},"id":4987394,"userId":440788,"count":0,"shareImage":"https://api.vc.ru/achievements/share/4987394"},{"title":"3 года на vc.ru","code":"registration_3_years","description":"Провёл 3 года вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"d9d72ac5-bcb5-55e0-8c72-b99251e5cdd9","formats":{"glb":"https://static.vc.ru/achievements/shark.glb","usdz":"https://static.vc.ru/achievements/shark.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.5205078125,"textY":0.341796875,"logoX":0.5205078125,"logoY":0.4609375,"logoXNoText":0.5,"logoYNoText":0.3662109375},"id":1363307,"userId":440788,"count":0,"shareImage":"https://api.vc.ru/achievements/share/1363307"},{"title":"5 лет на vc.ru","code":"registration_5_years","description":"Провёл 5 лет вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"a9140d54-73b8-5f40-afa8-449fbaafd42b","formats":{"glb":"https://static.vc.ru/achievements/whale.glb","usdz":"https://static.vc.ru/achievements/whale.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.533203125,"textY":0.658203125,"logoX":0.533203125,"logoY":0.77734375,"logoXNoText":0.4375,"logoYNoText":0.66015625},"id":136599,"userId":440788,"count":0,"shareImage":"https://api.vc.ru/achievements/share/136599"}],"lastModificationDate":1764981758,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":true,"badgeId":null,"isDonationsEnabled":false,"isPlusGiftEnabled":true,"isUnverifiedBlogForCompanyWithoutPro":false,"isRemovedByUserRequest":false,"isFrozen":false,"isDisabledAd":false,"isPlus":false,"isVerified":false,"isPro":false,"yandexMetricaId":null,"badge":null,"isOnline":false,"tgChannelShortname":null,"isUnsubscribable":true,"type":1,"subtype":"personal_blog"},"subsite":{"id":235819,"name":"Разработка","description":"Сообщество разработчиков: публикации о личном опыте, выдающиеся приёмы при решении рутинных задач, полезные материалы для профессионального роста.","uri":"/dev","avatar":{"type":"image","data":{"uuid":"fef5b5fb-e488-5b7f-8445-e3a26a910b44","width":1200,"height":1200,"size":7757,"type":"png","color":"343434","hash":"04042b2b1c1000","external_service":[]}},"cover":{"type":"image","data":{"uuid":"2a214cc5-35cc-58ca-bc07-fc1c892d2101","width":960,"height":280,"size":177,"type":"png","color":"343434","hash":"","external_service":[]}},"lastModificationDate":1642411346,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":false,"isDisabledAd":false,"nickname":"dev","isUnsubscribable":true,"badge":null,"badgeId":null,"isDonationsEnabled":false,"isOnline":false,"isPlus":false,"isUnverifiedBlogForCompanyWithoutPro":false,"isVerified":false,"isRemovedByUserRequest":false,"isFrozen":false,"isPro":false,"type":2,"subtype":"community"},"reactions":{"counters":[{"id":1,"count":3}],"reactionId":0},"isNews":false,"source":null,"clusters":[],"donations":{"amount":0,"isDonated":false},"commentsSeenCount":null}},{"type":"entry","data":{"id":104147,"customUri":null,"subsiteId":440788,"title":"Веб парсинг: 10 вещей, на которые следует обратить внимание, чтобы избежать обнаружения","date":1580394547,"dateModified":1580394547,"blocks":[{"type":"text","cover":true,"hidden":false,"anchor":"","data":{"text":"

В данной статье не рассматриваются правовые и этические вопросы, связанные с парсингом. Она сосредоточена на технических аспектах предотвращения обнаружения. Ниже перечислены наиболее распространенные проблемы, с которыми вы можете столкнуться при парсинге. Конечно, каждый веб сайт имеет свои особенности, которые необходимо учитывать при создании парсера. Это своего рода универсальный чек лист, по которому будет полезно пройтись как тем, кто уже столкнулся с препятствиями, так и тем, кто только начал изучать парсинг.

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"1. Юзер агент"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Переключение или рандомное назначение юзер агентов является одной из наиболее эффективных тактик предотвращения обнаружения. Многие сисадмины и IT-менеджеры отслеживают количество запросов с разных юзер агентов. Если они видят необычно большое количество запросов с одного IP и юзер агента - user agent/IP нарушителя будут заблокированы. Вы можете наблюдать это в действии, когда парсите с использованием стандартных заголовков, предоставляемых HTTP библиотеками. Попробуйте запросить страницу Amazon, используя стандартные заголовки запросов Python, и вы сразу получите 503.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Чтобы минимизировать вероятность блокировки, вы можете установить кастомный юзер агент. Лучше выбирать юзер агент рандомно из списка самых распространенных. С помощью библиотеки запросов Python можно сделать это следующим образом:

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"from random import choice\nimport requests\n\ndesktop_agents = ['Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36',\n 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36',\n 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36',\n 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0.1 Safari/602.2.14',\n 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36',\n 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36',\n 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36',\n 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36',\n 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36',\n 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0']\n\ndef random_headers():\n return {'User-Agent': choice(desktop_agents),'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'}\n\nr = requests.get('https://edmundmartin.com',headers=random_headers())","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Приведенный выше фрагмент кода возвращает случайный юзер агент и стандартный заголовок Chrome ‘Accept’. Этот фрагмент кода содержит десять наиболее часто используемых браузеров для десктопа. Стоит время от времени обновлять список браузеров, чтобы обеспечить актуальность юзер агентов, включенных в список.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

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

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"2. Остальные заголовки"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Даже когда вы меняете юзер агенты, есть вероятность, что вас раскроют. Иногда вас могут выдать другие элементы заголовков. Заголовки ‘accept’ и ‘accept encoding’, отправляемые HTTP библиотеками, как правило отличаются от тех, которые отправляются реальными браузерами. Вы можете модифицировать эти заголовки, чтобы сделать их максимально похожими на заголовки реального браузера.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Любой, кто присмотрится к заголовкам ‘Accept’ в примере с рандомной сменой юзер агента, быстро поймет, что различные юзер агенты используют один и тот же заголовок ‘Accept’. К счастью, большинство системных администраторов полностью игнорируют хитросплетения этих заголовков и просто проверяют, отправляют ли браузеры что-либо правдоподобное.

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"3. Таймауты"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

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

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"4. Прокси"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

В некоторых случаях прокси - это необходимость. Для парсинга больших объемов данных требуется много ресурсов, поэтому нет необходимости «изобретать велосипед», разрабатывая собственную внутреннюю инфраструктуру для управления прокси. Если в парсинге вы новичок - за прокси лучше обратится к прокси-провайдеру, который поможет вам их настроить и позаботится о всех трудностях с их управлением.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Хорошим примером такого провайдера является Infatica. Они предоставляют резидентные прокси, которые идеально подходят для парсинга, поскольку это IP реальных пользователей. Обнаружить парсинг с такими прокси практически невозможно - они маскируют ваши запросы и для сайта, который активно препятствует скрепингу, ваши запросы поступают с разных источников.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Даже крупные e-commerce компании передают управление прокси на аутсорс прокси-сетям, поскольку приоритетом № 1 для большинства компаний являются данные, а не управление прокси. Многие SEO-агентства и компании, занимающимся digital маркетингом, также прибегают к подобным SaaS-компаниям для получения данных о ранжировании в поисковых системах. Они “вращают” и контролируют состояние своих прокси с целью извлечения огромных объемов данных из Google и других поисковиков.

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"5. Рендеринг JavaScript"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

JavaScript используется сейчас практически везде. Количество людей, браузеры которых не поддерживают JavaScript, составляет менее <1%. Поэтому для некоторых сайтов IP, отправляющие большое количество запросов без рендеринга JavaScript, являются одним из триггеров для блокировки. Простое решение - рендерить JavaScript, используя безголовый браузер и Selenium.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Для блокировки ботов такие компании как Cloudflare используют проверку на предмет включен ли у пользователя JavaScript. Однако в настоящее время существует несколько библиотек, которые помогут обойти защиту, реализованную Cloudflare. Библиотека Python cloudflare-scrape представляет собой обертку вокруг библиотеки запросов, которая просто запускает тест JavaScript Cloudflare в среде узлов, если обнаружит, что такая защита установлена.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Кроме того, вы можете воспользоваться облегченным безголовым браузером, таким как Splash. Этот специализированный браузер позволяет даже установить правила AdBlock Plus, позволяющие быстрее отображать страницы, и может использоваться вместе с популярным фреймворком Scrapy.

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"6. Исключения"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

То, что многие краулеры и парсеры не могут делать, - это отключение после того, как начинают получать ошибки 403 и 503. Когда после прохождения множества страниц с ошибками парсер продолжает запрашивать еще больше страниц, становится совершенно очевидно, что вы на самом деле бот. У вас должна быть возможность приостановить и возобновить парсинг, чтобы по ходу дела поправить код. Замедление и откаты назад, когда вы получаете ошибки запрещенного доступа, могут помочь вам избежать постоянного бана.

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"7. Honeypots/ловушки для ботов"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Некоторые вебмастера внедряют ловушки, которые стремятся захватить ботов путем направления их на страницы, единственная цель которых - определить, являются ли они ботами. Существует очень популярный плагин WordPress, который просто создает пустой каталог «/ blackhole /» на вашем сайте. Затем ссылка на этот каталог скрывается в нижнем колонтитуле сайта, который не виден тем, кто использует браузеры. При разработке парсера для конкретного сайта стоит посмотреть, не скрыты ли какие-либо ссылки для пользователей, загружающих страницу с помощью стандартного браузера.

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"8. Robots.txt"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Простое соблюдение robots.txt во время парсинга может избавить вас от многих проблем. Хотя сам файл robots.txt не обеспечивает защиту от парсеров, некоторые веб-мастера просто блокируют любой IP-адрес, который делает много запросов на заблокированные в robots.txt страницы. К счастью, процент веб-мастеров, которые это делают, довольно мал. Если контент, который вам нужен, заблокирован robots.txt, вам, конечно, придется его проигнорировать. Но я настоятельно рекомендую вам уважать чужие правила, а то, что не запрещено в нем - разрешено. Старайтесь соблюдать инструкции robots.txt - это определенно может избавить вас от серьезных проблем.

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"9. Куки"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

В некоторых случаях полезно собирать и хранить куки. При парсинге таких сервисов как Google, cookie-файлы могут влиять на результаты, возвращаемые поисковой системой. Большинство тех, кто парсит поиск Google, не отправляют cookie с запросами, что является ненормальным с точки зрения поведения обычного пользователя. Если вы не возражаете против получения персонализированных результатов, отправка куки вместе со своими запросами может быть хорошей идеей для некоторых задач.

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"10. Капча"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Капча - одна из самых трудных для обхода мер по защите от парсинга. К счастью, капча невероятно раздражает и реальных пользователей, поэтому не многие сайты злоупотребляют ею. Справиться с капчей можно либо с помощью инструментов компьютерного зрения, таких как tesseract-ocr, либо можно приобрести решения в ряде API сервисов, которые используют людей для решения основных капч. Эти сервисы доступны даже для последних визуальных капч от Google - просто они будут стоить дороже.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Используя приведенные выше советы, вы сможете спарсить подавляющее большинство сайтов, не сталкиваясь с какими-либо проблемами.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

P.S. Написано по материалам edmundmartin.com - полезный ресурс для всех, кто занимается парсингом или изучает его.

"}}],"summaryContent":null,"isExistSummaryContent":false,"warningFromEditor":null,"warningFromEditorTitle":null,"counters":{"comments":4,"favorites":46,"reposts":0,"views":7,"hits":10283,"reads":null,"online":0},"dateFavorite":0,"hitsCount":10283,"isCommentsEnabled":true,"isLikesEnabled":true,"isRemovedByUserRequest":false,"isFavorited":false,"isPinned":false,"repostId":null,"repostData":null,"subscribedToTreads":false,"isEditorial":false,"isAudioAvailable":false,"audioUrl":null,"isAudioAvailableToGenerate":false,"commentEditor":{"enabled":true,"who":null,"text":"","until":null,"reason":null,"type":"everybody"},"isBlur":false,"isPublished":true,"isDisabledAd":true,"withheld":[],"ogTitle":null,"ogDescription":null,"url":"https://vc.ru/services/104147-veb-parsing-10-veshei-na-kotorye-sleduet-obratit-vnimanie-chtoby-izbezhat-obnaruzheniya","author":{"id":440788,"name":"Natalia Kurinna","nickname":null,"description":null,"uri":"","avatar":{"type":"image","data":{"uuid":"8f3384f1-3319-ca6a-6615-08b064b15e2e","width":690,"height":798,"size":1686201,"type":"png","color":"ab9893","hash":"0763cbcbcbd32d0b","external_service":[]}},"cover":null,"achievements":[{"title":"Год на vc.ru","code":"registration_1_year","description":"Первый год с vc.ru. Получена 24 июля 2025.","previewUuid":"0d11c244-49de-50e7-894e-b9b27945d42b","formats":{"glb":"https://static.vc.ru/achievements/fish.glb","usdz":"https://static.vc.ru/achievements/fish.usdz"},"viewData":{"contentColor":"#C67AA3","textMaxWidth":0.634765625,"textX":0.5888671875,"textY":0.54296875,"logoX":0.5859375,"logoY":0.6669921875,"logoXNoText":0.6044921875,"logoYNoText":0.5439453125},"id":4987394,"userId":440788,"count":0,"shareImage":"https://api.vc.ru/achievements/share/4987394"},{"title":"3 года на vc.ru","code":"registration_3_years","description":"Провёл 3 года вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"d9d72ac5-bcb5-55e0-8c72-b99251e5cdd9","formats":{"glb":"https://static.vc.ru/achievements/shark.glb","usdz":"https://static.vc.ru/achievements/shark.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.5205078125,"textY":0.341796875,"logoX":0.5205078125,"logoY":0.4609375,"logoXNoText":0.5,"logoYNoText":0.3662109375},"id":1363307,"userId":440788,"count":0,"shareImage":"https://api.vc.ru/achievements/share/1363307"},{"title":"5 лет на vc.ru","code":"registration_5_years","description":"Провёл 5 лет вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"a9140d54-73b8-5f40-afa8-449fbaafd42b","formats":{"glb":"https://static.vc.ru/achievements/whale.glb","usdz":"https://static.vc.ru/achievements/whale.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.533203125,"textY":0.658203125,"logoX":0.533203125,"logoY":0.77734375,"logoXNoText":0.4375,"logoYNoText":0.66015625},"id":136599,"userId":440788,"count":0,"shareImage":"https://api.vc.ru/achievements/share/136599"}],"lastModificationDate":1764981758,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":true,"badgeId":null,"isDonationsEnabled":false,"isPlusGiftEnabled":true,"isUnverifiedBlogForCompanyWithoutPro":false,"isRemovedByUserRequest":false,"isFrozen":false,"isDisabledAd":false,"isPlus":false,"isVerified":false,"isPro":false,"yandexMetricaId":null,"badge":null,"isOnline":false,"tgChannelShortname":null,"isUnsubscribable":true,"type":1,"subtype":"personal_blog"},"subsite":{"id":200396,"name":"Сервисы","description":"Новые сервисы, обновления инструментов, опыт использования и полезные приёмы.","uri":"/services","avatar":{"type":"image","data":{"uuid":"158fab2d-76c1-5ed8-898a-76ee48d4c795","width":1200,"height":1200,"size":99571,"type":"png","color":"7cdaea","hash":"08183848d81000","external_service":[]}},"cover":{"type":"image","data":{"uuid":"c3fe3abb-6808-527e-9eb1-2b6bb92ea400","width":3840,"height":1120,"size":19502,"type":"png","color":"7cdcec","hash":"","external_service":[]}},"lastModificationDate":1688995401,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":false,"isDisabledAd":false,"nickname":"services","isUnsubscribable":true,"badge":null,"badgeId":null,"isDonationsEnabled":false,"isOnline":false,"isPlus":false,"isUnverifiedBlogForCompanyWithoutPro":false,"isVerified":false,"isRemovedByUserRequest":false,"isFrozen":false,"isPro":false,"type":2,"subtype":"community"},"reactions":{"counters":[{"id":1,"count":4}],"reactionId":0},"isNews":false,"source":null,"clusters":[],"donations":{"amount":0,"isDonated":false},"commentsSeenCount":null}}],"cursor":"PuR2GsZKFTvhhGtRAY/m79rVS6IzQAa09I6wtbz/zlbeaPDONLamx05S5m9Akm4=","isAnonymized":true}};