<?xml version="1.0" encoding="utf-8" ?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:tt="http://teletype.in/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"><title>Vatican</title><subtitle>Frontend architect</subtitle><author><name>Vatican</name></author><id>https://teletype.in/atom/vatican_joy</id><link rel="self" type="application/atom+xml" href="https://teletype.in/atom/vatican_joy?offset=0"></link><link rel="alternate" type="text/html" href="https://vatican-blog.cvv.life/?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=vatican_joy"></link><link rel="next" type="application/rss+xml" href="https://teletype.in/atom/vatican_joy?offset=10"></link><link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></link><updated>2026-11-11T09:48:21.482Z</updated><entry><id>vatican_joy:osint-map</id><link rel="alternate" type="text/html" href="https://vatican-blog.cvv.life/osint-map?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=vatican_joy"></link><title>003 — OSINT: полная карта открытых источников</title><published>2026-09-22T01:08:31.914Z</published><updated>2026-09-22T01:08:31.914Z</updated><summary type="html">&lt;img src=&quot;https://img1.teletype.in/files/46/08/4608ffc3-c5f6-4016-bfb2-be00a2789c9c.jpeg&quot;&gt;Всё, что можно узнать о человеке, фирме, месте и объекте — без единого запроса в закрытые базы</summary><content type="html">
  &lt;blockquote id=&quot;CQOp&quot;&gt;&lt;em&gt;Всё, что можно узнать о человеке, фирме, месте и объекте — без единого запроса в закрытые базы&lt;/em&gt;&lt;/blockquote&gt;
  &lt;h2 id=&quot;NUl3&quot;&gt;Часть 1: Философия&lt;/h2&gt;
  &lt;p id=&quot;P13p&quot;&gt;Ты оставляешь след везде. Каждый пост, фото, заказ, логин, маршрут. Эти данные &lt;strong&gt;уже публичны&lt;/strong&gt; — просто разложены по сотням мест.&lt;/p&gt;
  &lt;p id=&quot;Eayx&quot;&gt;&lt;strong&gt;OSINT&lt;/strong&gt; — &lt;em&gt;искусство собирать эти куски в единую картину.&lt;/em&gt;&lt;/p&gt;
  &lt;ul id=&quot;91RD&quot;&gt;
    &lt;li id=&quot;tmZA&quot;&gt;Фрагмент 1: ник на форуме&lt;/li&gt;
    &lt;li id=&quot;d5OC&quot;&gt;Фрагмент 2: почта в утечке&lt;/li&gt;
    &lt;li id=&quot;P8YQ&quot;&gt;Фрагмент 3: фото с геолокацией&lt;/li&gt;
    &lt;li id=&quot;h4D3&quot;&gt;Фрагмент 4: номер телефона в объявлении&lt;/li&gt;
    &lt;li id=&quot;056q&quot;&gt;Фрагмент 5: коммент в соцсети&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;32Jm&quot;&gt;По отдельности — мусор.&lt;br /&gt;Вместе — досье.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;AyI8&quot;&gt;Часть 2: Классификация&lt;/h2&gt;
  &lt;p id=&quot;u544&quot;&gt;&lt;em&gt;OSINT делится на дисциплины. У каждой свои инструменты и методы.&lt;/em&gt;&lt;/p&gt;
  &lt;figure id=&quot;XJuJ&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/84/b1/84b136e6-7aad-41cd-8499-ace83117204a.png&quot; width=&quot;672&quot; /&gt;
  &lt;/figure&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;jhfx&quot;&gt;Часть 3: SOCMINT — человек через соцсети&lt;/h2&gt;
  &lt;h3 id=&quot;GYGH&quot;&gt;Метод 1: Пивот от ника&lt;/h3&gt;
  &lt;blockquote id=&quot;9tAD&quot;&gt;&lt;em&gt;Один ник почти всегда используется на десятках площадок. Это точка входа.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;p id=&quot;lHmz&quot;&gt;&lt;strong&gt;Инструменты:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;mTuX&quot;&gt;
    &lt;li id=&quot;q1iA&quot;&gt;WhatsMyName (web) — 600+ площадок&lt;/li&gt;
    &lt;li id=&quot;mDKS&quot;&gt;Sherlock (CLI) — быстрый перебор&lt;/li&gt;
    &lt;li id=&quot;iYvA&quot;&gt;Maigret (CLI) — Sherlock на стероидах&lt;/li&gt;
    &lt;li id=&quot;0dN3&quot;&gt;Nexfil (CLI) — фокус на стриминг и киносайты&lt;/li&gt;
    &lt;li id=&quot;4yn7&quot;&gt;Blackbird (CLI) — быстрый + поиск аккаунтов&lt;/li&gt;
    &lt;li id=&quot;unDq&quot;&gt;ID Crawl — веб-интерфейс&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;6hsR&quot;&gt;&lt;strong&gt;Sherlock в действии:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;rog1&quot; data-lang=&quot;python&quot;&gt;# Установка
pip install sherlock-project

# Поиск ника на 400+ сайтах
sherlock vatican --timeout 10

# Результат:
# [+] GitHub: https://github.com/vatican
# [+] Telegram: https://t.me/vatican
# [+] Steam: https://steamcommunity.com/id/vatican
# [+] Reddit: https://reddit.com/user/vatican
# [+] SoundCloud: https://soundcloud.com/vatican&lt;/pre&gt;
  &lt;p id=&quot;lnbA&quot;&gt;&lt;strong&gt;Maigret — глубже:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;i1Ak&quot; data-lang=&quot;python&quot;&gt;# Поддерживает больше сайтов + вытаскивает доп. инфо
maigret vatican --html report

# Парсит аватарки, био, количество постов
# Генерирует HTML-отчёт со всеми найденными аккаунтами&lt;/pre&gt;
  &lt;h3 id=&quot;r4lD&quot;&gt;Метод 2: Пивот от email&lt;/h3&gt;
  &lt;blockquote id=&quot;wSlK&quot;&gt;&lt;em&gt;Почта — ключ к большинству сервисов.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;p id=&quot;7q1e&quot;&gt;Как пример:&lt;/p&gt;
  &lt;ul id=&quot;qMbf&quot;&gt;
    &lt;li id=&quot;Norg&quot;&gt;Email → leaks → пароли&lt;/li&gt;
    &lt;li id=&quot;KpUb&quot;&gt;Email → GitHub → код, коммиты, юзернейм&lt;/li&gt;
    &lt;li id=&quot;Ayc8&quot;&gt;Email → Gravatar → аватар&lt;/li&gt;
    &lt;li id=&quot;4KOJ&quot;&gt;Email → соцсети → восстановление → маска номера&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;BgCo&quot;&gt;&lt;strong&gt;Агрегаторы email:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;9GZ9&quot;&gt;
    &lt;li id=&quot;Z1HP&quot;&gt;Epieos — покажет где зарегистрирован email&lt;/li&gt;
    &lt;li id=&quot;cqMW&quot;&gt;EmailRep — репутация и возраст почты&lt;/li&gt;
    &lt;li id=&quot;HqtT&quot;&gt;Holehe — проверка регистрации на 120+ сайтах&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;Eg4F&quot;&gt;&lt;strong&gt;Holehe — где зарегистрирована почта:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;PqcJ&quot; data-lang=&quot;python&quot;&gt;pip install holehe
holehe target@example.com

# [+] Instagram — зарегистрирован
# [+] Twitter — зарегистрирован
# [+] Spotify — зарегистрирован
# [+] Discord — зарегистрирован&lt;/pre&gt;
  &lt;h3 id=&quot;2w1H&quot;&gt;Метод 3: Пивот от телефона&lt;/h3&gt;
  &lt;blockquote id=&quot;OTEz&quot;&gt;&lt;em&gt;Номер телефона — это оператор, регион, и часто — имя.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;ul id=&quot;7RKm&quot;&gt;
    &lt;li id=&quot;uYT0&quot;&gt;Номер → оператор/регион → гео&lt;/li&gt;
    &lt;li id=&quot;G8WJ&quot;&gt;Номер → Telegram → аватар, юзернейм, био&lt;/li&gt;
    &lt;li id=&quot;hZkN&quot;&gt;Номер → мессенджеры (WhatsApp, Viber)&lt;/li&gt;
    &lt;li id=&quot;7R4j&quot;&gt;Номер → объявления (Avito, Юла)&lt;/li&gt;
    &lt;li id=&quot;V9ag&quot;&gt;Номер → утечки&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;a88w&quot;&gt;&lt;strong&gt;Определение оператора и региона:&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;NGC5&quot;&gt;&lt;em&gt;&lt;u&gt;Портация номеров между операторами делает определение оператора неточным&lt;/u&gt;&lt;/em&gt;&lt;/p&gt;
  &lt;pre id=&quot;uc2j&quot; data-lang=&quot;python&quot;&gt;import phonenumbers
from phonenumbers import carrier, geocoder, timezone

def analyze_phone(number_str):
    try:
        number = phonenumbers.parse(number_str, &amp;quot;RU&amp;quot;)
        
        if not phonenumbers.is_valid_number(number):
            return {&amp;quot;valid&amp;quot;: False}
        
        return {
            &amp;quot;valid&amp;quot;: True,
            &amp;quot;country&amp;quot;: geocoder.description_for_number(number, &amp;quot;ru&amp;quot;),
            &amp;quot;carrier&amp;quot;: carrier.name_for_number(number, &amp;quot;ru&amp;quot;),
            &amp;quot;timezone&amp;quot;: str(timezone.time_zones_for_number(number)),
            &amp;quot;type&amp;quot;: phonenumbers.number_type(number),
            &amp;quot;formatted&amp;quot;: phonenumbers.format_number(
                number, phonenumbers.PhoneNumberFormat.INTERNATIONAL
            )
        }
    except Exception as e:
        return {&amp;quot;error&amp;quot;: str(e)}&lt;/pre&gt;
  &lt;p id=&quot;Zt1q&quot;&gt;&lt;strong&gt;Telegram как OSINT-инструмент:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;g5pf&quot;&gt;
    &lt;li id=&quot;yDzx&quot;&gt;Метод 1: Добавление в контакты&lt;br /&gt;Telegram покажет: аватар, имя, юзернейм, био, последний раз онлайн&lt;/li&gt;
    &lt;li id=&quot;s7p6&quot;&gt;Метод 2: через Telegram API&lt;br /&gt;даже без сохранения контакта можно получить:&lt;br /&gt;     - аватар&lt;br /&gt;     - юзернейм&lt;br /&gt;     - last seen&lt;br /&gt;     - статус (был недавно/онлайн/офлайн)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;UBOA&quot;&gt;&lt;strong&gt;Пример использования:&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;UEcB&quot;&gt;api id и api hash можно получить тут &lt;br /&gt;&lt;a href=&quot;https://my.telegram.org/auth&quot; target=&quot;_blank&quot;&gt;https://my.telegram.org/auth&lt;/a&gt;&lt;/p&gt;
  &lt;pre id=&quot;oYF9&quot; data-lang=&quot;python&quot;&gt;from telethon.sync import TelegramClient

api_id = API_ID
api_hash = &amp;quot;API_HASH&amp;quot;

with TelegramClient(&amp;quot;session&amp;quot;, api_id, api_hash) as client:
    # Поиск по номеру
    contact = client.get_entity(&amp;quot;+79991234567&amp;quot;)
    
    print(f&amp;quot;Имя: {contact.first_name} {contact.last_name}&amp;quot;)
    print(f&amp;quot;Юзернейм: @{contact.username}&amp;quot;)
    print(f&amp;quot;Телефон: {contact.phone}&amp;quot;)
    print(f&amp;quot;Статус: {contact.status}&amp;quot;)
    
    # Скачать аватар
    client.download_profile_photo(contact, file=&amp;quot;avatar.jpg&amp;quot;)
    
    # Получить био
    full = client.get_entity(contact)
    print(f&amp;quot;Био: {full.about}&amp;quot;)&lt;/pre&gt;
  &lt;p id=&quot;e7h2&quot;&gt;&lt;strong&gt;Определение наличия в мессенджерах:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;eCl9&quot;&gt;
    &lt;li id=&quot;JbBs&quot;&gt;truecaller — имя по номеру (платно, но есть триал)&lt;/li&gt;
    &lt;li id=&quot;Z0Ku&quot;&gt;eyecon — то же&lt;/li&gt;
    &lt;li id=&quot;qN3e&quot;&gt;GetContact — показывает как записан в контактах других&lt;/li&gt;
    &lt;li id=&quot;EPf7&quot;&gt;NumBuster — аналогично&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;um2o&quot;&gt;Метод 4: Кросс-корреляция&lt;/h3&gt;
  &lt;blockquote id=&quot;5dNt&quot;&gt;&lt;em&gt;Самое мощное — когда данные из разных источников сходятся.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;p id=&quot;730E&quot;&gt;Пример пайплайна:&lt;/p&gt;
  &lt;p id=&quot;M6Uy&quot;&gt;Ник &amp;quot;vatican&amp;quot;&lt;br /&gt;  → Sherlock находит Twitter, GitHub, Telegram&lt;br /&gt;  → GitHub → email в коммите → vatican@example.com&lt;br /&gt;  → Holehe → почта зарегистрирована в VK, Avito&lt;br /&gt;  → VK → настоящие имя и фамилия, город&lt;br /&gt;  → Avito → телефон → пробив в Telegram&lt;br /&gt;  → Telegram → настоящее фото → Google Images&lt;br /&gt;  → Google Images → LinkedIn → место работы&lt;br /&gt;  &lt;br /&gt;&lt;em&gt;&lt;u&gt;Итого: полное досье за 30 минут.&lt;/u&gt;&lt;/em&gt;&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;5wCI&quot;&gt;Часть 4: GEOINT — геолокация&lt;/h2&gt;
  &lt;h3 id=&quot;DDVk&quot;&gt;Метод 1: EXIF данные&lt;/h3&gt;
  &lt;blockquote id=&quot;pLfZ&quot;&gt;&lt;em&gt;Каждое фото с телефона содержит метаданные — если автор их не вычистил.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;pre id=&quot;Z0Mu&quot; data-lang=&quot;python&quot;&gt;from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS
import requests

def extract_exif(image_path):
    image = Image.open(image_path)
    exif_data = image._getexif()
    
    if not exif_data:
        return {&amp;quot;error&amp;quot;: &amp;quot;EXIF данные удалены или отсутствуют&amp;quot;}
    
    data = {}
    for tag_id, value in exif_data.items():
        tag = TAGS.get(tag_id, tag_id)
        data[tag] = value
    
    # GPS координаты
    if &amp;quot;GPSInfo&amp;quot; in data:
        gps_info = data[&amp;quot;GPSInfo&amp;quot;]
        gps = {}
        for key in gps_info:
            decode = GPSTAGS.get(key, key)
            gps[decode] = gps_info[key]
        
        # Конвертация в десятичные градусы
        def dms_to_decimal(dms, ref):
            degrees = float(dms[0])
            minutes = float(dms[1])
            seconds = float(dms[2])
            decimal = degrees + minutes/60 + seconds/3600
            if ref in [&amp;quot;S&amp;quot;, &amp;quot;W&amp;quot;]:
                decimal = -decimal
            return decimal
        
 lat = dms_to_decimal(gps[&amp;quot;GPSLatitude&amp;quot;], gps.get(&amp;quot;GPSLatitudeRef&amp;quot;, &amp;quot;N&amp;quot;))
 lon = dms_to_decimal(gps[&amp;quot;GPSLongitude&amp;quot;], gps.get(&amp;quot;GPSLongitudeRef&amp;quot;, &amp;quot;E&amp;quot;))
        
        return {
            &amp;quot;coordinates&amp;quot;: (lat, lon),
            &amp;quot;maps_link&amp;quot;: f&amp;quot;https://maps.google.com/?q={lat},{lon}&amp;quot;,
            &amp;quot;camera&amp;quot;: data.get(&amp;quot;Model&amp;quot;),
            &amp;quot;date&amp;quot;: data.get(&amp;quot;DateTimeOriginal&amp;quot;),
            &amp;quot;software&amp;quot;: data.get(&amp;quot;Software&amp;quot;)
        }
    
    return {&amp;quot;gps&amp;quot;: &amp;quot;нет GPS данных&amp;quot;, &amp;quot;meta&amp;quot;: data}

# Что даёт EXIF:
# точные координаты съёмки
# модель телефона/камеры
# дату и время
# настройки съёмки
# иногда — серийный номер устройства&lt;/pre&gt;
  &lt;p id=&quot;mqm0&quot;&gt;&lt;strong&gt;Проверка онлайн (без установки):&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;BB0X&quot;&gt;
    &lt;li id=&quot;zwtJ&quot;&gt;exif.tools — просто загрузил увидел всё&lt;/li&gt;
    &lt;li id=&quot;4DSO&quot;&gt;fotoforensics.com — анализ + детект фотошопа&lt;/li&gt;
    &lt;li id=&quot;5H8e&quot;&gt;metapicz — аналогично&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;OWd7&quot;&gt;Метод 2: Геолокация по фото без EXIF&lt;/h3&gt;
  &lt;blockquote id=&quot;14MD&quot;&gt;&lt;em&gt;Когда метаданные вычищены — включается дедукция. Это уже ремесло.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;p id=&quot;sgAz&quot;&gt;&lt;strong&gt;Что смотреть на фото:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;BIqy&quot;&gt;
    &lt;li id=&quot;XNow&quot;&gt;Таблички (названия улиц, номера домов)&lt;/li&gt;
    &lt;li id=&quot;ANEf&quot;&gt;Вывески (магазины, рестораны, названия)&lt;/li&gt;
    &lt;li id=&quot;GSbL&quot;&gt;Язык надписей и шрифты&lt;/li&gt;
    &lt;li id=&quot;Td7s&quot;&gt;Номерные знаки машин (формат, цвет, регион)&lt;/li&gt;
    &lt;li id=&quot;GFeR&quot;&gt;Сторона движения (левостороннее/правостороннее)&lt;/li&gt;
    &lt;li id=&quot;955N&quot;&gt;Архитектурный стиль&lt;/li&gt;
    &lt;li id=&quot;8PLu&quot;&gt;Тип фонарей и разметки&lt;/li&gt;
    &lt;li id=&quot;b4wX&quot;&gt;Положение солнца (время + полушарие)&lt;/li&gt;
    &lt;li id=&quot;sxLb&quot;&gt;Провода (есть/нет, над/под землёй)&lt;/li&gt;
    &lt;li id=&quot;SD3J&quot;&gt;Горы/море/рельеф на горизонте&lt;/li&gt;
    &lt;li id=&quot;obuO&quot;&gt;Как уложена плитка/тротуар (положение/форма/материал/узор)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;x8nc&quot;&gt;&lt;strong&gt;Пошаговый процесс:&lt;/strong&gt;&lt;/p&gt;
  &lt;ol id=&quot;zsN3&quot;&gt;
    &lt;li id=&quot;nqYv&quot;&gt;Обрати внимание на уникальные объекты&lt;/li&gt;
    &lt;li id=&quot;hy6U&quot;&gt;Обратный поиск через Google Lens&lt;/li&gt;
    &lt;li id=&quot;3PwU&quot;&gt;Открой Google Maps в этом регионе&lt;/li&gt;
    &lt;li id=&quot;py64&quot;&gt;Включи Street View&lt;/li&gt;
    &lt;li id=&quot;HgXR&quot;&gt;Совмещай панорамы с фото&lt;/li&gt;
    &lt;li id=&quot;ll1c&quot;&gt;Ищи совпадения по ориентирам&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;nImS&quot;&gt;&lt;strong&gt;Инструменты:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;ybeC&quot;&gt;
    &lt;li id=&quot;NSQe&quot;&gt;Google Lens — распознавание объектов и мест&lt;/li&gt;
    &lt;li id=&quot;rkvN&quot;&gt;Yandex Images — часто лучше Google для СНГ&lt;/li&gt;
    &lt;li id=&quot;zyz3&quot;&gt;Bing Visual Search — третий источник&lt;/li&gt;
    &lt;li id=&quot;9sJn&quot;&gt;GeoGuessr — тренировка навыка (игра)&lt;/li&gt;
    &lt;li id=&quot;w3xJ&quot;&gt;Mapillary — краудсорсинговый street view&lt;/li&gt;
    &lt;li id=&quot;I6bX&quot;&gt;OpenStreetMap — детальные карты&lt;/li&gt;
    &lt;li id=&quot;WX2c&quot;&gt;Sentinel Hub — спутниковые снимки&lt;/li&gt;
    &lt;li id=&quot;CQkF&quot;&gt;SunCalc — положение солнца по времени/месту&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;3IqR&quot;&gt;&lt;strong&gt;Пример метода &amp;quot;солнце + тень&amp;quot;:&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;eDNo&quot;&gt;Дано: фото без гео, с тенью от столба&lt;/p&gt;
  &lt;ol id=&quot;tMNN&quot;&gt;
    &lt;li id=&quot;q8On&quot;&gt;Замерь угол тени относительно объекта&lt;/li&gt;
    &lt;li id=&quot;gIwD&quot;&gt;Солнце движется с востока на запад&lt;/li&gt;
    &lt;li id=&quot;cSx6&quot;&gt;Угол тени + время на фото (если есть) = широта&lt;/li&gt;
    &lt;li id=&quot;clk9&quot;&gt;Сверяешь с картой&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;4TOG&quot;&gt;&lt;strong&gt;Пример метода &amp;quot;вывески&amp;quot;:&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;eKTN&quot;&gt;Фото ресторана изнутри&lt;/p&gt;
  &lt;ol id=&quot;MybR&quot;&gt;
    &lt;li id=&quot;LRvo&quot;&gt;Читаешь название на стакане &amp;quot;Coffee Like&amp;quot;&lt;/li&gt;
    &lt;li id=&quot;gZ0g&quot;&gt;Ищешь &amp;quot;Coffee Like&amp;quot; на 2GIS в городе из контекста&lt;/li&gt;
    &lt;li id=&quot;cjwy&quot;&gt;Открываешь панораму у каждого филиала&lt;/li&gt;
    &lt;li id=&quot;rT8m&quot;&gt;Ищешь совпадение интерьера&lt;/li&gt;
    &lt;li id=&quot;6av9&quot;&gt;Совпало → точная локация&lt;/li&gt;
  &lt;/ol&gt;
  &lt;h3 id=&quot;piD4&quot;&gt;Метод 3: Геолокация через поведение&lt;/h3&gt;
  &lt;blockquote id=&quot;MMvT&quot;&gt;&lt;em&gt;Не фото, а цифровой след человека в пространстве.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;p id=&quot;ECGq&quot;&gt;&lt;strong&gt;Источники&lt;/strong&gt;:&lt;/p&gt;
  &lt;ul id=&quot;YUkb&quot;&gt;
    &lt;li id=&quot;ejjU&quot;&gt;Strava Heatmap — маршруты бегунов (палит военные базы)&lt;/li&gt;
    &lt;li id=&quot;6MDO&quot;&gt;Instagram локации — чекины&lt;/li&gt;
    &lt;li id=&quot;pVSc&quot;&gt;Fitness-трекеры — маршруты&lt;/li&gt;
    &lt;li id=&quot;Wa6s&quot;&gt;Фото по тегам города — где бывает&lt;/li&gt;
    &lt;li id=&quot;IgQm&quot;&gt;Отзывы на картах — Google/Yandex отзывы = места посещения&lt;/li&gt;
    &lt;li id=&quot;CCAf&quot;&gt;Объявления — геолокация на Avito&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;JOO6&quot;&gt;&lt;strong&gt;Strava Heatmap — классический пример:&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;oXHU&quot;&gt;Сервис публикует тепловую карту всех маршрутов пользователей. Через неё нашли:&lt;/p&gt;
  &lt;ul id=&quot;B9nf&quot;&gt;
    &lt;li id=&quot;mw6W&quot;&gt;Секретные военные базы&lt;/li&gt;
    &lt;li id=&quot;9tFP&quot;&gt;Маршруты охраны&lt;/li&gt;
    &lt;li id=&quot;iXP3&quot;&gt;Личные адреса (дом → работа)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;phy2&quot;&gt;Метод 4: Спутниковые снимки&lt;/h3&gt;
  &lt;p id=&quot;Xaln&quot;&gt;Инструменты:&lt;/p&gt;
  &lt;ul id=&quot;KKRq&quot;&gt;
    &lt;li id=&quot;7FBR&quot;&gt;Google Earth Pro — бесплатно, история снимков&lt;/li&gt;
    &lt;li id=&quot;3UND&quot;&gt;Sentinel Playground — свежие снимки (обновление каждые 5 дней)&lt;/li&gt;
    &lt;li id=&quot;dwkC&quot;&gt;Bing Maps — иногда снимки лучше Google&lt;/li&gt;
    &lt;li id=&quot;SppS&quot;&gt;Yandex Maps — для СНГ&lt;/li&gt;
    &lt;li id=&quot;0KvP&quot;&gt;Terraserver — исторические снимки&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;z1NF&quot;&gt;&lt;strong&gt;Что можно определить по спутнику:&lt;/strong&gt;&lt;/p&gt;
  &lt;ol id=&quot;VmcG&quot;&gt;
    &lt;li id=&quot;QesJ&quot;&gt;Размер объекта и планировку&lt;/li&gt;
    &lt;li id=&quot;cQLh&quot;&gt;Теневую сторону в разное время суток&lt;/li&gt;
    &lt;li id=&quot;GUNP&quot;&gt;Историю (Google Earth хранит архив за 20+ лет)&lt;/li&gt;
    &lt;li id=&quot;wOjF&quot;&gt;Транспорт и технику&lt;/li&gt;
    &lt;li id=&quot;5VlM&quot;&gt;Недавние изменения (стройка, снос)&lt;/li&gt;
  &lt;/ol&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;VNpc&quot;&gt;Часть 5: IMINT — изображения&lt;/h2&gt;
  &lt;blockquote id=&quot;0D9U&quot;&gt;Обратный поиск изображений&lt;/blockquote&gt;
  &lt;p id=&quot;4LSf&quot;&gt;&lt;strong&gt;Движки и их сильные стороны:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;sw7s&quot;&gt;
    &lt;li id=&quot;AOTI&quot;&gt;Google Images — Универсальный, глобальный&lt;/li&gt;
    &lt;li id=&quot;xoBN&quot;&gt;Yandex Images — СНГ, лица, лучше всех ищет по людям&lt;/li&gt;
    &lt;li id=&quot;Ngb6&quot;&gt;Bing Visual — Промтовары, продукты&lt;/li&gt;
    &lt;li id=&quot;SUPx&quot;&gt;TinEye — Точное совпадение, история&lt;/li&gt;
    &lt;li id=&quot;5kP3&quot;&gt;PimEyes — Поиск по лицу (найти все фото человека)&lt;/li&gt;
    &lt;li id=&quot;YE90&quot;&gt;FaceCheck.ID — Поиск по лицу в криминальном контексте&lt;/li&gt;
    &lt;li id=&quot;OvPU&quot;&gt;百度 (Baidu) — Азия&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;s4Yk&quot;&gt;&lt;strong&gt;PimEyes — поиск лица:&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;2Mhz&quot;&gt;Загружаешь фото человека&lt;/p&gt;
  &lt;ol id=&quot;43Nm&quot;&gt;
    &lt;li id=&quot;zZqK&quot;&gt;движок сканирует веб&lt;/li&gt;
    &lt;li id=&quot;95s5&quot;&gt;показывает ВСЕ фото этого лица в открытом доступе&lt;/li&gt;
    &lt;li id=&quot;7Uuz&quot;&gt;даже те, где нет тега или имени&lt;/li&gt;
  &lt;/ol&gt;
  &lt;blockquote id=&quot;313A&quot;&gt;&lt;em&gt;Это самый мощный инструмент деанона через визуал. Есть и обратная сторона — работает в обе стороны.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;h3 id=&quot;b9nC&quot;&gt;Автоматизация обратного поиска:&lt;/h3&gt;
  &lt;pre id=&quot;O29Y&quot; data-lang=&quot;python&quot;&gt;# Яндекс Images — автоматический обратный поиск
import requests
from io import BytesIO

def yandex_reverse_search(image_path):
    url = &amp;quot;https://yandex.ru/images/search&amp;quot;
    
    files = {&amp;quot;upfile&amp;quot;: (&amp;quot;image.jpg&amp;quot;, open(image_path, &amp;quot;rb&amp;quot;), &amp;quot;image/jpeg&amp;quot;)}
    params = {&amp;quot;rpt&amp;quot;: &amp;quot;imageview&amp;quot;, &amp;quot;cbird&amp;quot;: &amp;quot;77&amp;quot;}
    
    session = requests.Session()
    response = session.post(url, params=params, files=files)
    
    
    return response.url  # ссылка на результаты поиска

# Для продакшена лучше использовать:
# - SerpAPI (платно, стабильно)
# - Browser automation (Playwright)&lt;/pre&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;xbm4&quot;&gt;Часть 6: TECHINT — инфраструктура&lt;/h2&gt;
  &lt;blockquote id=&quot;0lcb&quot;&gt;Домены и IP &lt;/blockquote&gt;
  &lt;p id=&quot;zgMH&quot;&gt;&lt;strong&gt;Инструменты:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;aPSM&quot;&gt;
    &lt;li id=&quot;Hdr1&quot;&gt;whois — владелец домена, регистратор&lt;/li&gt;
    &lt;li id=&quot;O8fY&quot;&gt;DNSDumpster — вся DNS-структура&lt;/li&gt;
    &lt;li id=&quot;00On&quot;&gt;Shodan — поисковик по устройствам в сети&lt;/li&gt;
    &lt;li id=&quot;eguF&quot;&gt;Censys — аналог Shodan&lt;/li&gt;
    &lt;li id=&quot;V0zb&quot;&gt;SecurityTrails — история DNS, субдомены&lt;/li&gt;
    &lt;li id=&quot;yIUA&quot;&gt;crt.sh — SSL сертификаты и субдомены&lt;/li&gt;
    &lt;li id=&quot;aFMB&quot;&gt;ViewDNS — обратный IP (кто ещё на этом IP)&lt;/li&gt;
    &lt;li id=&quot;INRA&quot;&gt;Hunter.io — email на домене&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;6pPU&quot;&gt;&lt;strong&gt;Shodan — поиск устройств:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;2xg8&quot; data-lang=&quot;python&quot;&gt;import shodan

api = shodan.Shodan(&amp;quot;API_KEY&amp;quot;)

# Поиск открытых камер
results = api.search(&amp;#x27;webcam city:Moscow&amp;#x27;)

for result in results[&amp;#x27;matches&amp;#x27;]:
    print(f&amp;quot;IP: {result[&amp;#x27;ip_str&amp;#x27;]}&amp;quot;)
    print(f&amp;quot;Port: {result[&amp;#x27;port&amp;#x27;]}&amp;quot;)
    print(f&amp;quot;Org: {result.get(&amp;#x27;org&amp;#x27;)}&amp;quot;)
    print(f&amp;quot;Location: {result[&amp;#x27;location&amp;#x27;]}&amp;quot;)
    print(&amp;quot;---&amp;quot;)

# Поиск незащищённых баз данных
results = api.search(&amp;#x27;mongodb port:27017&amp;#x27;)

# Поиск по IP — вся информация об устройстве
host = api.host(&amp;#x27;8.8.8.8&amp;#x27;)
print(host)&lt;/pre&gt;
  &lt;p id=&quot;OreA&quot;&gt;&lt;strong&gt;crt.sh — скрытые субдомены через SSL:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;HnCz&quot; data-lang=&quot;python&quot;&gt;# Все SSL сертификаты, выданные для домена
curl -s &amp;quot;https://crt.sh/?q=%25.example.com&amp;amp;output=json&amp;quot; | \
  jq -r &amp;#x27;.[].name_value&amp;#x27; | sort -u

# Результат — все субдомены, которые когда-либо выпускали серт&lt;/pre&gt;
  &lt;p id=&quot;bPfM&quot;&gt;&lt;strong&gt;Полный OSINT по домену:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;dxFN&quot; data-lang=&quot;python&quot;&gt;import requests
import whois
from dns import resolver

def full_domain_recon(domain):
    report = {}
    
    # WHOIS
    try:
        w = whois.whois(domain)
        report[&amp;quot;registrar&amp;quot;] = w.registrar
        report[&amp;quot;created&amp;quot;] = str(w.creation_date)
        report[&amp;quot;owner&amp;quot;] = w.name  # если не скрыт privacy
    except:
        pass
    
    # DNS записи
    for record_type in [&amp;quot;A&amp;quot;, &amp;quot;MX&amp;quot;, &amp;quot;NS&amp;quot;, &amp;quot;TXT&amp;quot;]:
        try:
            answers = resolver.resolve(domain, record_type)
            report[record_type] = [str(r) for r in answers]
        except:
            pass
    
    # Субдомены через crt.sh
    try:
        resp = requests.get(
            f&amp;quot;https://crt.sh/?q=%25.{domain}&amp;amp;output=json&amp;quot;,
            timeout=10
        )
        subdomains = set()
        for entry in resp.json():
            for name in entry[&amp;quot;name_value&amp;quot;].split(&amp;quot;\n&amp;quot;):
                if domain in name:
                    subdomains.add(name.strip())
        report[&amp;quot;subdomains&amp;quot;] = list(subdomains)
    except:
        pass
    
    # Email через Hunter.io
    # (нужен API ключ, бесплатный тариф — 25 запросов/мес)
    
    return report&lt;/pre&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;q47N&quot;&gt;Часть 7: Утечки данных&lt;/h2&gt;
  &lt;h3 id=&quot;hnYY&quot;&gt;Проверка своих данных&lt;/h3&gt;
  &lt;ul id=&quot;emWT&quot;&gt;
    &lt;li id=&quot;7TFX&quot;&gt;HaveIBeenPwned — email + пароли (проверка по K-Anonymity)&lt;/li&gt;
    &lt;li id=&quot;3bB9&quot;&gt;DeHashed — полный поиск по утечкам (email, имя, IP, телефон)&lt;/li&gt;
    &lt;li id=&quot;KBPp&quot;&gt;LeakCheck — email/телефон/ник&lt;/li&gt;
    &lt;li id=&quot;EisM&quot;&gt;Snusbase — самый быстрый (платный)&lt;/li&gt;
    &lt;li id=&quot;LuIp&quot;&gt;Intelligence X — darknet + утечки&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;kjwx&quot;&gt;Что дают утечки:&lt;/h3&gt;
  &lt;ul id=&quot;yxcy&quot;&gt;
    &lt;li id=&quot;07ry&quot;&gt;Email + пароль → доступ к аккаунтам (если пароль не уникальный)&lt;/li&gt;
    &lt;li id=&quot;s8wy&quot;&gt;Email + телефон → связка для деанона&lt;/li&gt;
    &lt;li id=&quot;TUad&quot;&gt;Email + адрес → физическая локация&lt;/li&gt;
    &lt;li id=&quot;Pfwk&quot;&gt;Email + паспортные данные → полный профиль&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;NP5c&quot;&gt;&lt;strong&gt;Пример работы с DeHashed API:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;lIYH&quot; data-lang=&quot;python&quot;&gt;import requests
import base64

def dehashed_search(query, email, api_key):
    # Поиск по всем утечкам
    auth = base64.b64encode(f&amp;quot;{email}:{api_key}&amp;quot;.encode()).decode()
    
    headers = {
        &amp;quot;Accept&amp;quot;: &amp;quot;application/json&amp;quot;,
        &amp;quot;Authorization&amp;quot;: f&amp;quot;Basic {auth}&amp;quot;
    }
    
    # Поиск можно вести по:
    # email, username, name, address, phone, ip, hash
    
    response = requests.get(
        f&amp;quot;https://api.dehashed.com/search?query=email:{query}&amp;quot;,
        headers=headers
    )
    return response.json()

# Результат содержит:
# - все пароли (в чистом/хешированном виде)
# - все email
# - имена
# - адреса
# - телефоны
# - IP&lt;/pre&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;doci&quot;&gt;Часть 8: Транспорт и физический мир&lt;/h2&gt;
  &lt;blockquote id=&quot;oDUG&quot;&gt;Номера автомобилей&lt;/blockquote&gt;
  &lt;p id=&quot;ea2Y&quot;&gt;Формат российского номера:&lt;br /&gt;&lt;em&gt;&lt;u&gt;А123ВС77 регион 77, Москва&lt;/u&gt;&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;OgRm&quot;&gt;Источники:&lt;/p&gt;
  &lt;ul id=&quot;hLLK&quot;&gt;
    &lt;li id=&quot;IYQ7&quot;&gt;ГИБДД (гибдд.рф) — история ДТП&lt;/li&gt;
    &lt;li id=&quot;5wDM&quot;&gt;Автокод (avtocod.ru) — платный агрегатор&lt;/li&gt;
    &lt;li id=&quot;iXBF&quot;&gt;Номер-база — платные Telegram-боты&lt;/li&gt;
    &lt;li id=&quot;r73r&quot;&gt;Реестр залогов (reestr-zalogov.ru) — залог&lt;/li&gt;
    &lt;li id=&quot;Kq8S&quot;&gt;ФССП — если есть долги владельца&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;JJBA&quot;&gt;Авиация&lt;/h3&gt;
  &lt;ul id=&quot;aUo4&quot;&gt;
    &lt;li id=&quot;WOgp&quot;&gt;Flightradar24  — все рейсы в реальном времени&lt;/li&gt;
    &lt;li id=&quot;wVRe&quot;&gt;ADS-B Exchange — без фильтров (в отличие от FR24)&lt;/li&gt;
    &lt;li id=&quot;5t4p&quot;&gt;OpenSky Network — открытое API&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;QVaC&quot;&gt;&lt;strong&gt;Отслеживание частного борта:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;qVt8&quot; data-lang=&quot;python&quot;&gt;import requests

def track_aircraft(callsign):
    response = requests.get(
        f&amp;quot;https://opensky-network.org/api/states/all?callsign={callsign}&amp;quot;
    )
    data = response.json()
    
    if data.get(&amp;quot;states&amp;quot;):
        for state in data[&amp;quot;states&amp;quot;]:
            return {
                &amp;quot;callsign&amp;quot;: state[1],
                &amp;quot;latitude&amp;quot;: state[6],
                &amp;quot;longitude&amp;quot;: state[5],
                &amp;quot;altitude&amp;quot;: state[13],
                &amp;quot;velocity&amp;quot;: state[9],
                &amp;quot;heading&amp;quot;: state[10],
                &amp;quot;on_ground&amp;quot;: state[8]
            }
    return None&lt;/pre&gt;
  &lt;h3 id=&quot;afBi&quot;&gt;Морской транспорт&lt;/h3&gt;
  &lt;ul id=&quot;4bcE&quot;&gt;
    &lt;li id=&quot;vbQY&quot;&gt;MarineTraffic — все суда&lt;/li&gt;
    &lt;li id=&quot;BTHo&quot;&gt;VesselFinder — аналог&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;rYIm&quot;&gt;Часть 9: Автоматизация — фреймворки&lt;/h2&gt;
  &lt;h3 id=&quot;83u3&quot;&gt;SpiderFoot — автоматический OSINT-скан&lt;/h3&gt;
  &lt;pre id=&quot;f2IF&quot; data-lang=&quot;python&quot;&gt;# Установка
pip install spiderfoot

# Запуск веб-интерфейса
sf -l 127.0.0.1:5001

# Скан по email
sf -s target@example.com -t all

# Скан по IP
sf -s 8.8.8.8 -t all

# Скан по домену
sf -s example.com -t all&lt;/pre&gt;
  &lt;blockquote id=&quot;CcoL&quot;&gt;&lt;em&gt;SpiderFoot автоматически прогоняет цель через 200+ модулей и собирает всё в один отчёт.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;h3 id=&quot;mUlU&quot;&gt;Maltego — визуальный OSINT&lt;/h3&gt;
  &lt;pre id=&quot;NxPJ&quot;&gt;Построение графов связей:
Цель → запросы к разным источникам → визуальные связи

Пример графа:
  Email
  ├── Twitter аккаунт
  │   └── Подписки → другие аккаунты
  ├── Домены (whois)
  │   └── Другие домены на тот же whois
  ├── Утечки
  └── Соцсети

Платный, но Community-версия достаточна для старта.&lt;/pre&gt;
  &lt;h3 id=&quot;lSrt&quot;&gt;TheHarvester — сбор email/субдоменов&lt;/h3&gt;
  &lt;pre id=&quot;tlRG&quot; data-lang=&quot;python&quot;&gt;# Сбор email с домена из публичных источников
theHarvester -d example.com -b all

# Источники:
# - поисковые системы
# - LinkedIn
# - сертификаты
# - DNS&lt;/pre&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;Sd2t&quot;&gt;Часть 10: OpSec исследователя&lt;/h2&gt;
  &lt;blockquote id=&quot;vscE&quot;&gt;&lt;em&gt;Пока ты копаешь — тебя тоже могут копать.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;p id=&quot;RIil&quot;&gt;&lt;strong&gt;Правила гигиены:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;2QHU&quot;&gt;
    &lt;li id=&quot;zlfz&quot;&gt;Никогда не логинься в свои аккаунты при исследовании&lt;/li&gt;
    &lt;li id=&quot;yXLV&quot;&gt;Используй отдельный браузер (профиль) для OSINT&lt;/li&gt;
    &lt;li id=&quot;zflV&quot;&gt;SOCKS5 / VPN — не для анонимности, для смены IP&lt;/li&gt;
    &lt;li id=&quot;2wRX&quot;&gt;Виртуалка для рискованных сайтов&lt;/li&gt;
    &lt;li id=&quot;2w2c&quot;&gt;Не открывай ссылки напрямую — скрин через сервисы&lt;/li&gt;
    &lt;li id=&quot;Fn91&quot;&gt;Не переходи по ссылкам из подозрительных сообщений&lt;/li&gt;
    &lt;li id=&quot;KA7e&quot;&gt;Отключи синхронизацию браузера&lt;/li&gt;
    &lt;li id=&quot;KP11&quot;&gt;Отдельная почта для регистраций при исследовании&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;JZuA&quot;&gt;&lt;strong&gt;Инструменты безопасного просмотра:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;xYU5&quot;&gt;
    &lt;li id=&quot;MGMq&quot;&gt;urlscan.io — скриншот сайта без захода на него&lt;/li&gt;
    &lt;li id=&quot;dQLT&quot;&gt;archive.org — просмотр старой версии&lt;/li&gt;
    &lt;li id=&quot;DlEp&quot;&gt;proxy — через прокси для смены IP&lt;/li&gt;
    &lt;li id=&quot;fkCC&quot;&gt;whonix — виртуалка с Tor&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;Zc1z&quot;&gt;Часть 11: Как НЕ надо&lt;/h2&gt;
  &lt;ul id=&quot;TfCq&quot;&gt;
    &lt;li id=&quot;20LL&quot;&gt;Сталкинг бывших/близких — это незаконно и аморально XD)&lt;/li&gt;
    &lt;li id=&quot;pj1x&quot;&gt;Скачивание данных из взломанных баз (кроме проверки своих)&lt;/li&gt;
    &lt;li id=&quot;1svC&quot;&gt;Попытки взлома на основе собранной информации&lt;/li&gt;
    &lt;li id=&quot;qwrT&quot;&gt;Публикация собранных данных без согласия&lt;/li&gt;
    &lt;li id=&quot;SWem&quot;&gt;Пробив через &amp;quot;серые&amp;quot; Telegram-боты (палевно и небезопасно)&lt;/li&gt;
    &lt;li id=&quot;Xzn5&quot;&gt;Использование OSINT для шантажа&lt;/li&gt;
  &lt;/ul&gt;
  &lt;blockquote id=&quot;F0gE&quot;&gt;&lt;strong&gt;&lt;em&gt;OSINT — это про понимание системы. Будь умнее чем просто шантажировать и публиковать просто так) &lt;/em&gt;&lt;/strong&gt;&lt;/blockquote&gt;
  &lt;blockquote id=&quot;d6m0&quot;&gt;&lt;em&gt;By Vatican&lt;/em&gt;&lt;/blockquote&gt;

</content></entry><entry><id>vatican_joy:Reality_Reversal</id><link rel="alternate" type="text/html" href="https://vatican-blog.cvv.life/Reality_Reversal?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=vatican_joy"></link><title>Reality Reversal</title><published>2026-09-18T10:20:25.295Z</published><updated>2026-09-18T10:20:25.295Z</updated><category term="dev" label="Dev"></category><summary type="html">&lt;img src=&quot;https://img3.teletype.in/files/66/e8/66e89196-e734-482b-88a1-d1734b4208da.jpeg&quot;&gt;В 1986 году The Mentor написал &quot;Сознание хакера&quot;. Прошло почти 40 лет. Мир изменился. Мы — нет.</summary><content type="html">
  &lt;p id=&quot;GvkA&quot;&gt;&lt;em&gt;В 1986 году The Mentor написал &amp;quot;Сознание хакера&amp;quot;. Прошло почти 40 лет. Мир изменился. Мы — нет.&lt;/em&gt;&lt;/p&gt;
  &lt;blockquote id=&quot;LTti&quot;&gt;&lt;strong&gt;Мы верим, что:&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;Знание — это власть. Не доступ к власти. Не инструмент власти. Сама власть.&lt;/strong&gt;&lt;/blockquote&gt;
  &lt;blockquote id=&quot;TV69&quot;&gt;&lt;strong&gt;&lt;br /&gt;Тот, кто понимает механику системы — контролирует её. Тот, кто контролирует — не спрашивает разрешения.&lt;/strong&gt;&lt;/blockquote&gt;
  &lt;h3 id=&quot;G11s&quot;&gt;Наши принципы:&lt;br /&gt;1. Разбирай всё&lt;/h3&gt;
  &lt;blockquote id=&quot;74ct&quot;&gt;&lt;em&gt;Всё, что построено — можно разобрать. Всё, что работает — можно понять. Всё, что можно понять — можно воспроизвести. Нет &amp;quot;закрытых&amp;quot; систем. Есть системы, которые ты ещё не вскрыл.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;h3 id=&quot;3e73&quot;&gt;2. Поверхность — это ложь&lt;/h3&gt;
  &lt;blockquote id=&quot;TDR4&quot;&gt;&lt;em&gt;То, что показывают — витрина. То, что под ней — сущность. API скрыт? Значит есть. Данные &amp;quot;недоступны&amp;quot;? Значит просто не нашли endpoint. Реальность имеет слои, и большинство живёт на первом.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;h3 id=&quot;nlkw&quot;&gt;3. Слабость системы — не твоя проблема&lt;/h3&gt;
  &lt;blockquote id=&quot;1bWH&quot;&gt;&lt;em&gt;Если их пароль — 123456. Если их API отдаёт всё без токена. Если их &amp;quot;защита&amp;quot; — проверка на фронте. Это не ты эксплуатируешь. Это они построили картонный дом.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;h3 id=&quot;kp1a&quot;&gt;4. Инструмент не выбирает цель&lt;/h3&gt;
  &lt;blockquote id=&quot;mN0d&quot;&gt;&lt;em&gt;Молоток не решает, что строить. Скрипт не решает, что парсить. Тот, кто держит инструмент в руках — определяет применение.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;h3 id=&quot;oSfT&quot;&gt;5. Эффективность — единственная метрика&lt;/h3&gt;
  &lt;blockquote id=&quot;QlQ1&quot;&gt;&lt;em&gt;Работает / не работает. Быстро / медленно. Обнаружили / не обнаружили. Остальное — шум.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;h2 id=&quot;6tmV&quot;&gt;Три типа тех, кто в этой игре:&lt;/h2&gt;
  &lt;ol id=&quot;aCky&quot;&gt;
    &lt;li id=&quot;HovK&quot;&gt;Играет по правилам, которые написал кто-то другой. Ждёт bug bounty. Отчитывается. Просит.&lt;/li&gt;
    &lt;li id=&quot;c75z&quot;&gt;Берёт что находит. Не спрашивает. Не оглядывается. Иногда проигрывает.&lt;/li&gt;
    &lt;li id=&quot;dHkt&quot;&gt;Понимает обе стороны. Использует ту, которая даёт результат. Границу двигает под задачу.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;blockquote id=&quot;ZoKA&quot;&gt;&lt;em&gt;Этот канал — не про этику. Не про закон. Не про &amp;quot;как правильно&amp;quot;.&lt;br /&gt;Этот канал — про то, &lt;strong&gt;как всё устроено на самом деле&lt;/strong&gt;.&lt;br /&gt;Система видит то, что показывает. Мы видим то, что она скрывает.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;blockquote id=&quot;CO9o&quot;&gt;&lt;em&gt;By Vatican&lt;/em&gt;&lt;/blockquote&gt;

</content></entry><entry><id>vatican_joy:dark_side_API</id><link rel="alternate" type="text/html" href="https://vatican-blog.cvv.life/dark_side_API?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=vatican_joy"></link><title>Тёмная сторона API</title><published>2026-09-18T10:05:36.013Z</published><updated>2026-09-18T10:05:36.013Z</updated><category term="dev" label="Dev"></category><summary type="html">&lt;img src=&quot;https://img1.teletype.in/files/01/6e/016ea2aa-72cf-471c-a2cf-4d19958edb59.jpeg&quot;&gt;Всё, что ты видишь в браузере — это данные. Вопрос только в том, как их достать.</summary><content type="html">
  &lt;h2 id=&quot;2dNy&quot;&gt;Часть 1: Анатомия данных&lt;/h2&gt;
  &lt;p id=&quot;iAAF&quot;&gt;&lt;em&gt;Всё, что ты видишь в браузере — это данные. Вопрос только в том, как их достать.&lt;/em&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;xhNT&quot;&gt;Сайт в браузере&lt;/p&gt;
    &lt;ul id=&quot;ClcM&quot;&gt;
      &lt;li id=&quot;20dt&quot;&gt;Открытый API (мб будет документация)&lt;/li&gt;
      &lt;li id=&quot;Ni6w&quot;&gt;Скрытый API (документации нету но стучать можно)&lt;/li&gt;
      &lt;li id=&quot;MasQ&quot;&gt;&lt;em&gt;GraphQL endpoint&lt;/em&gt;&lt;/li&gt;
      &lt;li id=&quot;sulH&quot;&gt;&lt;em&gt;WebSocket поток&lt;/em&gt;&lt;/li&gt;
      &lt;li id=&quot;qB0c&quot;&gt;&lt;em&gt;Серверный рендеринг (HTML с данными)&lt;/em&gt;&lt;/li&gt;
      &lt;li id=&quot;yeVV&quot;&gt;&lt;em&gt;Клиентский рендеринг (JS собирает данные)&lt;/em&gt;&lt;/li&gt;
      &lt;li id=&quot;5KC9&quot;&gt;&lt;em&gt;Скрытые поля, комментарии, метаданные&lt;/em&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/section&gt;
  &lt;blockquote id=&quot;TAjH&quot;&gt;&lt;strong&gt;&lt;em&gt;&lt;u&gt;Если данные видны в браузере — их можно достать программно.&lt;/u&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/blockquote&gt;
  &lt;h2 id=&quot;Ut8t&quot;&gt;Часть 2: Уровни доступа к данным&lt;/h2&gt;
  &lt;h3 id=&quot;6e9S&quot;&gt;&lt;em&gt;Уровень 0 — Официальное API&lt;/em&gt;&lt;/h3&gt;
  &lt;blockquote id=&quot;dV37&quot;&gt;Самое простое. Документация открыта, ключ бесплатный.&lt;/blockquote&gt;
  &lt;pre id=&quot;lZlU&quot; data-lang=&quot;python&quot;&gt;import requests
# Пример: публичное API

response = requests.get(&amp;quot;https://api.example.com/v1/data&amp;quot;)
data = response.json()&lt;/pre&gt;
  &lt;p id=&quot;t15K&quot;&gt;&lt;strong&gt;Плюсы:&lt;/strong&gt; Стабильно, легально, документация&lt;br /&gt;&lt;strong&gt;Минусы:&lt;/strong&gt; Rate limits, неполные данные, ключ могут отозвать&lt;/p&gt;
  &lt;h3 id=&quot;wTVY&quot;&gt;Уровень 1 — Скрытый API (Reverse Engineering)&lt;/h3&gt;
  &lt;p id=&quot;vl3c&quot;&gt;&lt;em&gt;Сайты часто имеют внутренние API, которые фронтенд использует для получения данных. Документации нет, но endpoint работает.&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;fLPD&quot;&gt;&lt;strong&gt;Как найти:&lt;/strong&gt;&lt;/p&gt;
  &lt;ol id=&quot;460M&quot;&gt;
    &lt;li id=&quot;DQ6B&quot;&gt;Открой DevTools (F12)&lt;/li&gt;
    &lt;li id=&quot;btoM&quot;&gt;Вкладка Network → XHR/Fetch&lt;/li&gt;
    &lt;li id=&quot;bf3G&quot;&gt;Обнови страницу&lt;/li&gt;
    &lt;li id=&quot;r5yX&quot;&gt;Смотри какие запросы летят&lt;/li&gt;
    &lt;li id=&quot;teu4&quot;&gt;Найди endpoint с нужными данными&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;xaPM&quot;&gt;&lt;/p&gt;
  &lt;blockquote id=&quot;VLOE&quot;&gt;&lt;strong&gt;Пример — что видишь в Network:&lt;br /&gt;GET https://site.com/api/v2/products?page=1&amp;amp;limit=50&lt;/strong&gt;&lt;/blockquote&gt;
  &lt;p id=&quot;cr5e&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;y1Pp&quot;&gt;&lt;strong&gt;Воспроизводим&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;2O5i&quot; data-lang=&quot;python&quot;&gt;import requests

headers = {
    &amp;quot;Authorization&amp;quot;: &amp;quot;Bearer eyJhbGciOiJIUzI1...&amp;quot;,
    &amp;quot;User-Agent&amp;quot;: &amp;quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64)&amp;quot;,
    &amp;quot;Accept&amp;quot;: &amp;quot;application/json&amp;quot;,
    &amp;quot;Referer&amp;quot;: &amp;quot;https://site.com/catalog&amp;quot;
}

response = requests.get(
    &amp;quot;https://site.com/api/v2/products&amp;quot;,
    params={&amp;quot;page&amp;quot;: 1, &amp;quot;limit&amp;quot;: 50},
    headers=headers
)
print(response.json())&lt;/pre&gt;
  &lt;p id=&quot;rX4d&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;x0vv&quot;&gt;&lt;strong&gt;Инструменты для реверса:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;UJ66&quot;&gt;
    &lt;li id=&quot;kjfo&quot;&gt;&lt;strong&gt;DevTools (Network)&lt;/strong&gt; — базовый&lt;/li&gt;
    &lt;li id=&quot;SGLH&quot;&gt;&lt;strong&gt;mitmproxy&lt;/strong&gt; — перехват трафика мобильных приложений&lt;/li&gt;
    &lt;li id=&quot;mGkA&quot;&gt;&lt;strong&gt;Charles Proxy&lt;/strong&gt; — то же, но с GUI&lt;/li&gt;
    &lt;li id=&quot;uzck&quot;&gt;&lt;strong&gt;Postman&lt;/strong&gt; — тестирование найденных endpoints&lt;/li&gt;
    &lt;li id=&quot;Rw3d&quot;&gt;&lt;strong&gt;Frida&lt;/strong&gt; — хук методов в мобильных приложениях&lt;/li&gt;
    &lt;li id=&quot;IbZ1&quot;&gt;&lt;strong&gt;Burp Suite — &lt;/strong&gt;Позволяет перехватывать, анализировать и модифицировать HTTP- и HTTPS-трафик между браузером&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;TAw5&quot;&gt;Уровень 2 — GraphQL Endpoints&lt;/h3&gt;
  &lt;blockquote id=&quot;LKJH&quot;&gt;&lt;em&gt;Многие современные сайты используют GraphQL. Он отдаёт ровно те данные, которые запросишь.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;p id=&quot;nrEd&quot;&gt;&lt;strong&gt;Как обнаружить:&lt;/strong&gt;&lt;/p&gt;
  &lt;ol id=&quot;s1he&quot;&gt;
    &lt;li id=&quot;r7Rz&quot;&gt;В DevTools ищи POST-запросы на /graphql&lt;/li&gt;
    &lt;li id=&quot;5s3u&quot;&gt;Или /api/graphql&lt;/li&gt;
    &lt;li id=&quot;48N5&quot;&gt;Или любые POST с query в body&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;iCtC&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;OfEu&quot;&gt;&lt;strong&gt;Интроспекция — всей схемы:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;4XUC&quot; data-lang=&quot;graphql&quot;&gt;# Запрос всей схемы API
{
  __schema {
    types {
      name
      fields {
        name
        type {
          name
        }
      }
    }
  }
}&lt;/pre&gt;
  &lt;p id=&quot;7R2v&quot;&gt;&lt;strong&gt;Пример запроса данных:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;ozaX&quot; data-lang=&quot;python&quot;&gt;import requests

query = &amp;quot;&amp;quot;&amp;quot;
{
  users(first: 100) {
    id
    username
    email
    posts {
      title
      createdAt
    }
  }
}
&amp;quot;&amp;quot;&amp;quot;

response = requests.post(
    &amp;quot;https://site.com/graphql&amp;quot;,
    json={&amp;quot;query&amp;quot;: query},
    headers={&amp;quot;Content-Type&amp;quot;: &amp;quot;application/json&amp;quot;}
)
print(response.json())&lt;/pre&gt;
  &lt;p id=&quot;H7bc&quot;&gt;&lt;strong&gt;Инструменты:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;ZWR8&quot;&gt;
    &lt;li id=&quot;Cd5c&quot;&gt;&lt;strong&gt;GraphiQL / Altair&lt;/strong&gt; — IDE для GraphQL&lt;/li&gt;
    &lt;li id=&quot;Ey4b&quot;&gt;&lt;strong&gt;graphql-path-enum&lt;/strong&gt; — перебор скрытых полей&lt;/li&gt;
    &lt;li id=&quot;hCP0&quot;&gt;&lt;strong&gt;InQL (Burp extension)&lt;/strong&gt; — автоматическая интроспекция&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;DmHI&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;5uYi&quot;&gt;Уровень 3 — Парсинг HTML&lt;/h3&gt;
  &lt;blockquote id=&quot;uJ2c&quot;&gt;&lt;em&gt;Когда API нет или оно закрыто — парсим то, что видит браузер.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;h4 id=&quot;d9Em&quot;&gt;Базовый — requests + BeautifulSoup&lt;/h4&gt;
  &lt;pre id=&quot;RXvG&quot; data-lang=&quot;python&quot;&gt;import requests
from bs4 import BeautifulSoup

response = requests.get(&amp;quot;https://example.com/products&amp;quot;)
soup = BeautifulSoup(response.text, &amp;quot;html.parser&amp;quot;)

products = soup.find_all(&amp;quot;div&amp;quot;, class_=&amp;quot;product-card&amp;quot;)

for product in products:
    title = product.find(&amp;quot;h3&amp;quot;).text.strip()
    price = product.find(&amp;quot;span&amp;quot;, class_=&amp;quot;price&amp;quot;).text
    link = product.find(&amp;quot;a&amp;quot;)[&amp;quot;href&amp;quot;]
    
    print(f&amp;quot;{title} | {price} | {link}&amp;quot;)&lt;/pre&gt;
  &lt;p id=&quot;rp9o&quot;&gt;&lt;strong&gt;или когда например html динамический&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;hCHV&quot; data-lang=&quot;python&quot;&gt;from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page()
    
    # Перехватываем API-запросы страницы
    responses = []
    page.on(&amp;quot;response&amp;quot;, lambda res: responses.append(res) 
            if &amp;quot;api&amp;quot; in res.url else None)
    
    page.goto(&amp;quot;https://example.com/catalog&amp;quot;)
    page.wait_for_load_state(&amp;quot;networkidle&amp;quot;)
    
    # Данные из перехваченных API-запросов
    for res in responses:
        print(res.url, res.json())
    
    # Или контент из DOM
    content = page.content()
    browser.close()
&lt;/pre&gt;
  &lt;h4 id=&quot;aYBE&quot;&gt;Селекторы — что использовать&lt;/h4&gt;
  &lt;pre id=&quot;VGxd&quot; data-lang=&quot;python&quot;&gt;# CSS селекторы (быстрее, чище)
soup.select(&amp;quot;div.product-card &amp;gt; h3.title&amp;quot;)
soup.select(&amp;quot;a[href*=&amp;#x27;/product/&amp;#x27;]&amp;quot;)
soup.select(&amp;quot;span[data-price]&amp;quot;)

# XPath (мощнее для сложной логики)
soup.xpath(&amp;quot;//div[@class=&amp;#x27;item&amp;#x27;][position() &amp;lt; 10]&amp;quot;)
soup.xpath(&amp;quot;//a[contains(@href, &amp;#x27;product&amp;#x27;)]/@href&amp;quot;)&lt;/pre&gt;
  &lt;p id=&quot;9Gpm&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;om4n&quot;&gt;Уровень 4 — Headless Browser (эмуляция)&lt;/h3&gt;
  &lt;blockquote id=&quot;vDSs&quot;&gt;&lt;em&gt;Когда сайт проверяет JS, куки, поведение — эмулируем реального пользователя.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;h4 id=&quot;xOAR&quot;&gt;Playwright — стандарт&lt;/h4&gt;
  &lt;pre id=&quot;wGfa&quot; data-lang=&quot;python&quot;&gt;from playwright.sync_api import sync_playwright
import time
import random

with sync_playwright() as p:
    browser = p.chromium.launch(
        headless=False,
        args=[
            &amp;quot;--disable-blink-features=AutomationControlled&amp;quot;,
            &amp;quot;--no-sandbox&amp;quot;
        ]
    )
    
    context = browser.new_context(
        viewport={&amp;quot;width&amp;quot;: 1920, &amp;quot;height&amp;quot;: 1080},
        user_agent=&amp;quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36&amp;quot;,
        locale=&amp;quot;ru-RU&amp;quot;,
        timezone_id=&amp;quot;Europe/Moscow&amp;quot;
    )
    
    page = context.new_page()
    
    # Убираем флаг webdriver
    page.add_init_script(&amp;quot;&amp;quot;&amp;quot;
        Object.defineProperty(navigator, &amp;#x27;webdriver&amp;#x27;, {
            get: () =&amp;gt; undefined
        });
    &amp;quot;&amp;quot;&amp;quot;)
    
    page.goto(&amp;quot;https://example.com&amp;quot;)
    
    # Имитируем человека
    time.sleep(random.uniform(1, 3))
    page.mouse.move(random.randint(100, 800), random.randint(100, 600))
    
    # Скроллим как человек
    page.evaluate(&amp;quot;&amp;quot;&amp;quot;
        async () =&amp;gt; {
            for (let i = 0; i &amp;lt; document.body.scrollHeight; i += 100) {
                window.scrollTo(0, i);
                await new Promise(r =&amp;gt; setTimeout(r, 100));
            }
        }
    &amp;quot;&amp;quot;&amp;quot;)
    
    # Забираем контент
    html = page.content()
    
    browser.close()&lt;/pre&gt;
  &lt;h4 id=&quot;KV3h&quot;&gt;Анти-детект: что проверяют сайты (зависит от фантазии создателя)&lt;/h4&gt;
  &lt;p id=&quot;jCd5&quot;&gt;Основное&lt;/p&gt;
  &lt;figure id=&quot;erw2&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/4e/73/4e73ec50-6381-4ab8-b555-e71c7e38d889.png&quot; width=&quot;568&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;wF0M&quot;&gt;Уровень 5 — Мобильные API&lt;/h3&gt;
  &lt;blockquote id=&quot;t3ii&quot;&gt;&lt;em&gt;Приложения часто используют API, недоступные через веб. Данные там чище и полнее.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;p id=&quot;rOhj&quot;&gt;&lt;strong&gt;Инструменты:&lt;/strong&gt;&lt;/p&gt;
  &lt;ul id=&quot;UzEO&quot;&gt;
    &lt;li id=&quot;56Bc&quot;&gt;mitmproxy — перехват HTTPS трафика&lt;/li&gt;
    &lt;li id=&quot;vB4u&quot;&gt;Frida — инъекция кода в приложение&lt;/li&gt;
    &lt;li id=&quot;Ghsm&quot;&gt;Charles Proxy — GUI-альтернатива&lt;/li&gt;
    &lt;li id=&quot;NHWg&quot;&gt;jadx — декомпиляция APK&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;fb7P&quot;&gt;&lt;strong&gt;Процесс:&lt;/strong&gt;&lt;/p&gt;
  &lt;ol id=&quot;eIui&quot;&gt;
    &lt;li id=&quot;tdC5&quot;&gt;Скачай APK (apkpure, apkmirror)&lt;/li&gt;
    &lt;li id=&quot;1WY7&quot;&gt;Декомпилируй (jadx)&lt;/li&gt;
    &lt;li id=&quot;YK5I&quot;&gt;Ищи строки с &amp;quot;api&amp;quot;, &amp;quot;http&amp;quot;, &amp;quot;endpoint&amp;quot;&lt;/li&gt;
    &lt;li id=&quot;qKnM&quot;&gt;Найди базовый URL и параметры&lt;/li&gt;
    &lt;li id=&quot;BXQf&quot;&gt;Перехвати трафик через mitmproxy&lt;/li&gt;
    &lt;li id=&quot;wfFf&quot;&gt;Воспроизведи запрос в Python&lt;/li&gt;
  &lt;/ol&gt;
  &lt;h2 id=&quot;31ho&quot;&gt;&lt;strong&gt;Часть 3: Защита и обход&lt;/strong&gt;&lt;/h2&gt;
  &lt;h3 id=&quot;lkcQ&quot;&gt;Rate Limiting&lt;/h3&gt;
  &lt;p id=&quot;E9wD&quot;&gt;Сайт ограничивает частоту запросов. Виды:&lt;/p&gt;
  &lt;ul id=&quot;Yo3o&quot;&gt;
    &lt;li id=&quot;NSGv&quot;&gt;IP-based → ротация прокси&lt;/li&gt;
    &lt;li id=&quot;19sT&quot;&gt;API Key-based → ротация ключей&lt;/li&gt;
    &lt;li id=&quot;PjYU&quot;&gt;Session-based → ротация сессий&lt;/li&gt;
    &lt;li id=&quot;GOgj&quot;&gt;Cookie-based → сброс куки&lt;/li&gt;
    &lt;li id=&quot;XyCR&quot;&gt;Device fingerprint → подмена отпечатка&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;0YE5&quot;&gt;&lt;strong&gt;Подход:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;nLU3&quot; data-lang=&quot;python&quot;&gt;import time
import random
from itertools import cycle

class RateLimiter:
    def __init__(self, min_delay=1.0, max_delay=3.0):
        self.min_delay = min_delay
        self.max_delay = max_delay
    
    def wait(self):
        delay = random.uniform(self.min_delay, self.max_delay)
        time.sleep(delay)

# Использование прокси
proxies = cycle([
    &amp;quot;http://proxy1:port&amp;quot;,
    &amp;quot;http://proxy2:port&amp;quot;,
    &amp;quot;http://proxy3:port&amp;quot;,
])

limiter = RateLimiter(1, 3)

for url in urls:
    proxy = next(proxies)
    limiter.wait()
    
    response = requests.get(url, proxiДл&amp;quot;: proxy})
    # Дальше ваша логика...&lt;/pre&gt;
  &lt;h3 id=&quot;3IjE&quot;&gt;Теперь главный враг автоматизации CAPTCHA&lt;/h3&gt;
  &lt;blockquote id=&quot;Gl6m&quot;&gt;&lt;em&gt;CAPTCHA можно проходить самыми разными способами от солвером до обучения локальных ИИ-моделей&lt;/em&gt;&lt;/blockquote&gt;
  &lt;figure id=&quot;iVzH&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/a1/8f/a18f63fb-34f4-4190-8108-80aa66a9d61f.png&quot; width=&quot;560&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Eu6N&quot;&gt;&lt;strong&gt;Интеграция с сервисом решения:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;F9mf&quot; data-lang=&quot;python&quot;&gt;import requests
import time

API_KEY = &amp;quot;your_2captcha_key&amp;quot;

def solve_recaptcha(site_key, page_url):
    # Отправляем задачу
    response = requests.post(&amp;quot;https://api.2captcha.com/in.php&amp;quot;, data={
        &amp;quot;key&amp;quot;: API_KEY,
        &amp;quot;method&amp;quot;: &amp;quot;userrecaptcha&amp;quot;,
        &amp;quot;googlekey&amp;quot;: site_key,
        &amp;quot;pageurl&amp;quot;: page_url,
        &amp;quot;json&amp;quot;: 1
    })
    task_id = response.json()[&amp;quot;request&amp;quot;]
    
    # Ждём решение
    for _ in range(30):
        time.sleep(5)
        result = requests.get(&amp;quot;https://api.2captcha.com/res.php&amp;quot;, params={
            &amp;quot;key&amp;quot;: API_KEY,
            &amp;quot;action&amp;quot;: &amp;quot;get&amp;quot;,
            &amp;quot;id&amp;quot;: task_id,
            &amp;quot;json&amp;quot;: 1
        })
        if result.json()[&amp;quot;status&amp;quot;] == 1:
            return result.json()[&amp;quot;request&amp;quot;]
    
    return None&lt;/pre&gt;
  &lt;h2 id=&quot;7qzo&quot;&gt;Часть 4: Инфраструктура&lt;/h2&gt;
  &lt;h3 id=&quot;7ul7&quot;&gt;Прокси — виды и стратегии&lt;/h3&gt;
  &lt;p id=&quot;jMAn&quot;&gt;1. HTTP прокси → обычные, для http запросов&lt;br /&gt;2. SOCKS5 прокси → любой трафик&lt;br /&gt;3. Резидентные → IP реальных людей (дорого, надёжно)&lt;br /&gt;4. Датацентровые → IP серверов (дёшево, палевно)&lt;br /&gt;5. Мобильные → IP мобильных операторов (самые надёжные)&lt;br /&gt;6. Ротация → новый IP на каждый запрос&lt;br /&gt;7. Стик → IP привязан к сессии&lt;/p&gt;
  &lt;p id=&quot;4H8t&quot;&gt;&lt;strong&gt;Правильная ротация:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;ylJz&quot; data-lang=&quot;python&quot;&gt;import aiohttp
import asyncio
from itertools import cycle

class ProxyPool:
    def __init__(self, proxy_list):
        self.proxies = cycle(proxy_list)
        self.failed = set()
    
    def get_proxy(self):
        for _ in range(len(self.proxies)):
            proxy = next(self.proxies)
            if proxy not in self.failed:
                return proxy
        # Все прокси умерли — сбрасываем
        self.failed.clear()
        return next(self.proxies)
    
    def mark_failed(self, proxy):
        self.failed.add(proxy)

async def fetch(session, url, proxy):
    try:
        async with session.get(url, proxy=proxy, timeout=10) as resp:
            return await resp.json()
    except:
        pool.mark_failed(proxy)
        return None

async def main(urls):
    pool = ProxyPool([
        &amp;quot;http://proxy1:8080&amp;quot;,
        &amp;quot;http://proxy2:8080&amp;quot;,
    ])
    
    connector = aiohttp.TCPConnector(limit=20)
    async with aiohttp.ClientSession(connector=connector) as session:
        tasks = []
        for url in urls:
            proxy = pool.get_proxy()
            tasks.append(fetch(session, url, proxy))
        
        results = await asyncio.gather(*tasks)
    return [r for r in results if r is not None]&lt;/pre&gt;
  &lt;h2 id=&quot;Pt2p&quot;&gt;Часть 5: Практические схемы&lt;/h2&gt;
  &lt;h3 id=&quot;wCHs&quot;&gt;Схема 1: Сбор данных с каталога&lt;/h3&gt;
  &lt;pre id=&quot;vBbj&quot; data-lang=&quot;python&quot;&gt;from playwright.sync_api import sync_playwright
from bs4 import BeautifulSoup
import json
import time
import random

class CatalogParser:
    def __init__(self, base_url):
        self.base_url = base_url
        self.results = []
    
    def parse_page(self, page, url):
        page.goto(url)
        page.wait_for_load_state(&amp;quot;networkidle&amp;quot;)
        
        # Ждём появления товаров
        page.wait_for_selector(&amp;quot;.product-card&amp;quot;, timeout=10000)
        
        html = page.content()
        soup = BeautifulSoup(html, &amp;quot;html.parser&amp;quot;)
        
        products = soup.select(&amp;quot;.product-card&amp;quot;)
        
        for product in products:
            self.results.append({
                &amp;quot;title&amp;quot;: product.select_one(&amp;quot;.title&amp;quot;)?.text.strip(),
                &amp;quot;price&amp;quot;: product.select_one(&amp;quot;.price&amp;quot;)?.text.strip(),
                &amp;quot;url&amp;quot;: product.select_one(&amp;quot;a&amp;quot;)?.get(&amp;quot;href&amp;quot;),
                &amp;quot;parsed_at&amp;quot;: time.strftime(&amp;quot;%Y-%m-%d %H:%M&amp;quot;)
            })
        
        # Случайная задержка
        time.sleep(random.uniform(2, 5))
    
    def run(self, pages=10):
        with sync_playwright() as p:
            browser = p.chromium.launch(headless=True)
            page = browser.new_page()
            
            for i in range(1, pages + 1):
                url = f&amp;quot;{self.base_url}?page={i}&amp;quot;
                print(f&amp;quot;Страница {i}/{pages}&amp;quot;)
                self.parse_page(page, url)
            
            browser.close()
        
        return self.results
    
    def save(self, filename=&amp;quot;data.json&amp;quot;):
        with open(filename, &amp;quot;w&amp;quot;, encoding=&amp;quot;utf-8&amp;quot;) as f:
            json.dump(self.results, f, ensure_ascii=False, indent=2)

# Использование
parser = CatalogParser(&amp;quot;https://example.com/catalog&amp;quot;)
data = parser.run(pages=50)
parser.save()&lt;/pre&gt;
  &lt;h3 id=&quot;KwuT&quot;&gt;&lt;br /&gt;Схема 2: Мониторинг изменений&lt;/h3&gt;
  &lt;pre id=&quot;JUvg&quot; data-lang=&quot;python&quot;&gt;import hashlib
import json
from datetime import datetime
from pathlib import Path

class ChangeMonitor:
    def __init__(self, state_file=&amp;quot;state.json&amp;quot;):
        self.state_file = Path(state_file)
        self.state = self.load_state()
    
    def load_state(self):
        if self.state_file.exists():
            return json.loads(self.state_file.read_text())
        return {}
    
    def save_state(self):
        self.state_file.write_text(
            json.dumps(self.state, ensure_ascii=False, indent=2)
        )
    
    def get_hash(self, data):
        return hashlib.md5(json.dumps(data, sort_keys=True).encode()).hexdigest()
    
    def check(self, key, new_data):
        new_hash = self.get_hash(new_data)
        old_hash = self.state.get(key, {}).get(&amp;quot;hash&amp;quot;)
        
        if old_hash is None:
            self.state[key] = {&amp;quot;hash&amp;quot;: new_hash, &amp;quot;data&amp;quot;: new_data, &amp;quot;updated&amp;quot;: datetime.now().isoformat()}
            return {&amp;quot;status&amp;quot;: &amp;quot;new&amp;quot;, &amp;quot;data&amp;quot;: new_data}
        
        elif old_hash != new_hash:
            old = self.state[key][&amp;quot;data&amp;quot;]
            self.state[key] = {&amp;quot;hash&amp;quot;: new_hash, &amp;quot;data&amp;quot;: new_data, &amp;quot;updated&amp;quot;: datetime.now().isoformat()}
            return {&amp;quot;status&amp;quot;: &amp;quot;changed&amp;quot;, &amp;quot;old&amp;quot;: old, &amp;quot;new&amp;quot;: new_data}
        
        return {&amp;quot;status&amp;quot;: &amp;quot;unchanged&amp;quot;}&lt;/pre&gt;
  &lt;p id=&quot;kKWH&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;Ox4c&quot;&gt;Схема 3: Распределённый парсер&lt;/h3&gt;
  &lt;pre id=&quot;7RC2&quot; data-lang=&quot;python&quot;&gt;import asyncio
import aiohttp
from dataclasses import dataclass, field
from typing import Optional
import json

@dataclass
class Task:
    url: str
    retries: int = 0
    max_retries: int = 3
    proxy: Optional[str] = None

@dataclass
class Worker:
    id: int
    session: aiohttp.ClientSession
    queue: asyncio.Queue
    results: list = field(default_factory=list)

class DistributedParser:
    def __init__(self, urls, num_workers=5, proxy_list=None):
        self.tasks = [Task(url=url) for url in urls]
        self.num_workers = num_workers
        self.proxy_list = proxy_list or []
        self.results = []
    
    async def worker(self, wid, queue, session):
        while True:
            try:
                task = await asyncio.wait_for(queue.get(), timeout=5)
            except asyncio.TimeoutError:
                break
            
            try:
                proxy = None
                if self.proxy_list:
                    proxy = self.proxy_list[task.retries % len(self.proxy_list)]
                
                async with session.get(
                    task.url, 
                    proxy=proxy,
                    timeout=aiohttp.ClientTimeout(total=15)
                ) as resp:
                    if resp.status == 200:
                        data = await resp.text()
                        self.results.append({
                            &amp;quot;url&amp;quot;: task.url,
                            &amp;quot;data&amp;quot;: data,
                            &amp;quot;worker&amp;quot;: wid
                        })
                        print(f&amp;quot;[Worker {wid}] OK: {task.url}&amp;quot;)
                    else:
                        raise Exception(f&amp;quot;Status {resp.status}&amp;quot;)
                        
            except Exception as e:
                task.retries += 1
                if task.retries &amp;lt; task.max_retries:
                    await queue.put(task)
                else:
                    print(f&amp;quot;[Worker {wid}] FAILED: {task.url} - {e}&amp;quot;)
            
            finally:
                queue.task_done()
    
    async def run(self):
        queue = asyncio.Queue()
        for task in self.tasks:
            queue.put(task)
        
        connector = aiohttp.TCPConnector(limit=self.num_workers * 2)
        
        async with aiohttp.ClientSession(connector=connector) as session:
            workers = [
                asyncio.create_task(self.worker(i, queue, session))
                for i in range(self.num_workers)
            ]
            await queue.join()
            for w in workers:
                w.cancel()
        
        return self.results

# Использование
urls = [f&amp;quot;https://example.com/item/{i}&amp;quot; for i in range(1000)]
parser = DistributedParser(
    urls=urls, 
    num_workers=10,
    proxy_list=[&amp;quot;http://p1:8080&amp;quot;, &amp;quot;http://p2:8080&amp;quot;, &amp;quot;http://p3:8080&amp;quot;]
)
results = asyncio.run(parser.run())&lt;/pre&gt;
  &lt;p id=&quot;ocw4&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;TLlR&quot;&gt;Часть 6: Стек инструментов&lt;/h2&gt;
  &lt;h3 id=&quot;GVK4&quot;&gt;Обязательный минимум&lt;/h3&gt;
  &lt;ul id=&quot;h0lH&quot;&gt;
    &lt;li id=&quot;lRso&quot;&gt;requests — базовые HTTP запросы&lt;/li&gt;
    &lt;li id=&quot;TFKA&quot;&gt;httpx — async HTTP, HTTP/2&lt;/li&gt;
    &lt;li id=&quot;bU0M&quot;&gt;beautifulsoup4 — парсинг HTML&lt;/li&gt;
    &lt;li id=&quot;0Ioc&quot;&gt;lxml — быстрый парсер&lt;/li&gt;
    &lt;li id=&quot;6gg4&quot;&gt;playwright — headless браузер&lt;/li&gt;
    &lt;li id=&quot;Nx7q&quot;&gt;scrapy — фреймворк для масштабных проектов&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;sjxN&quot;&gt;Стань лучше:&lt;/h3&gt;
  &lt;ul id=&quot;a3A4&quot;&gt;
    &lt;li id=&quot;sXnk&quot;&gt;curl_cffi — имитация TLS fingerprint браузера&lt;/li&gt;
    &lt;li id=&quot;YMnl&quot;&gt;tls_client — обход Cloudflare через TLS&lt;/li&gt;
    &lt;li id=&quot;uGab&quot;&gt;camoufox — анти-детект Firefox&lt;/li&gt;
    &lt;li id=&quot;noed&quot;&gt;undetected-chromedriver — анти-детект Chrome&lt;/li&gt;
    &lt;li id=&quot;d8dJ&quot;&gt;aiohttp — async для скорости&lt;/li&gt;
    &lt;li id=&quot;Ou9y&quot;&gt;celery — очереди задач&lt;/li&gt;
    &lt;li id=&quot;I0JW&quot;&gt;redis — кэш и состояние&lt;/li&gt;
    &lt;li id=&quot;gL8X&quot;&gt;postgresql — хранилище данных&lt;/li&gt;
    &lt;li id=&quot;49kW&quot;&gt;docker — изоляция окружения (на уровне базовый минимум)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;ObOv&quot;&gt;Инфраструктура (Может не подойти)&lt;/h3&gt;
  &lt;p id=&quot;YdrV&quot;&gt;Прокси-провайдеры:&lt;/p&gt;
  &lt;ul id=&quot;dXNG&quot;&gt;
    &lt;li id=&quot;0moO&quot;&gt;Bright Data (резидентные)&lt;/li&gt;
    &lt;li id=&quot;6xwK&quot;&gt;SmartProxy (резидентные)&lt;/li&gt;
    &lt;li id=&quot;ghsl&quot;&gt;Proxy-Seller (датацентровые)&lt;/li&gt;
    &lt;li id=&quot;tC7c&quot;&gt;IPRoyal (мобильные)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;2c5N&quot;&gt;Решение капчи:&lt;/p&gt;
  &lt;ul id=&quot;CHP5&quot;&gt;
    &lt;li id=&quot;cVeA&quot;&gt;2Captcha&lt;/li&gt;
    &lt;li id=&quot;laYk&quot;&gt;Anti-Captcha&lt;/li&gt;
    &lt;li id=&quot;aEB2&quot;&gt;CapSolver&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;plNt&quot;&gt;Мониторинг:&lt;/p&gt;
  &lt;ul id=&quot;To3q&quot;&gt;
    &lt;li id=&quot;9NZM&quot;&gt;Grafana + Prometheus&lt;/li&gt;
    &lt;li id=&quot;y1ji&quot;&gt;Telegram-бот алерты&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;l4Hw&quot;&gt;Часть 7: Как НЕ надо&lt;/h2&gt;
  &lt;ul id=&quot;Qhwq&quot;&gt;
    &lt;li id=&quot;wPeJ&quot;&gt;ДДОСить сайт парсером (1000 req/sec)&lt;/li&gt;
    &lt;li id=&quot;H4ih&quot;&gt;Игнорировать ошибки и повторять бесконечно&lt;/li&gt;
    &lt;li id=&quot;rtx2&quot;&gt;Хранить данные без структуры&lt;/li&gt;
    &lt;li id=&quot;8lxb&quot;&gt;Не логировать — не понимаешь что происходит&lt;/li&gt;
    &lt;li id=&quot;ZLtW&quot;&gt;Хардкодить селекторы без фоллбеков&lt;/li&gt;
    &lt;li id=&quot;M66j&quot;&gt;Не обрабатывать изменение вёрстк&lt;/li&gt;
    &lt;li id=&quot;F0HI&quot;&gt;Собирать всё подряд без цели&lt;/li&gt;
    &lt;li id=&quot;rZ9Y&quot;&gt;Не кэшировать — один и тот же запрос 50 раз&lt;/li&gt;
    &lt;li id=&quot;NCWG&quot;&gt;Писать всё в один файл без модульности&lt;/li&gt;
    &lt;li id=&quot;X0Ml&quot;&gt;Игнорировать robots.txt и уважение к серверу&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;ZfAs&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;kx2b&quot;&gt;&lt;/p&gt;
  &lt;blockquote id=&quot;QOtz&quot;&gt;&lt;em&gt;На этом все с вами был Vatican.&lt;/em&gt;&lt;/blockquote&gt;

</content></entry></feed>