a028af4bc8
Экстрактор кода страницы ловил любые 11 цифр (7/8 + телефонная группировка) без проверки, что это настоящий российский номер — со страниц-агрегаторов пролезал мусор с несуществующими кодами (227/303/453/613/761) и подписывался «городской». PhoneValidityGate между CandidateBuilder и SourceAggregator: - слой 1 (бесплатно, всегда): реестр Россвязи (phone_ranges) — нет в реестре → выкидываем; - слой 2 (платно, за флагом autopodbor.phone_dadata_enabled, по умолчанию ВЫКЛ): DaDataValidityLayer перепроверяет прошедшие реестр номера, снимает qc 2/7, под дневным бюджетом + кэш вердикта; платим только за выживших (мусор отсекается ДО ДаДаты). - fail-open при пустом реестре / сбое БД (иначе внешний catch в SiteOpener съел бы все номера); - короткие/uncertain номера не трогаем (нельзя сверить). Закрыты ОБА пути шага 2: обычный (RealCompetitorAgent) и глубокий (SiteOpener). Миграций нет — реестр уже на проде (453k диапазонов). Тесты: PhoneValidityGateTest (7), DaDataValidityLayerTest (6), SiteOpenerValidityTest (1); весь набор автоподбора 519 зелёных, Pint + Larastan чисто. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
142 lines
9.4 KiB
PHP
142 lines
9.4 KiB
PHP
<?php
|
||
|
||
return [
|
||
/*
|
||
|--------------------------------------------------------------------------
|
||
| Живой движок поиска конкурентов (шаг 1)
|
||
|--------------------------------------------------------------------------
|
||
|
|
||
| true → findCompetitors использует НАСТОЯЩИЙ движок (ниша → поиск 2ГИС/Яндекс →
|
||
| резолв → сборка). false → демо-заглушка FakeCompetitorAgent. По умолчанию ВЫКЛ —
|
||
| включается осознанно (локально/за тумблером), т.к. ходит в живые сервисы.
|
||
|
|
||
*/
|
||
'real_find' => env('AUTOPODBOR_REAL_FIND', false),
|
||
|
||
/*
|
||
|--------------------------------------------------------------------------
|
||
| Авто-повтор поиска при ПУСТОМ сборе
|
||
|--------------------------------------------------------------------------
|
||
|
|
||
| Внешние источники (2ГИС/Яндекс/EXA) иногда моргают и отдают пусто. Чтобы
|
||
| клиент не видел «ничего не нашлось» из-за секундного сбоя — при пустом сборе
|
||
| повторяем поиск N доп. раз. 0 → без повторов. Реально пустая ниша (все попытки
|
||
| пусты) идёт штатным путём «empty» без списания.
|
||
|
|
||
*/
|
||
'search_retry_on_empty' => (int) env('AUTOPODBOR_SEARCH_RETRY_ON_EMPTY', 2),
|
||
|
||
/*
|
||
|--------------------------------------------------------------------------
|
||
| Путь к бинарнику node для Playwright-скриптов
|
||
|--------------------------------------------------------------------------
|
||
|
|
||
| Из-под PHP-процесса (очередь, artisan) PATH может отличаться от интерактивного
|
||
| шелла. Если 'node' по PATH не находится — пропишите абсолютный путь в .env:
|
||
| AUTOPODBOR_NODE_BIN="C:\Program Files\nodejs\node.exe"
|
||
|
|
||
*/
|
||
'node_bin' => env('AUTOPODBOR_NODE_BIN', 'node'),
|
||
|
||
/*
|
||
|--------------------------------------------------------------------------
|
||
| Глубокий шаг 2 (движок «глобального сбора источников»)
|
||
|--------------------------------------------------------------------------
|
||
|
|
||
| true → studyCompetitor сам доищет след (EXA → площадки → якорный фильтр →
|
||
| 2ГИС по имени → Яндекс Playwright). false → старый путь по site_url +
|
||
| directory_urls из шага 1. По умолчанию ВЫКЛ — включается осознанно.
|
||
|
|
||
*/
|
||
'deep_study' => env('AUTOPODBOR_DEEP_STUDY', false),
|
||
|
||
/*
|
||
|--------------------------------------------------------------------------
|
||
| Разворот по телефонам (сайты проектов застройщика)
|
||
|--------------------------------------------------------------------------
|
||
|
|
||
| true → на шаге 2 по каждому личному телефону фирмы делаем обратный поиск в
|
||
| 2ГИС и вскрываем связанные карточки (проекты холдинга): забираем их сайты и
|
||
| телефоны, цепочкой. Общие номера (у многих фирм) пропускаем. Требует deep_study.
|
||
| По умолчанию ВЫКЛ — включается осознанно (ходит в живой 2ГИС).
|
||
|
|
||
*/
|
||
'phone_reverse' => env('AUTOPODBOR_PHONE_REVERSE', false),
|
||
|
||
/*
|
||
|--------------------------------------------------------------------------
|
||
| Разворот по телефонам в Яндекс.Картах (рядом с 2ГИС)
|
||
|--------------------------------------------------------------------------
|
||
|
|
||
| true → на шаге 2 номера фирмы разворачиваем ещё и в Яндексе (для застройщиков,
|
||
| которые только в Яндексе). Каждая карточка-кандидат открывается и номер на ней
|
||
| проверяется (Яндекс отдаёт рыхлый список). Требует phone_reverse. По умолчанию ВЫКЛ.
|
||
|
|
||
*/
|
||
'phone_reverse_yandex' => env('AUTOPODBOR_PHONE_REVERSE_YANDEX', false),
|
||
|
||
/*
|
||
|--------------------------------------------------------------------------
|
||
| Параллельный разворот: 2ГИС и Яндекс одновременно
|
||
|--------------------------------------------------------------------------
|
||
|
|
||
| true → 2ГИС-разворот и Яндекс-разворот запускаются РАЗОМ (двумя процессами,
|
||
| Concurrency), итог по времени = max(2ГИС, Яндекс), а не сумма. Оба источника
|
||
| отрабатывают полностью — ничего не режется. false → последовательный композит.
|
||
| Безопасно: два разных провайдера, каждый одно-поточный, виртуалка держит потолок.
|
||
| Требует phone_reverse_yandex. По умолчанию ВЫКЛ.
|
||
|
|
||
*/
|
||
'phone_reverse_parallel' => env('AUTOPODBOR_PHONE_REVERSE_PARALLEL', false),
|
||
|
||
/*
|
||
|--------------------------------------------------------------------------
|
||
| Свой рендер-канал (self-render) вместо платного xf4
|
||
|--------------------------------------------------------------------------
|
||
|
|
||
| true → 2ГИС+Яндекс тянутся через свой рендер-сервис на виртуалке (SelfRenderClient
|
||
| + прокси; 2ГИС отдаёт initialState → TwoGisJsonReader). false → текущий путь xf4.
|
||
| Мгновенный откат тумблером. Требует services.self_render.endpoint/.key (в .env).
|
||
| Гранулярные тумблеры (для безопасной раскатки) наследуют master, если не заданы явно:
|
||
| self_render_2gis — только 2ГИС на свой рендер;
|
||
| self_render_yandex — только Яндекс на свой рендер+прокси.
|
||
| По умолчанию ВСЁ ВЫКЛ.
|
||
|
|
||
*/
|
||
'self_render' => env('AUTOPODBOR_SELF_RENDER', false),
|
||
'self_render_2gis' => env('AUTOPODBOR_SELF_RENDER_2GIS', env('AUTOPODBOR_SELF_RENDER', false)),
|
||
'self_render_yandex' => env('AUTOPODBOR_SELF_RENDER_YANDEX', env('AUTOPODBOR_SELF_RENDER', false)),
|
||
|
||
/*
|
||
|--------------------------------------------------------------------------
|
||
| Кэш отрисованных карточек 2ГИС/Яндекс (снизить нагрузку и ускорить)
|
||
|--------------------------------------------------------------------------
|
||
|
|
||
| true → загрузчик карточек оборачивается CachingPageFetcher: отрисованные карточки
|
||
| (2ГИС `…/firm/…`, Яндекс `…/maps/org/…`) кладутся в Redis по ключу URL на N дней и
|
||
| повторно берутся из кэша — без обращений к 2ГИС/Яндекс/прокси. Кэш ОБЩИЙ для шага 1
|
||
| (поиск) и шага 2 (изучение) и для повторных прогонов. Поиск (`…/search/…`) и ленты —
|
||
| всегда свежие (мимо кэша), поэтому повторный сбор всё равно находит новые фирмы.
|
||
| Пустой ответ не кэшируется (сбой не отравит кэш). По умолчанию ВЫКЛ — откат тумблером.
|
||
|
|
||
*/
|
||
'render_cache' => env('AUTOPODBOR_RENDER_CACHE', false),
|
||
'render_cache_ttl_days' => (int) env('AUTOPODBOR_RENDER_CACHE_TTL_DAYS', 5),
|
||
|
||
/*
|
||
|--------------------------------------------------------------------------
|
||
| Второй слой отсева телефонов через ДаДату (после реестра Россвязи)
|
||
|--------------------------------------------------------------------------
|
||
|
|
||
| Пойманные при «вскрытии» кода страницы номера всегда чистятся реестром Россвязи
|
||
| (бесплатно): номера с несуществующим кодом → выкидываются. Этот флаг добавляет
|
||
| ВТОРОЙ, ПЛАТНЫЙ слой — ДаДата clean/phone (~0,6 ₽/номер) перепроверяет уже прошедшие
|
||
| реестр номера и снимает подтверждённый мусор/иностранцев (qc 2/7). Платим только за
|
||
| реальных выживших (мусор отсекается бесплатно ДО ДаДаты), под дневным бюджетом
|
||
| services.dadata.daily_cap_rub, с кэшем вердикта. По умолчанию ВЫКЛ — включается
|
||
| осознанно (тратит деньги). Требует services.dadata.api_key/secret.
|
||
|
|
||
*/
|
||
'phone_dadata_enabled' => env('AUTOPODBOR_PHONE_DADATA_ENABLED', false),
|
||
];
|