[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-post-ru-geo-targeted-serp-scraping-best-practices":3},{"success":4,"payload":5,"related":60,"errors":127},true,{"id":6,"slug":7,"title":8,"excerpt":9,"body_html":10,"meta_title":11,"meta_description":12,"canonical_url":13,"canonical_override":14,"og_title":11,"og_description":15,"og_image_url":16,"faq_json":17,"key_takeaways":14,"allow_index":27,"noindex_google_only":27,"allow_follow":4,"published_at":28,"updated_at":28,"content_updated_at":29,"featured_image_url":30,"featured_image_alt":31,"card_image_url":32,"reading_time_minutes":33,"author":34,"categories":38,"tags":45,"alternates":46,"locale_paths":48,"views":59},198,"geo-targeted-serp-scraping-best-practices","Лучшие практики гео-таргетированного скрейпинга SERP: uule, gl, hl и прокси","Практическое руководство для SEO-инженеров: как собирать локализованные SERP Google с точностью до города, конструировать параметр uule, синхронизировать gl\u002Fhl с IP-географией и ротировать резидентные прокси через ProxyHat.","\u003Cp>Лучшие практики гео-таргетированного скрейпинга SERP начинаются с одного простого факта: один и тот же поисковый запрос в Google возвращает разные результаты в зависимости от того, откуда он отправлен. Запрос «pizza near me» из Нью-Йорка и из Берлина даст принципиально разные органические результаты, локальные пакеты (Local Pack) и карты. Если вы строите систему rank-tracking для клиентов в нескольких городах, таргетинга на уровне страны недостаточно — вам нужна точность до города, а иногда и до района.\u003C\u002Fp>\n\n\u003Ch2>Почему один запрос даёт разные результаты по локации\u003C\u002Fh2>\n\n\u003Cp>Google определяет релевантность результатов на основе множества сигналов, среди которых геолокация пользователя — один из ключевых. Согласно документации Google Search, поисковая система учитывает IP-адрес, историю местоположений, явные параметры URL и настройки аккаунта. Для SEO-инженеров это означает: нельзя собрать «каноничный» SERP без явного указания локации.\u003C\u002Fp>\n\n\u003Cp>Таргетинг только на уровне страны (через параметр \u003Ccode>gl=us\u003C\u002Fcode>) скрывает критические различия. Запрос «plumber» в Чикаго и в Майами покажет разных локальных подрядчиков, разные Local Pack и даже разные органические результаты, потому что Google применяет \u003Cstrong>локальный алгоритм\u003C\u002Fstrong> даже для запросов без явного гео-модификатора. По данным \u003Ca href=\"https:\u002F\u002Fwww.brightlocal.com\u002Fresearch\u002Flocal-consumer-review-survey\u002F\" rel=\"noopener noreferrer\">BrightLocal\u003C\u002Fa>, 76% пользователей, ищущих локальный бизнес, просматривают результаты с привязкой к городу — это означает, что ваши клиенты видят именно локальный SERP, а не национальный.\u003C\u002Fp>\n\n\u003Ch3>Уровни гео-точности\u003C\u002Fh3>\n\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\u003Cth>Уровень\u003C\u002Fth>\u003Cth>Параметр\u003C\u002Fth>\u003Cth>Точность\u003C\u002Fth>\u003Cth>Когда использовать\u003C\u002Fth>\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\u003Ctd>Страна\u003C\u002Ftd>\u003Ctd>\u003Ccode>gl\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Национальный SERP\u003C\u002Ftd>\u003Ctd>Бренд-трекинг, общий рейтинг\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Язык интерфейса\u003C\u002Ftd>\u003Ctd>\u003Ccode>hl\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Текст интерфейса\u003C\u002Ftd>\u003Ctd>Мультиязычные рынки (Канада, Швейцария)\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Домен Google\u003C\u002Ftd>\u003Ctd>\u003Ccode>google_domain\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Регональный домен\u003C\u002Ftd>\u003Ctd>google.de, google.co.jp, google.com.br\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Город\u002Fрайон\u003C\u002Ftd>\u003Ctd>\u003Ccode>uule\u003C\u002Fcode>\u003C\u002Ftd>\u003Ctd>Точный город\u003C\u002Ftd>\u003Ctd>Local SEO, rank-tracking по городам\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\n\u003Ch2>Параметры локализации SERP: gl, hl, google_domain, lr, uule, pws\u003C\u002Fh2>\n\n\u003Cp>Google принимает несколько параметров URL для управления локализацией. Вот полный набор, который нужно использовать в продакшене:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>\u003Cstrong>\u003Ccode>gl\u003C\u002Fcode>\u003C\u002Fstrong> — код страны (ISO 3166-1 alpha-2), например \u003Ccode>gl=us\u003C\u002Fcode>, \u003Ccode>gl=de\u003C\u002Fcode>, \u003Ccode>gl=jp\u003C\u002Fcode>. Влияет на национальную версию SERP.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>\u003Ccode>hl\u003C\u002Fcode>\u003C\u002Fstrong> — язык интерфейса, например \u003Ccode>hl=en\u003C\u002Fcode>, \u003Ccode>hl=de\u003C\u002Fcode>, \u003Ccode>hl=ja\u003C\u002Fcode>. Не путать с языком результатов — это язык кнопок и подсказок.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>\u003Ccode>google_domain\u003C\u002Fcode>\u003C\u002Fstrong> — домен поисковика, например \u003Ccode>google.com\u003C\u002Fcode>, \u003Ccode>google.de\u003C\u002Fcode>, \u003Ccode>google.co.jp\u003C\u002Fcode>. Должен соответствовать \u003Ccode>gl\u003C\u002Fcode>.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>\u003Ccode>lr\u003C\u002Fcode>\u003C\u002Fstrong> — ограничение языка результатов (lang_en, lang_de, lang_ja). Полезно для мультиязычных стран.\u003C\u002Fli>\n\u003Cli>\u003Ccode>uule\u003C\u002Fcode> — закодированная каноническая локация (город\u002Fрайон). Самый мощный параметр для локального SEO.\u003C\u002Fli>\n\u003Cli>\u003Ccode>pws=0\u003C\u002Fcode> — отключает персонализацию. Критично для получения воспроизводимого базового SERP.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Ch3>Конструкция параметра uule\u003C\u002Fh3>\n\n\u003Cp>Параметр \u003Ccode>uule\u003C\u002Fcode> (User-Location Lat-Enc) — это base64-кодированная строка с каноническим названием места. Формат строго фиксирован:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>uule = &quot;w+CAIQICI&quot; + base64(canonical_place_name)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>Где \u003Ccode>w+CAIQICI\u003C\u002Fcode> — фиксированный префикс (8 символов), за которым следует base64-представление канонического названия города в формате Google. Например, для Нью-Йорка каноническое имя — \u003Ccode>Brooklyn, New York, NY\u003C\u002Fcode>, для Берлина — \u003Ccode>Berlin, Germany\u003C\u002Fcode>. Длина base64-строки добавляется как однобайтовый символ перед base64-полезной нагрузкой.\u003C\u002Fp>\n\n\u003Cp>Вот Python-функция для генерации uule:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>import base64\n\ndef build_uule(place_name: str) -&gt; str:\n    &quot;&quot;&quot;Конструирует параметр uule для Google SERP.\n    \n    Args:\n        place_name: Каноническое название места,\n                    например &apos;Brooklyn, New York, NY&apos; или &apos;Berlin, Germany&apos;.\n    Returns:\n        Строка uule, готовая для URL-параметра.\n    &quot;&quot;&quot;\n    prefix = &quot;w+CAIQICI&quot;\n    encoded = base64.b64encode(place_name.encode(&quot;utf-8&quot;)).decode(&quot;ascii&quot;)\n    # Длина base64-строки как однобайтовый символ\n    length_byte = chr(len(encoded))\n    return prefix + length_byte + encoded\n\n# Примеры\nuule_nyc = build_uule(&quot;Brooklyn, New York, NY&quot;)\nuule_berlin = build_uule(&quot;Berlin, Germany&quot;)\nuule_tokyo = build_uule(&quot;Tokyo, Tokyo, Japan&quot;)\n\nprint(f&quot;NYC:  {uule_nyc}&quot;)\nprint(f&quot;Berlin: {uule_berlin}&quot;)\nprint(f&quot;Tokyo: {uule_tokyo}&quot;)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>Всегда добавляйте \u003Ccode>pws=0\u003C\u002Fcode> к запросу, чтобы отключить персонализацию на основе истории поиска. Без этого параметра результаты будут непредсказуемо варьироваться между запусками.\u003C\u002Fp>\n\n\u003Ch2>Согласованность параметров и IP-географии\u003C\u002Fh2>\n\n\u003Cp>Критическое правило, которое часто упускают: Google кросс-проверяет параметры локализации с IP-адресом запроса. Если вы отправляете \u003Ccode>gl=us&uule=...New York\u003C\u002Fcode> с IP-адреса из Франкфурта, Google может:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>Проигнорировать \u003Ccode>uule\u003C\u002Fcode> и показать немецкие результаты.\u003C\u002Fli>\n\u003Cli>Показать смешанный SERP с элементами обеих локаций.\u003C\u002Fli>\n\u003Cli>Пометить запрос как подозрительный и вернуть CAPTCHA.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>Поэтому запросы должны маршрутизироваться через резидентные прокси из той же локации, что и целевые параметры. ProxyHat поддерживает таргетинг по стране и городу через имя пользователя:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode># Резидентный прокси для США, Нью-Йорк\nhttp:\u002F\u002Fuser-country-US-region-new_york-city-new_york_city:pass@gate.proxyhat.com:8080\n\n# Резидентный прокси для Германии, Берлин  \nhttp:\u002F\u002Fuser-country-DE-region-state_of_berlin-city-berlin:pass@gate.proxyhat.com:8080\n\n# Резидентный прокси для Японии, Токио\nhttp:\u002F\u002Fuser-country-JP-region-tokyo-city-tokyo:pass@gate.proxyhat.com:8080\n\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>Подробности по доступным локациям — на странице \u003Ca href=\"\u002Fru\u002Flocations\">локаций ProxyHat\u003C\u002Fa>.\u003C\u002Fp>\n\n\u003Ch2>Пример 1: Сбор SERP с uule и ротацией резидентных IP\u003C\u002Fh2>\n\n\u003Cp>Ниже — полный пример на Python с использованием \u003Ccode>curl_cffi\u003C\u002Fcode> для имперсонализации TLS-отпечатка Chrome и ProxyHat-прокси для гео-таргетинга:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>import base64\nimport time\nimport logging\nfrom curl_cffi import requests as cffi_requests\nfrom urllib.parse import urlencode, quote_plus\n\nlogging.basicConfig(level=logging.INFO, format=&quot;%(asctime)s %(levelname)s %(message)s&quot;)\nlogger = logging.getLogger(&quot;serp_scraper&quot;)\n\n# --- Конфигурация локаций ---\nLOCALES = [\n    {\n        &quot;label&quot;: &quot;NYC&quot;,\n        &quot;gl&quot;: &quot;us&quot;, &quot;hl&quot;: &quot;en&quot;, &quot;google_domain&quot;: &quot;google.com&quot;,\n        &quot;uule_place&quot;: &quot;Brooklyn, New York, NY&quot;,\n        &quot;proxy_user&quot;: &quot;user-country-US-region-new_york-city-new_york_city&quot;,\n        &quot;proxy_pass&quot;: &quot;YOUR_PASSWORD&quot;,\n    },\n    {\n        &quot;label&quot;: &quot;Berlin&quot;,\n        &quot;gl&quot;: &quot;de&quot;, &quot;hl&quot;: &quot;de&quot;, &quot;google_domain&quot;: &quot;google.de&quot;,\n        &quot;uule_place&quot;: &quot;Berlin, Germany&quot;,\n        &quot;proxy_user&quot;: &quot;user-country-DE-region-state_of_berlin-city-berlin&quot;,\n        &quot;proxy_pass&quot;: &quot;YOUR_PASSWORD&quot;,\n    },\n    {\n        &quot;label&quot;: &quot;Tokyo&quot;,\n        &quot;gl&quot;: &quot;jp&quot;, &quot;hl&quot;: &quot;ja&quot;, &quot;google_domain&quot;: &quot;google.co.jp&quot;,\n        &quot;uule_place&quot;: &quot;Tokyo, Tokyo, Japan&quot;,\n        &quot;proxy_user&quot;: &quot;user-country-JP-region-tokyo-city-tokyo&quot;,\n        &quot;proxy_pass&quot;: &quot;YOUR_PASSWORD&quot;,\n    },\n]\n\nPROXY_GATEWAY = &quot;gate.proxyhat.com&quot;\nPROXY_PORT = 8080\n\n\ndef build_uule(place_name: str) -&gt; str:\n    &quot;&quot;&quot;Конструирует uule: фиксированный префикс + length byte + base64.&quot;&quot;&quot;\n    prefix = &quot;w+CAIQICI&quot;\n    encoded = base64.b64encode(place_name.encode(&quot;utf-8&quot;)).decode(&quot;ascii&quot;)\n    length_byte = chr(len(encoded))\n    return prefix + length_byte + encoded\n\n\ndef build_serp_url(query: str, locale: dict) -&gt; str:\n    &quot;&quot;&quot;Собирает URL Google SERP с параметрами локализации.&quot;&quot;&quot;\n    uule = build_uule(locale[&quot;uule_place&quot;])\n    params = {\n        &quot;q&quot;: query,\n        &quot;gl&quot;: locale[&quot;gl&quot;],\n        &quot;hl&quot;: locale[&quot;hl&quot;],\n        &quot;google_domain&quot;: locale[&quot;google_domain&quot;],\n        &quot;uule&quot;: uule,\n        &quot;pws&quot;: &quot;0&quot;,\n        &quot;num&quot;: &quot;20&quot;,\n        &quot;output&quot;: &quot;serp&quot;,\n    }\n    base = f&quot;https:\u002F\u002Fwww.{locale[&apos;google_domain&apos;]}\u002Fsearch&quot;\n    return f&quot;{base}?{urlencode(params)}&quot;\n\n\ndef fetch_serp(query: str, locale: dict) -&gt; str:\n    &quot;&quot;&quot;Отправляет запрос SERP через резидентный прокси ProxyHat.\n    Использует curl_cffi для имперсонализации TLS-отпечатка Chrome.\n    &quot;&quot;&quot;\n    proxy_url = (\n        f&quot;http:\u002F\u002F{locale[&apos;proxy_user&apos;]}:{locale[&apos;proxy_pass&apos;]}&quot;\n        f&quot;@{PROXY_GATEWAY}:{PROXY_PORT}&quot;\n    )\n    serp_url = build_serp_url(query, locale)\n\n    logger.info(f&quot;[{locale[&apos;label&apos;]}] Fetching: {query}&quot;)\n\n    try:\n        response = cffi_requests.get(\n            serp_url,\n            proxies={&quot;http&quot;: proxy_url, &quot;https&quot;: proxy_url},\n            impersonate=&quot;chrome120&quot;,\n            timeout=30,\n            allow_redirects=True,\n        )\n        response.raise_for_status()\n        logger.info(f&quot;[{locale[&apos;label&apos;]}] Status: {response.status_code}, len={len(response.text)}&quot;)\n        return response.text\n    except Exception as e:\n        logger.error(f&quot;[{locale[&apos;label&apos;]}] Error: {e}&quot;)\n        raise\n\n\n# --- Запуск ---\nif __name__ == &quot;__main__&quot;:\n    query = &quot;best coffee shop&quot;\n    for locale in LOCALES:\n        html = fetch_serp(query, locale)\n        # Сохраняем для парсинга\n        filename = f&quot;serp_{locale[&apos;label&apos;]}_{int(time.time())}.html&quot;\n        with open(filename, &quot;w&quot;, encoding=&quot;utf-8&quot;) as f:\n            f.write(html)\n        logger.info(f&quot;Saved: {filename}&quot;)\n        time.sleep(2)  # Вежливая задержка между локациями\n\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Cp>Тот же запрос через \u003Ccode>curl\u003C\u002Fcode> для быстрой отладки:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode># US \u002F New York через резидентный прокси ProxyHat\ncurl -s \\\n  --proxy &quot;http:\u002F\u002Fuser-country-US-region-new_york-city-new_york_city:YOUR_PASSWORD@gate.proxyhat.com:8080&quot; \\\n  -H &quot;User-Agent: Mozilla\u002F5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\u002F537.36 (KHTML, like Gecko) Chrome\u002F120.0.0.0 Safari\u002F537.36&quot; \\\n  &quot;https:\u002F\u002Fwww.google.com\u002Fsearch?q=best+coffee+shop&amp;gl=us&amp;hl=en&amp;pws=0&amp;num=20&amp;uule=w+CAIQICIRQnJvb2tseW4sIE5ldyBZb3JrLCBOWQ==&quot; \\\n  -o serp_nyc.html\n\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch2>Пример 2: Парсинг органических результатов и Local Pack с selectolax\u003C\u002Fh2>\n\n\u003Cp>После получения HTML нужно извлечь органические результаты и Local Pack. Используем \u003Ccode>selectolax\u003C\u002Fcode> — быстрый HTML-парсер на основе Lexbor:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>from selectolax.parser import HTMLParser\nimport json\nimport re\n\n\ndef parse_organic_results(html: str) -&gt; list[dict]:\n    &quot;&quot;&quot;Извлекает органические результаты из HTML SERP.&quot;&quot;&quot;\n    tree = HTMLParser(html)\n    results = []\n\n    # Google использует div.g для органических результатов\n    for div in tree.css(&quot;div.g&quot;):\n        title_tag = div.css_first(&quot;h3&quot;)\n        link_tag = div.css_first(&quot;a[href]&quot;)\n        snippet_tag = div.css_first(&quot;div[data-sncf], .VwiC3b, span.aCOpRe&quot;)\n\n        if not title_tag or not link_tag:\n            continue\n\n        title = title_tag.text(strip=True)\n        url = link_tag.attributes.get(&quot;href&quot;, &quot;&quot;)\n        snippet = snippet_tag.text(strip=True) if snippet_tag else &quot;&quot;\n\n        # Фильтруем внутренние ссылки Google\n        if url.startswith(&quot;http&quot;) and &quot;google.com&quot; not in url.split(&quot;\u002F&quot;)[2]:\n            results.append({\n                &quot;position&quot;: len(results) + 1,\n                &quot;title&quot;: title,\n                &quot;url&quot;: url,\n                &quot;snippet&quot;: snippet,\n            })\n\n    return results\n\n\ndef parse_local_pack(html: str) -&gt; list[dict]:\n    &quot;&quot;&quot;Извлекает Local Pack (3-pack) из SERP.&quot;&quot;&quot;\n    tree = HTMLParser(html)\n    local_results = []\n\n    # Local Pack обычно в div с role=&quot;main&quot; или в .local-packed\n    for item in tree.css(&quot;div.eT1oC, div[jsname] &gt; div.g&quot;):\n        name_tag = item.css_first(&quot;span.Jr5vfb, .dbg0pd, .OSrXXb&quot;)\n        rating_tag = item.css_first(&quot;span.MHleUd, span[aria-label*=rating]&quot;)\n        address_tag = item.css_first(&quot;span.LrzXKn, .text&quot;)\n\n        if not name_tag:\n            continue\n\n        name = name_tag.text(strip=True)\n        rating = rating_tag.text(strip=True) if rating_tag else &quot;N\u002FA&quot;\n        address = address_tag.text(strip=True) if address_tag else &quot;&quot;\n\n        local_results.append({\n            &quot;name&quot;: name,\n            &quot;rating&quot;: rating,\n            &quot;address&quot;: address,\n        })\n\n    return local_results\n\n\ndef parse_serp(html: str, locale_label: str, query: str) -&gt; dict:\n    &quot;&quot;&quot;Полный парсинг SERP: органика + Local Pack.&quot;&quot;&quot;\n    organic = parse_organic_results(html)\n    local_pack = parse_local_pack(html)\n\n    return {\n        &quot;query&quot;: query,\n        &quot;locale&quot;: locale_label,\n        &quot;organic_count&quot;: len(organic),\n        &quot;local_pack_count&quot;: len(local_pack),\n        &quot;organic&quot;: organic[:10],  # Топ-10\n        &quot;local_pack&quot;: local_pack,\n    }\n\n\n# --- Использование ---\nif __name__ == &quot;__main__&quot;:\n    with open(&quot;serp_NYC_1700000000.html&quot;, &quot;r&quot;, encoding=&quot;utf-8&quot;) as f:\n        html = f.read()\n\n    data = parse_serp(html, &quot;NYC&quot;, &quot;best coffee shop&quot;)\n    print(json.dumps(data, indent=2, ensure_ascii=False))\n\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch2>Пример 3: Sticky-сессии для многостраничного сбора SERP\u003C\u002Fh2>\n\n\u003Cp>При сборе нескольких страниц SERP (page=1, page=2, ...) важно сохранять один IP-адрес в рамках сессии. Если IP меняется между страницами, Google может показать разные результаты из-за смены геолокации. ProxyHat поддерживает sticky-сессии через флаг \u003Ccode>sid-XXX\u003C\u002Fcode> в имени пользователя:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>import base64\nimport time\nimport logging\nfrom curl_cffi import requests as cffi_requests\nfrom urllib.parse import urlencode\n\nlogging.basicConfig(level=logging.INFO)\nlogger = logging.getLogger(&quot;multi_page_serp&quot;)\n\ndef build_uule(place_name: str) -&gt; str:\n    prefix = &quot;w+CAIQICI&quot;\n    encoded = base64.b64encode(place_name.encode(&quot;utf-8&quot;)).decode(&quot;ascii&quot;)\n    length_byte = chr(len(encoded))\n    return prefix + length_byte + encoded\n\n\ndef fetch_serp_page(\n    query: str,\n    page: int,\n    locale: dict,\n    session_id: str,\n) -&gt; str:\n    &quot;&quot;&quot;Запрашивает конкретную страницу SERP с sticky-сессией ProxyHat.\n    \n    Sticky-сессия сохраняет один IP для всех страниц,\n    обеспечивая консистентность геолокации.\n    &quot;&quot;&quot;\n    # Sticky-сессия: session-ID в имени пользователя\n    proxy_user = f&quot;{locale[&apos;proxy_user&apos;]}-sid-{session_id}&quot;\n    proxy_url = (\n        f&quot;http:\u002F\u002F{proxy_user}:{locale[&apos;proxy_pass&apos;]}&quot;\n        f&quot;@gate.proxyhat.com:8080&quot;\n    )\n\n    uule = build_uule(locale[&quot;uule_place&quot;])\n    start = (page - 1) * 10  # Google использует start= для пагинации\n\n    params = {\n        &quot;q&quot;: query,\n        &quot;gl&quot;: locale[&quot;gl&quot;],\n        &quot;hl&quot;: locale[&quot;hl&quot;],\n        &quot;uule&quot;: uule,\n        &quot;pws&quot;: &quot;0&quot;,\n        &quot;num&quot;: &quot;10&quot;,\n        &quot;start&quot;: str(start),\n    }\n    serp_url = f&quot;https:\u002F\u002Fwww.{locale[&apos;google_domain&apos;]}\u002Fsearch?{urlencode(params)}&quot;\n\n    logger.info(f&quot;[{locale[&apos;label&apos;]}] Page {page}, session={session_id}&quot;)\n\n    response = cffi_requests.get(\n        serp_url,\n        proxies={&quot;http&quot;: proxy_url, &quot;https&quot;: proxy_url},\n        impersonate=&quot;chrome120&quot;,\n        timeout=30,\n    )\n    response.raise_for_status()\n    return response.text\n\n\ndef scrape_all_pages(\n    query: str,\n    locale: dict,\n    max_pages: int = 3,\n) -&gt; list[str]:\n    &quot;&quot;&quot;Собирает несколько страниц SERP с одной sticky-сессией.&quot;&quot;&quot;\n    session_id = f&quot;loc{locale[&apos;label&apos;]}{int(time.time())}&quot;\n    pages_html = []\n\n    for page in range(1, max_pages + 1):\n        try:\n            html = fetch_serp_page(query, page, locale, session_id)\n            pages_html.append(html)\n            logger.info(f&quot;[{locale[&apos;label&apos;]}] Page {page} OK, len={len(html)}&quot;)\n        except Exception as e:\n            logger.error(f&quot;[{locale[&apos;label&apos;]}] Page {page} failed: {e}&quot;)\n            break\n\n        if page &lt; max_pages:\n            time.sleep(2.5)  # Задержка между страницами\n\n    return pages_html\n\n\n# --- Запуск ---\nif __name__ == &quot;__main__&quot;:\n    locale = {\n        &quot;label&quot;: &quot;NYC&quot;,\n        &quot;gl&quot;: &quot;us&quot;, &quot;hl&quot;: &quot;en&quot;, &quot;google_domain&quot;: &quot;google.com&quot;,\n        &quot;uule_place&quot;: &quot;Brooklyn, New York, NY&quot;,\n        &quot;proxy_user&quot;: &quot;user-country-US-region-new_york-city-new_york_city&quot;,\n        &quot;proxy_pass&quot;: &quot;YOUR_PASSWORD&quot;,\n    }\n\n    all_pages = scrape_all_pages(&quot;plumber&quot;, locale, max_pages=3)\n    logger.info(f&quot;Collected {len(all_pages)} pages for {locale[&apos;label&apos;]}&quot;)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch2>CAPTCHA, 429 и экспоненциальный backoff\u003C\u002Fh2>\n\n\u003Cp>Даже с резидентными прокси Google может вернуть CAPTCHA или HTTP 429 при интенсивном скрейпинге. Вот стратегия обработки с экспоненциальным backoff, повторными попытками и переключением прокси:\u003C\u002Fp>\n\n\u003Cpre>\u003Ccode>import time\nimport random\nimport logging\nfrom curl_cffi import requests as cffi_requests\n\nlogging.basicConfig(level=logging.INFO)\nlogger = logging.getLogger(&quot;serp_retry&quot;)\n\n# Словарь пулов прокси по странам\nPROXY_POOLS = {\n    &quot;US&quot;: [\n        &quot;http:\u002F\u002Fuser-country-US-region-new_york-city-new_york_city-sid-s1:PASS@gate.proxyhat.com:8080&quot;,\n        &quot;http:\u002F\u002Fuser-country-US-region-illinois-city-chicago-sid-s2:PASS@gate.proxyhat.com:8080&quot;,\n        &quot;http:\u002F\u002Fuser-country-US-region-florida-city-miami-sid-s3:PASS@gate.proxyhat.com:8080&quot;,\n    ],\n    &quot;DE&quot;: [\n        &quot;http:\u002F\u002Fuser-country-DE-region-state_of_berlin-city-berlin-sid-s1:PASS@gate.proxyhat.com:8080&quot;,\n        &quot;http:\u002F\u002Fuser-country-DE-region-bayern-city-munich-sid-s2:PASS@gate.proxyhat.com:8080&quot;,\n    ],\n}\n\nMAX_RETRIES = 5\nBASE_DELAY = 2.0  # секунд\n\n\ndef fetch_with_retry(url: str, country: str, impersonate=&quot;chrome120&quot;) -&gt; str | None:\n    &quot;&quot;&quot;Запрос с экспоненциальным backoff и ротацией прокси.\n    \n    - При 429\u002F503 ждёт и повторяет с новым прокси из пула.\n    - При CAPTCHA (302 на sorry\u002Findex) меняет прокси и повторяет.\n    - При 200 возвращает HTML.\n    &quot;&quot;&quot;\n    pool = PROXY_POOLS.get(country, [])\n    if not pool:\n        raise ValueError(f&quot;No proxy pool for country: {country}&quot;)\n\n    for attempt in range(1, MAX_RETRIES + 1):\n        proxy_url = random.choice(pool)\n        try:\n            response = cffi_requests.get(\n                url,\n                proxies={&quot;http&quot;: proxy_url, &quot;https&quot;: proxy_url},\n                impersonate=impersonate,\n                timeout=30,\n                allow_redirects=False,  # Не следуем за CAPTCHA-редиректами\n            )\n\n            # Проверяем CAPTCHA-редирект\n            if response.status_code == 302 and &quot;sorry&quot; in response.headers.get(&quot;location&quot;, &quot;&quot;):\n                logger.warning(f&quot;Attempt {attempt}: CAPTCHA redirect detected&quot;)\n                delay = BASE_DELAY * (2 ** (attempt - 1)) + random.uniform(0, 1)\n                time.sleep(delay)\n                continue\n\n            # Rate limiting\n            if response.status_code in (429, 503):\n                delay = BASE_DELAY * (2 ** (attempt - 1)) + random.uniform(0, 1)\n                logger.warning(f&quot;Attempt {attempt}: HTTP {response.status_code}, retry in {delay:.1f}s&quot;)\n                time.sleep(delay)\n                continue\n\n            response.raise_for_status()\n            logger.info(f&quot;Attempt {attempt}: OK, len={len(response.text)}&quot;)\n            return response.text\n\n        except Exception as e:\n            logger.error(f&quot;Attempt {attempt}: {e}&quot;)\n            delay = BASE_DELAY * (2 ** (attempt - 1))\n            time.sleep(delay)\n\n    logger.error(f&quot;All {MAX_RETRIES} attempts failed for {url}&quot;)\n    return None\n\n\n# --- Использование ---\nif __name__ == &quot;__main__&quot;:\n    serp_url = (\n        &quot;https:\u002F\u002Fwww.google.com\u002Fsearch?q=plumber&amp;gl=us&amp;hl=en&amp;pws=0&amp;num=10&quot;\n        &quot;&amp;uule=w+CAIQICIRQnJvb2tseW4sIE5ldyBZb3JrLCBOWQ==&quot;\n    )\n    html = fetch_with_retry(serp_url, &quot;US&quot;)\n    if html:\n        print(f&quot;Success! HTML length: {len(html)}&quot;)\n    else:\n        print(&quot;Failed after all retries&quot;)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\n\u003Ch3>Советы по продакшен-надёжности\u003C\u002Fh3>\n\n\u003Cul>\n\u003Cli>Пер-страновые пулы прокси: держите минимум 3-5 IP на каждую локацию. Это позволяет ротировать при CAPTCHA без потери гео-точности.\u003C\u002Fli>\n\u003Cli>Задержки 1-3 секунды между запросами к одному домену. Случайный джиттер снижает вероятность rate-limit.\u003C\u002Fli>\n\u003Cli>Логирование метрик: записывайте success rate, latency, код ответа для каждого прокси. ProxyHat dashboard показывает статистику по сессиям.\u003C\u002Fli>\n\u003Cli>Circuit breaker: если пул прокси для страны даёт &gt;30% ошибок за 5 минут, ставьте его на паузу и переключайтесь на резервный.\u003C\u002Fli>\n\u003Cli>Мониторинг CAPTCHA: если доля CAPTCHA превышает 5%, снижайте частоту запросов на 50%.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Ch2>Сравнение типов прокси для SERP-скрейпинга\u003C\u002Fh2>\n\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\u003Cth>Тип прокси\u003C\u002Fth>\u003Cth>Success rate (Google)\u003C\u002Fth>\u003Cth>Гео-точность\u003C\u002Fth>\u003Cth>Стоимость\u003C\u002Fth>\u003Cth>Рекомендация\u003C\u002Fth>\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\u003Ctd>Дата-центровые\u003C\u002Ftd>\u003Ctd>~40-60%\u003C\u002Ftd>\u003Ctd>Страна\u003C\u002Ftd>\u003Ctd>Низкая\u003C\u002Ftd>\u003Ctd>Не рекомендуется для Google\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Резидентные\u003C\u002Ftd>\u003Ctd>~90-95%\u003C\u002Ftd>\u003Ctd>Страна + Город\u003C\u002Ftd>\u003Ctd>Средняя\u003C\u002Ftd>\u003Ctd>Оптимальный выбор\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>Мобильные\u003C\u002Ftd>\u003Ctd>~95-98%\u003C\u002Ftd>\u003Ctd>Страна\u003C\u002Ftd>\u003Ctd>Высокая\u003C\u002Ftd>\u003Ctd>Для критичных задач\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\n\u003Cp>ProxyHat предоставляет все три типа. Для гео-таргетированного SERP-скрейпинга рекомендуется \u003Ca href=\"\u002Fru\u002Fpricing\">резидентный план\u003C\u002Fa> с поддержкой city-level таргетинга. Подробнее о применении — в разделе \u003Ca href=\"\u002Fru\u002Fuse-cases\u002Fserp-tracking\">SERP tracking\u003C\u002Fa> и \u003Ca href=\"\u002Fru\u002Fuse-cases\u002Fweb-scraping\">web scraping\u003C\u002Fa>.\u003C\u002Fp>\n\n\u003Ch2>Юридические и этические ограничения\u003C\u002Fh2>\n\n\u003Cp>Сбор публичных данных из SERP Google находится в серой правовой зоне. \u003Ca href=\"https:\u002F\u002Fwww.google.com\u002Frobots.txt\" rel=\"noopener noreferrer\">robots.txt Google\u003C\u002Fa> запрещает автоматический доступ к \u003Ccode>\u002Fsearch\u003C\u002Fcode>. Технически это не имеет силы закона, но Google ToS прямо запрещают автоматизированные запросы. В деле \u003Cem>hiQ Labs v. LinkedIn\u003C\u002Fem> (9th Circuit, 2022) суд постановил, что сбор публично доступных данных не нарушает CFAA, но это не освобождает от ответственности за нарушение ToS конкретной платформы.\u003C\u002Fp>\n\n\u003Cp>Практические рекомендации:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>Соблюдайте разумные лимиты частоты запросов (не более 1 req\u002Fsec на IP).\u003C\u002Fli>\n\u003Cli>Не собирайте персональные данные без правового основания (GDPR\u002FCCPA).\u003C\u002Fli>\n\u003Cli>Если используете данные коммерчески, рассмотрите официальное API — \u003Ca href=\"https:\u002F\u002Fdevelopers.google.com\u002Fcustom-search\u002Fv1\u002Foverview\" rel=\"noopener noreferrer\">Google Custom Search API\u003C\u002Fa> (100 запросов\u002Fдень бесплатно, далее $5\u002F1000 запросов).\u003C\u002Fli>\n\u003Cli>Храните собранные данные не дольше, чем необходимо для бизнес-задачи.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>Полная документация по настройке прокси доступна на \u003Ca href=\"https:\u002F\u002Fdocs.proxyhat.com\u002F\" rel=\"noopener noreferrer\">docs.proxyhat.com\u003C\u002Fa>.\u003C\u002Fp>\n\n\u003Ch2>Ключевые выводы\u003C\u002Fh2>\n\n\u003Cblockquote>\n\u003Cp>Гео-таргетированный скрейпинг SERP требует согласованности трёх уровней: параметров URL (gl\u002Fhl\u002Fuule), IP-географии (прокси) и TLS-отпечатка (имперсонализация браузера). Без согласованности любого из уровней результаты будут искажены.\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\n\u003Cul>\n\u003Cli>uule — ключевой параметр для локального SEO. Без него вы получаете национальный SERP, а не городской. Всегда добавляйте \u003Ccode>pws=0\u003C\u002Fcode> для воспроизводимости.\u003C\u002Fli>\n\u003Cli>Резидентные прокси обязательны для Google SERP. Дата-центровые IP блокируются в 40-60% случаев. ProxyHat резидентные прокси через \u003Ccode>gate.proxyhat.com:8080\u003C\u002Fcode> с city-level таргетингом обеспечивают ~90-95% success rate.\u003C\u002Fli>\n\u003Cli>Sticky-сессии через флаг \u003Ccode>sid-XXX\u003C\u002Fcode> сохраняют IP между страницами, что критично для консистентности многостраничных SERP.\u003C\u002Fli>\n\u003Cli>Экспоненциальный backoff с ротацией прокси — минимальный набор для продакшена. Circuit breaker и пер-страновые пулы повышают надёжность до уровня SaaS.\u003C\u002Fli>\n\u003Cli>Соблюдайте ToS: сбор SERP нарушает условия Google. Оценивайте риски и рассмотрите официальное API для критичных задач.\u003C\u002Fli>\n\u003C\u002Ful>","Гео-таргетированный скрейпинг SERP: лучшие практики | ProxyHat","Лучшие практики гео-таргетированного скрейпинга SERP: параметр uule, gl, hl, google_domain, ротация резидентных прокси. Примеры кода на Python для локального SEO.","\u002Fru\u002Fblog\u002Fgeo-targeted-serp-scraping-best-practices",null,"Практическое руководство по локализованному сбору SERP Google: uule, gl, hl, pws=0, резидентные прокси. Примеры кода на Python.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fgeo-targeted-serp-scraping-best-practices-og.webp",[18,21,24],{"question":19,"answer":20},"Почему гео-таргетированный скрейпинг важен для пользователей прокси?","Google возвращает разные результаты в зависимости от IP-адреса, языка интерфейса и явных параметров локализации. Если IP-география не совпадает с параметром gl или uule, Google может проигнорировать их или показать смешанные результаты. Резидентные прокси из нужной локации обеспечивают согласованность и снижают риск блокировок.",{"question":22,"answer":23},"Какой тип прокси лучше всего подходит для гео-таргетированного скрейпинга SERP?","Резидентные прокси — оптимальный выбор. Они используют IP-адреса реальных ISP, что делает их неотличимыми от обычных пользователей. Мобильные прокси подходят для высокой анонимности, но дороже. Дата-центровые прокси часто блокируются Google. ProxyHat предоставляет резидентные прокси с таргетингом по стране и городу через gate.proxyhat.com:8080.",{"question":25,"answer":26},"Как избежать блокировок при гео-таргетированном скрейпинге SERP?","Используйте ротацию IP между запросами, задержки между запросами (1-3 секунды), экспоненциальный backoff при 429\u002F503, имперсонализацию браузера (TLS fingerprint Chrome), согласованность параметров gl\u002Fhl\u002Fuule с IP-географией, и уважайте robots.txt. Sticky-сессии помогают для многостраничных запросов, сохраняя один IP.",false,"2026-07-31T16:11:16+00:00","2026-10-03T08:57:46+00:00","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fgeo-targeted-serp-scraping-best-practices-master.webp","Geo-Targeted SERP Scraping Best Practices for Local SEO Data","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fgeo-targeted-serp-scraping-best-practices-card.webp",12,{"name":35,"slug":36,"bio":37,"avatar_url":14,"website_url":14,"social_links":14},"ProxyHat Team","proxyhat-team","The ProxyHat editorial team covers proxies, web scraping, and data extraction.",[39],{"id":40,"slug":41,"name":42,"description":14,"meta_title":43,"meta_description":44,"parent_id":14},3,"serp-i-seo-treking","SERP и SEO-трекинг","Руководства по SERP и SEO-трекингу | Блог ProxyHat","Как отслеживать позиции в поисковых системах и парсить SERP с помощью прокси.",[],{"en":47,"x-default":47},"\u002Fblog\u002Fgeo-targeted-serp-scraping-best-practices",{"zh":49,"ja":50,"pl":51,"es":52,"it":53,"tr":54,"ko":55,"en":47,"ru":13,"de":56,"fr":57,"pt":58},"\u002Fcn\u002Fblog\u002Fserp-dili-dingwei-zhuaqu-zhinan","\u002Fja\u002Fblog\u002Fgeo-targeted-serp-scraping-guide","\u002Fpl\u002Fblog\u002Fgeotargetowane-scrapowanie-serp-najlepsze-praktyki","\u002Fes\u002Fblog\u002Fscraping-serp-geo-segmentado-mejores-practicas","\u002Fit\u002Fblog\u002Fscraping-serp-geo-targetato-best-practices","\u002Ftr\u002Fblog\u002Fcografi-hedefli-serp-kazima-rehberi","\u002Fko\u002Fblog\u002Fgeo-targeted-serp-scraping-guide","\u002Fde\u002Fblog\u002Fgeo-targeted-serp-scraping-leitfaden","\u002Ffr\u002Fblog\u002Fscraping-serp-geocible-meilleures-pratiques","\u002Fpt\u002Fblog\u002Fpraticas-serp-scraping-geo-targeted",59,[61,78,94,111],{"id":62,"slug":63,"title":64,"excerpt":65,"featured_image_url":66,"featured_image_alt":67,"card_image_url":68,"og_image_url":69,"published_at":70,"updated_at":70,"content_updated_at":71,"reading_time_minutes":72,"is_featured":27,"indexable":27,"views":73,"author":74,"categories":75,"tags":77},155,"amazon-treking-pozitsiy-klyuchevyh-slov","Отслеживание позиций ключевых слов Amazon через прокси: руководство для разработчиков","Полное руководство по отслеживанию позиций ключевых слов Amazon через residential-прокси. Примеры на Python с curl_cffi и Playwright, парсинг SERP, production-настройки.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Famazon-treking-pozitsiy-klyuchevyh-slov-master.webp","Amazon Keyword Rank Tracking with Proxies: A Developer's Guide","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Famazon-treking-pozitsiy-klyuchevyh-slov-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Famazon-treking-pozitsiy-klyuchevyh-slov-og.webp","2026-07-16T16:05:31+00:00","2026-10-03T08:21:27+00:00",13,98,{"name":35,"slug":36,"bio":37,"avatar_url":14,"website_url":14,"social_links":14},[76],{"id":40,"slug":41,"name":42,"description":14,"meta_title":43,"meta_description":44,"parent_id":14},[],{"id":79,"slug":80,"title":81,"excerpt":82,"featured_image_url":83,"featured_image_alt":84,"card_image_url":85,"og_image_url":86,"published_at":87,"updated_at":87,"content_updated_at":88,"reading_time_minutes":33,"is_featured":27,"indexable":27,"views":89,"author":90,"categories":91,"tags":93},153,"skrejping-google-paa-autocomplete-python","Скрейпинг Google People Also Ask и Autocomplete для исследования ключевых слов: руководство по Python","Практическое руководство по сбору автодополнений Google, блоков People Also Ask и связанных запросов с помощью Python, httpx, Playwright и резидентных прокси ProxyHat для локализованного исследования ключевых слов.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fskrejping-google-paa-autocomplete-python-master.webp","Scrape Google People Also Ask and Autocomplete for Keyword Research (Python Guide)","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fskrejping-google-paa-autocomplete-python-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fskrejping-google-paa-autocomplete-python-og.webp","2026-07-14T16:06:25+00:00","2026-10-03T08:29:54+00:00",124,{"name":35,"slug":36,"bio":37,"avatar_url":14,"website_url":14,"social_links":14},[92],{"id":40,"slug":41,"name":42,"description":14,"meta_title":43,"meta_description":44,"parent_id":14},[],{"id":95,"slug":96,"title":97,"excerpt":98,"featured_image_url":99,"featured_image_alt":100,"card_image_url":101,"og_image_url":102,"published_at":103,"updated_at":103,"content_updated_at":104,"reading_time_minutes":105,"is_featured":27,"indexable":27,"views":106,"author":107,"categories":108,"tags":110},154,"kak-otslezhivat-google-ai-overviews-1","Как отслеживать Google AI Overviews: стратегическое руководство для SEO-команд","Практическое руководство по отслеживанию Google AI Overviews для SEO-лидов и продуктовых менеджеров: данные, build-vs-buy, настройка резидентных прокси и управление комплаенсом.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fkak-otslezhivat-google-ai-overviews-1-master.webp","How to Track Your Brand in Google AI Overviews: A Strategic Guide for SEO & Data Teams","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fkak-otslezhivat-google-ai-overviews-1-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fkak-otslezhivat-google-ai-overviews-1-og.webp","2026-07-14T10:05:37+00:00","2026-10-03T08:29:51+00:00",10,66,{"name":35,"slug":36,"bio":37,"avatar_url":14,"website_url":14,"social_links":14},[109],{"id":40,"slug":41,"name":42,"description":14,"meta_title":43,"meta_description":44,"parent_id":14},[],{"id":112,"slug":113,"title":114,"excerpt":115,"featured_image_url":116,"featured_image_alt":117,"card_image_url":118,"og_image_url":119,"published_at":120,"updated_at":120,"content_updated_at":121,"reading_time_minutes":33,"is_featured":27,"indexable":27,"views":122,"author":123,"categories":124,"tags":126},152,"postroit-treker-pozitsiy-google-python","Создать трекер позиций Google на Python с резидентными прокси: руководство 2026","Полное руководство для разработчиков: модель данных, пагинация SERP после удаления num=100, обход TLS-фингерпринтинга JA3\u002FJA4, curl_cffi + ProxyHat, хранение в SQLite и продакшн-надёжность.","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fpostroit-treker-pozitsiy-google-python-master.webp","Build a Google Rank Tracker in Python with Residential Proxies","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fpostroit-treker-pozitsiy-google-python-card.webp","https:\u002F\u002Fstatic.proxyhat.com\u002Fstorage\u002Fblog-covers\u002Fru\u002Fpostroit-treker-pozitsiy-google-python-og.webp","2026-07-02T16:04:58+00:00","2026-10-03T08:57:49+00:00",56,{"name":35,"slug":36,"bio":37,"avatar_url":14,"website_url":14,"social_links":14},[125],{"id":40,"slug":41,"name":42,"description":14,"meta_title":43,"meta_description":44,"parent_id":14},[],[]]