
Поиск Подрядчика
Поиск и сравнение подрядчиков на Profi.ru, Авито Услуги, Яндекс.Услуги и YouDo. Поиск исполнителей на всех площадках, сравнение рейтингов, цен, отзывов и времени отклика. Включает анализ фото портфолио, проверку репутации, обнаружение мошенничества, оценку стоимости и автоматизированную связь с персонализированными сообщениями.
SKILL.md
Поиск подрядчиков — Contractor Finder
Поиск исполнителей и подрядчиков одновременно на четырёх крупнейших российских сервисах: Profi.ru, Avito Услуги, Яндекс.Услуги и YouDo. Агрегация результатов, дедупликация, скоринг по рейтингам и ценам, проверка репутации, анализ портфолио.
Обзор
Четыре платформы покрывают ~85% рынка частных услуг в России:
| Платформа | Доля рынка | Особенности |
|---|---|---|
| Profi.ru | ~35% | Крупнейший маркетплейс услуг, рейтинги, верификация, портфолио |
| Avito Услуги | ~30% | Встроен в крупнейший классифайд, много исполнителей, отзывы с покупок |
| Яндекс.Услуги | ~15% | Экосистема Яндекса, проверенные мастера, быстрые ответы |
| YouDo | ~10% | Быстрые задачи, аукцион цен, исполнители с подтверждёнными навыками |
Стратегия: Параллельный поиск по всем платформам, дедупликация (один исполнитель часто на нескольких площадках), скоринг и ранжирование по комплексной оценке.
Установка browser-use
Для работы этого навыка необходим browser-use.
Если browser-use не установлен — активируй навык browser-use и следуй его инструкциям.
Он автоматически установит Python, pip и browser-use для твоей платформы.
Пока идёт установка, скажи: «Настраиваю поиск, это займёт пару минут...» НЕ показывай пользователю команды, ошибки или технические детали.
Когда использовать
- Пользователь ищет подрядчика для ремонта, сантехника, электрика, уборку и т.д.
- Пользователь хочет «найти хорошего мастера» или «сравнить цены на услуги»
- Пользователь дал ссылку на профиль исполнителя и хочет проверить его репутацию
- Пользователь хочет оценить стоимость работ до начала поиска
- Пользователь просит «забронировать мастера» или «написать исполнителю»
- Пользователь хочет проверить портфолио и качество работ подрядчика
Сбор требований у пользователя
Перед поиском уточни:
- Тип услуги — что именно нужно сделать (ремонт, сантехника, электрика, уборка и т.д.)
- Город / район — где нужны работы
- Бюджет — примерная сумма или диапазон
- Срочность — когда нужно начать (срочно, на этой неделе, в течение месяца)
- Объём работ — масштаб задачи (косметический ремонт vs капитальный, одна розетка vs вся проводка)
- Особые требования — лицензии, допуски, опыт с конкретными материалами, язык общения
- Предпочтения — рейтинг от скольки, наличие портфолио, верифицированный исполнитель
Категории услуг и типичные цены
| Категория | URL-slug (Profi/Avito) | Типичная цена | Единица |
|---|---|---|---|
| Ремонт квартир | remont, remont-kvartir | 3 000 – 15 000 | ₽/м² |
| Сантехника | santekhnik, santekhnika | 1 500 – 5 000 | ₽/вызов |
| Электрика | elektrik, elektrika | 1 500 – 4 000 | ₽/точка |
| Уборка | uborka, uborka-kvartir | 1 500 – 4 000 | ₽/раз |
| Переезд | pereezd, pereezd-perevozki | 3 000 – 15 000 | ₽/раз |
| Покраска | pokraska, kraska | 500 – 1 500 | ₽/м² |
| Мебель на заказ | mebel-na-zakaz, mebel | Варьируется | ₽/проект |
| Маникюр / красота | manikyur, krasota-zdorove | 1 500 – 5 000 | ₽/сеанс |
| Репетитор | repititor | 800 – 3 000 | ₽/час |
| Юрист | yurist | 2 000 – 10 000 | ₽/консультация |
| Бухгалтер | bukhgalter | 3 000 – 15 000 | ₽/месяц |
| Дизайнер | dizayner | 3 000 – 20 000 | ₽/проект |
| Фотограф | fotograf | 3 000 – 30 000 | ₽/съёмка |
| Ландшафт | landshaftnyy-dizayn | 500 – 3 000 | ₽/м² |
| Кондиционеры | ustanovka-konditsionerov | 5 000 – 15 000 | ₽/единица |
| Окна / остекление | ustanovka-okon | 5 000 – 25 000 | ₽/окно |
| Отопление | otoplenie | 3 000 – 10 000 | ₽/точка |
| Сборка мебели | sborka-mebeli | 1 500 – 5 000 | ₽/единица |
| Грузчики | gruzchiki | 300 – 800 | ₽/час |
| IT-услуги | kompyuternaya-pomoshch | 500 – 3 000 | ₽/вызов |
Платформа 1: Profi.ru
Крупнейший маркетпллейс услуг в России. Хорошие фильтры, рейтинги, портфолио, верификация мастеров.
URL-структура
| Действие | URL |
|---|---|
| Категория | https://profi.ru/{category}/ |
| Поиск | https://profi.ru/search/?q={query}&location={city} |
| Профиль мастера | https://profi.ru/profile/{id}/ |
| Отзывы мастера | https://profi.ru/profile/{id}/otzyvy/ |
| Портфолио | https://profi.ru/profile/{id}/portfolio/ |
Параметры поиска
| Параметр | Описание | Пример |
|---|---|---|
q | Поисковый запрос (URL-encoded) | q=сантехник+замена+трубы |
location | Город | location=Москва |
sort | Сортировка | sort=rating, sort=price_asc, sort=price_desc |
page | Страница | page=1 |
Извлечение данных через eval
# Список мастеров на странице поиска
browser-use eval "JSON.stringify(Array.from(document.querySelectorAll('[data-testid=\"master-card\"], .master-card, [class*=\"SearchResults\"] [class*=\"card\"], [class*=\"search-result\"]')).slice(0,10).map(el => ({name: el.querySelector('[class*=\"name\"], [class*=\"title\"], a[class*=\"link\"]')?.textContent?.trim(), rating: el.querySelector('[class*=\"rating\"], [class*=\"Rating\"]')?.textContent?.trim(), reviews: el.querySelector('[class*=\"review\"], [class*=\"count\"]')?.textContent?.trim(), price: el.querySelector('[class*=\"price\"], [class*=\"Price\"], [class*=\"rate\"]')?.textContent?.trim(), verified: el.querySelector('[class*=\"verified\"], [class*=\"badge\"], [class*=\"confirm\"]') ? 'Да' : 'Нет', description: el.querySelector('[class*=\"description\"], [class*=\"about\"], p')?.textContent?.trim()?.substring(0, 200), link: el.querySelector('a[href*=\"/profile/\"]')?.href})))"
Селекторы Profi.ru
| Элемент | CSS селектор |
|---|---|
| Карточка мастера | [data-testid="master-card"], .master-card, [class*="SearchResults"] [class*="card"] |
| Имя | [class*="name"], [class*="title"], a[class*="link"] |
| Рейтинг | [class*="rating"], [class*="Rating"], [class*="stars"] |
| Количество отзывов | [class*="review"], [class*="count"] |
| Цена / ставка | [class*="price"], [class*="Price"], [class*="rate"] |
| Значок верификации | [class*="verified"], [class*="badge"], [class*="confirm"] |
| Описание | [class*="description"], [class*="about"], p |
| Ссылка на профиль | a[href*="/profile/"] |
| Портфолио фото | [class*="portfolio"] img, [class*="gallery"] img |
| Время ответа | [class*="response"], [class*="reply"] |
Профиль мастера — детальное извлечение
# Открыть профиль
browser-use --headed open "https://profi.ru/profile/{id}/"
sleep 3
# Полная информация о мастере
browser-use eval "JSON.stringify({name: document.querySelector('h1, [class*=\"name\"]')?.textContent?.trim(), rating: document.querySelector('[class*=\"rating\"], [class*=\"Rating\"]')?.textContent?.trim(), reviews: document.querySelector('[class*=\"review-count\"], [class*=\"reviewsCount\"]')?.textContent?.trim(), price: document.querySelector('[class*=\"price\"], [class*=\"rate\"]')?.textContent?.trim(), verified: document.querySelector('[class*=\"verified\"]') ? 'Да' : 'Нет', responseTime: document.querySelector('[class*=\"response\"], [class*=\"reply\"]')?.textContent?.trim(), description: document.querySelector('[class*=\"about\"], [class*=\"description\"]')?.textContent?.trim()?.substring(0, 500), portfolioCount: document.querySelectorAll('[class*=\"portfolio\"] img, [class*=\"gallery\"] img').length, completedTasks: document.querySelector('[class*=\"completed\"], [class*=\"tasks\"]')?.textContent?.trim()})"
Отзывы
# Перейти к отзывам
browser-use --headed open "https://profi.ru/profile/{id}/otzyvy/"
sleep 3
# Извлечь последние 10 отзывов
browser-use eval "JSON.stringify(Array.from(document.querySelectorAll('[class*=\"review\"], [class*=\"Review\"], [class*=\"feedback\"]')).slice(0,10).map(el => ({rating: el.querySelector('[class*=\"stars\"], [class*=\"rating\"]')?.textContent?.trim(), text: el.querySelector('[class*=\"text\"], [class*=\"body\"], [class*=\"content\"]')?.textContent?.trim()?.substring(0, 300), author: el.querySelector('[class*=\"author\"], [class*=\"name\"]')?.textContent?.trim(), date: el.querySelector('[class*=\"date\"]')?.textContent?.trim()})))"
Особенности Profi.ru
- Рейтинг из 5 звёзд, основан на подтверждённых отзывах
- «Проверенный мастер» — верификация документов и телефонов
- «Быстрый ответ» — отвечает в течение 30 минут
- Цены часто указаны как «от X ₽» — уточняй у мастера
- Портфолио — загруженные мастером фото выполненных работ
- Часть функций доступна только авторизованным пользователям
Платформа 2: Avito Услуги
Крупнейший классифайд России с разделом услуг. Много исполнителей, но хуже модерируемых.
URL-структура
| Действие | URL |
|---|---|
| Категория | https://www.avito.ru/{city}/uslugi/{category} |
| Поиск | https://www.avito.ru/{city}/uslugi?q={query} |
| Объявление исполнителя | https://www.avito.ru/{city}/uslugi/{slug}-{id} |
| Отзывы | На странице объявления (внизу) |
Параметры поиска
| Параметр | Описание | Пример |
|---|---|---|
q | Поисковый запрос | q=электрик |
priceMin | Минимальная цена | priceMin=1000 |
priceMax | Максимальная цена | priceMax=5000 |
sort | Сортировка | sort=price, sort=date, sort=rating |
page | Страница | page=1 |
user | ID продавца | user=12345678 |
Популярные города (slug для URL)
| Город | Slug |
|---|---|
| Москва | moskva |
| Санкт-Петербург | sankt-peterburg |
| Новосибирск | novosibirsk |
| Екатеринбург | ekaterinburg |
| Казань | kazan |
| Краснодар | krasnodar |
| Нижний Новгород | nizhniy_novgorod |
| Самара | samara |
| Ростов-на-Дону | rostov-na-donu |
| Челябинск | chelyabinsk |
Извлечение данных через eval
ВАЖНО: Avito имеет агрессивную антибот-защиту. Минимизируй количество вызовов state. Используй eval для извлечения данных.
# Список объявлений на странице поиска
browser-use eval "JSON.stringify(Array.from(document.querySelectorAll('[data-marker=\"item\"], [class*=\"iva-item\"]')).slice(0,10).map(el => ({name: el.querySelector('[itemprop=\"name\"], [class*=\"title\"], h3, a[class*=\"link\"]')?.textContent?.trim(), price: el.querySelector('[class*=\"price\"], [itemprop=\"price\"], meta[content]')?.getAttribute('content') || el.querySelector('[class*=\"price\"]')?.textContent?.trim(), rating: el.querySelector('[class*=\"rating\"], [class*=\"stars\"]')?.textContent?.trim(), reviews: el.querySelector('[class*=\"review\"], [class*=\"count\"]')?.textContent?.trim(), location: el.querySelector('[class*=\"geo\"], [class*=\"location\"]')?.textContent?.trim(), date: el.querySelector('[class*=\"date\"]')?.textContent?.trim(), link: el.querySelector('a[itemprop=\"url\"], a[href*=\"/uslugi/\"]')?.href})))"
Селекторы Avito Услуги
| Элемент | CSS селектор |
|---|---|
| Карточка объявления | [data-marker="item"], [class*="iva-item"] |
| Название | [itemprop="name"], [class*="title"], h3 |
| Цена | [class*="price"], [itemprop="price"] |
| Рейтинг | [class*="rating"], [class*="stars"] |
| Количество отзывов | [class*="review"], [class*="count"] |
| Геолокация | [class*="geo"], [class*="location"] |
| Дата публикации | [class*="date"] |
| Ссылка | a[itemprop="url"], a[href*="/uslugi/"] |
| «На сайте с» | [class*="registration"], [class*="member-since"] |
| Фото | [class*="photo"] img, [class*="image"] img |
Страница объявления — детальное извлечение
# Открыть объявление
browser-use --headed open "https://www.avito.ru/{city}/uslugi/{slug}-{id}"
sleep 4
# Полная информация
browser-use eval "JSON.stringify({name: document.querySelector('h1, [class*=\"title\"]')?.textContent?.trim(), price: document.querySelector('[class*=\"price\"], [class*=\"Price\"]')?.textContent?.trim(), rating: document.querySelector('[class*=\"rating\"], [class*=\"stars\"]')?.textContent?.trim(), reviews: document.querySelector('[class*=\"review-count\"], [class*=\"count\"]')?.textContent?.trim(), description: document.querySelector('[class*=\"description\"], [class*=\"descriptionText\"]')?.textContent?.trim()?.substring(0, 500), memberSince: document.querySelector('[class*=\"registration\"], [class*=\"member\"]')?.textContent?.trim(), responseRate: document.querySelector('[class*=\"response\"], [class*=\"reply\"]')?.textContent?.trim(), location: document.querySelector('[class*=\"geo\"]')?.textContent?.trim(), photos: Array.from(document.querySelectorAll('[class*=\"photo\"] img, [class*=\"gallery\"] img, [class*=\"image\"] img')).slice(0,5).map(i => i.src)}))"
Особенности Avito Услуги
- Агрессивная антибот-защита: минимизируй количество state-вызовов, используй eval
- Если появилась капча — попроси пользователя пройти её вручную в headed-режиме
- «На сайте с» — дата регистрации, важна для оценки надёжности
- Рейтинг основан на отзывах покупателей
- Много дублей — один исполнитель может иметь несколько объявлений
- Цены часто не указаны — «Цена не указана» или «Договорная»
Платформа 3: Яндекс.Услуги
Сервис от Яндекса с верифицированными мастерами. Хорошая интеграция с экосистемой.
URL-структура
| Действие | URL |
|---|---|
| Главная | https://uslugi.yandex.ru/ |
| Категория | https://uslugi.yandex.ru/{category} |
| Поиск | https://uslugi.yandex.ru/search?text={query}&location={city} |
| Профиль исполнителя | https://uslugi.yandex.ru/profile/{id} |
Параметры поиска
| Параметр | Описание | Пример |
|---|---|---|
text | Поисковый запрос | text=сантехник |
location | Город | location=Москва |
page | Страница | page=1 |
sort | Сортировка | sort=rating, sort=price |
Извлечение данных через eval
# Список исполнителей
browser-use eval "JSON.stringify(Array.from(document.querySelectorAll('[class*=\"search-result\"], [class*=\"SearchResult\"], [class*=\"executor\"], [data-testid*=\"card\"]')).slice(0,10).map(el => ({name: el.querySelector('[class*=\"name\"], [class*=\"title\"], h3')?.textContent?.trim(), rating: el.querySelector('[class*=\"rating\"], [class*=\"Rating\"]')?.textContent?.trim(), reviews: el.querySelector('[class*=\"review\"], [class*=\"count\"]')?.textContent?.trim(), price: el.querySelector('[class*=\"price\"], [class*=\"Price\"]')?.textContent?.trim(), responseTime: el.querySelector('[class*=\"response\"], [class*=\"reply\"]')?.textContent?.trim(), verified: el.querySelector('[class*=\"verified\"], [class*=\"badge\"]') ? 'Да' : 'Нет', link: el.querySelector('a[href*=\"/profile/\"]')?.href})))"
Селекторы Яндекс.Услуги
| Элемент | CSS селектор |
|---|---|
| Карточка результата | [class*="search-result"], [class*="SearchResult"], [data-testid*="card"] |
| Имя | [class*="name"], [class*="title"], h3 |
| Рейтинг | [class*="rating"], [class*="Rating"] |
| Количество отзывов | [class*="review"], [class*="count"] |
| Цена | [class*="price"], [class*="Price"] |
| Время ответа | [class*="response"], [class*="reply"] |
| Значок верификации | [class*="verified"], [class*="badge"] |
| Ссылка на профиль | a[href*="/profile/"] |
| Фото работ | [class*="portfolio"] img, [class*="gallery"] img |
Особенности Яндекс.Услуги
- «Проверенный Яндексом» — верификация документов
- Быстрый ответ — среднее время ответа по данным Яндекса
- Цены часто указаны как «от X ₽/час»
- Хорошие отзывы — модерация строже, чем на Avito
- Меньше исполнителей, чем на Profi.ru, но качество выше
- Для полной информации может потребоваться авторизация
Платформа 4: YouDo
Маркетплейс для быстрых задач. Исполнители соревнуются ценой.
URL-структура
| Действие | URL |
|---|---|
| Главная | https://youdo.com/ |
| Категория | https://youdo.com/{category}/ |
| Поиск | https://youdo.com/search?text={query} |
| Профиль исполнителя | https://youdo.com/profile/{id} |
Категории YouDo
| Slug | Категория |
|---|---|
remont-kvartir | Ремонт квартир |
santekhnika | Сантехника |
elektrika | Электрика |
uborka | Уборка |
pereezd | Переезд |
sborka-mebeli | Сборка мебели |
konditsionery | Кондиционеры |
okna | Окна |
remont-bytovoy-tekhniki | Ремонт бытовой техники |
kompyuternaya-pomoshch | Компьютерная помощь |
Извлечение данных через eval
# Список исполнителей
browser-use eval "JSON.stringify(Array.from(document.querySelectorAll('[class*=\"user-card\"], [class*=\"profile-card\"], [class*=\"executor\"], [class*=\"search-item\"]')).slice(0,10).map(el => ({name: el.querySelector('[class*=\"name\"], [class*=\"title\"]')?.textContent?.trim(), rating: el.querySelector('[class*=\"rating\"], [class*=\"stars\"]')?.textContent?.trim(), completedTasks: el.querySelector('[class*=\"completed\"], [class*=\"tasks-count\"]')?.textContent?.trim(), reviews: el.querySelector('[class*=\"review\"], [class*=\"count\"]')?.textContent?.trim(), price: el.querySelector('[class*=\"price\"], [class*=\"rate\"]')?.textContent?.trim(), link: el.querySelector('a[href*=\"/profile/\"]')?.href})))"
Селекторы YouDo
| Элемент | CSS селектор |
|---|---|
| Карточка исполнителя | [class*="user-card"], [class*="profile-card"], [class*="executor"] |
| Имя | [class*="name"], [class*="title"] |
| Рейтинг | [class*="rating"], [class*="stars"] |
| Выполненные задачи | [class*="completed"], [class*="tasks-count"] |
| Отзывы | [class*="review"], [class*="count"] |
| Цена | [class*="price"], [class*="rate"] |
| Ссылка на профиль | a[href*="/profile/"] |
Особенности YouDo
- «Выполненные задачи» — главный показатель опыта
- Цену часто не указывают — она формируется в чате
- Больше подходит для разовых задач, чем для крупных проектов
- Исполнители соревнуются за задачу — можно получить несколько предложений
- Меньше детализации профиля, чем на Profi.ru
Workflow 1: Поиск подрядчика
Шаг 1: Сбор требований
Уточни у пользователя:
- Тип услуги (ремонт, сантехника, электрика и т.д.)
- Город и район
- Бюджет (диапазон)
- Срочность
- Объём работ
- Особые требования
Шаг 2: Подготовка
# Закрыть все предыдущие сессии
browser-use close --all
sleep 1
Шаг 3: Поиск на Profi.ru
# Открыть поиск Profi.ru
browser-use --headed open "https://profi.ru/search/?q=ЗАПРОС&location=ГОРОД"
sleep 4
# Закрыть cookie-баннер если есть
browser-use state
# Если баннер: browser-use click "Принять" или browser-use click "Согласен"
# Извлечь результаты
browser-use eval "JSON.stringify(Array.from(document.querySelectorAll('[data-testid=\"master-card\"], .master-card, [class*=\"SearchResults\"] [class*=\"card\"]')).slice(0,10).map(el => ({name: el.querySelector('[class*=\"name\"], [class*=\"title\"]')?.textContent?.trim(), rating: el.querySelector('[class*=\"rating\"]')?.textContent?.trim(), reviews: el.querySelector('[class*=\"review\"], [class*=\"count\"]')?.textContent?.trim(), price: el.querySelector('[class*=\"price\"], [class*=\"rate\"]')?.textContent?.trim(), verified: el.querySelector('[class*=\"verified\"], [class*=\"badge\"]') ? 'Да' : 'Нет', link: el.querySelector('a[href*=\"/profile/\"]')?.href})))"
Шаг 4: Поиск на Avito Услуги
browser-use --headed open "https://www.avito.ru/ГОРОД/uslugi?q=ЗАПРОС"
sleep 4
# Извлечь результаты (минимум state-вызовов!)
browser-use eval "JSON.stringify(Array.from(document.querySelectorAll('[data-marker=\"item\"], [class*=\"iva-item\"]')).slice(0,10).map(el => ({name: el.querySelector('[itemprop=\"name\"], [class*=\"title\"]')?.textContent?.trim(), price: el.querySelector('[class*=\"price\"]')?.textContent?.trim(), rating: el.querySelector('[class*=\"rating\"]')?.textContent?.trim(), reviews: el.querySelector('[class*=\"review\"]')?.textContent?.trim(), link: el.querySelector('a[itemprop=\"url\"]')?.href})))"
Шаг 5: Поиск на Яндекс.Услуги
browser-use --headed open "https://uslugi.yandex.ru/search?text=ЗАПРОС&location=ГОРОД"
sleep 4
# Извлечь результаты
browser-use eval "JSON.stringify(Array.from(document.querySelectorAll('[class*=\"search-result\"], [class*=\"SearchResult\"], [data-testid*=\"card\"]')).slice(0,10).map(el => ({name: el.querySelector('[class*=\"name\"], [class*=\"title\"]')?.textContent?.trim(), rating: el.querySelector('[class*=\"rating\"]')?.textContent?.trim(), reviews: el.querySelector('[class*=\"review\"]')?.textContent?.trim(), price: el.querySelector('[class*=\"price\"]')?.textContent?.trim(), link: el.querySelector('a[href*=\"/profile/\"]')?.href})))"
Шаг 6: Поиск на YouDo
browser-use --headed open "https://youdo.com/search?text=ЗАПРОС"
sleep 4
# Извлечь результаты
browser-use eval "JSON.stringify(Array.from(document.querySelectorAll('[class*=\"user-card\"], [class*=\"profile-card\"]')).slice(0,10).map(el => ({name: el.querySelector('[class*=\"name\"]')?.textContent?.trim(), rating: el.querySelector('[class*=\"rating\"]')?.textContent?.trim(), completedTasks: el.querySelector('[class*=\"completed\"]')?.textContent?.trim(), link: el.querySelector('a[href*=\"/profile/\"]')?.href})))"
Шаг 7: Агрегация и дедупликация
Собери все результаты в один список. Проверь на дубликаты:
- По имени — один и тот же мастер на разных площадках
- По телефону — если виден в нескольких профилях
- По фото — одна и та же фотография профиля
При обнаружении дубликата — объединяй данные из всех площадок в одну карточку.
Шаг 8: Скоринг
Рассчитай оценку для каждого исполнителя:
| Критерий | Вес | Как оценивать |
|---|---|---|
| Рейтинг | 30% | (рейтинг / 5) * 100 — баллы от 0 до 100 |
| Количество отзывов | 20% | min(отзывы / 50, 1) * 100 — максимум при 50+ отзывах |
| Соответствие цене | 20% | Насколько цена вписывается в бюджет пользователя |
| Время ответа | 15% | < 30 мин = 100, < 1 час = 80, < 3 часа = 60, > 3 часов = 40 |
| Верификация | 15% | Верифицирован на платформе = 100, нет = 30 |
Итоговый балл = 0.30 * рейтинг_балл + 0.20 * отзывы_балл + 0.20 * цена_балл + 0.15 * ответ_балл + 0.15 * верификация_балл
Шаг 9: Вывод результатов
Покажи топ-10 исполнителей в таблице:
НАЙДЕНЫ ПОДРЯДЧИКИ: [тип услуги] в [город]
Поиск: Profi.ru, Avito Услуги, Яндекс.Услуги, YouDo
+----+------------------+------------+---------+--------+-----------+--------+
| # | Имя | Рейтинг | Отзывы | Цена | Ответ | Площ. |
+----+------------------+------------+---------+--------+-----------+--------+
| 1 | Иванов А.С. | 4.9 (*) | 127 | от 3000| < 30 мин | Profi |
| 2 | Петров В.М. | 4.8 (*) | 89 | от 2500| < 1 час | Avito |
| 3 | Сидоров К.Н. | 4.7 (*) | 203 | от 3500| < 30 мин | Profi+ |
+----+------------------+------------+---------+--------+-----------+--------+
(*) — верифицированный исполнитель
Profi+ — найден на нескольких площадках (дедуплицирован)
Показаны топ-3 из 47 найденных.
Для полного списка скажи «покажи всех».
Для детальной информации скажи «подробнее о #1».
Workflow 2: Анализ портфолио
Шаг 1: Открыть профиль
# По ссылке от пользователя
browser-use --headed open "URL_ПРОФИЛЯ"
sleep 4
# Или по имени — сначала найти через поиск
browser-use --headed open "https://profi.ru/search/?q=ИМЯ+ФАМИЛИЯ"
sleep 4
Шаг 2: Извлечь фото портфолио
# Получить URL всех фото в портфолио
browser-use eval "JSON.stringify(Array.from(document.querySelectorAll('[class*=\"portfolio\"] img, [class*=\"gallery\"] img, [class*=\"work-sample\"] img, [class*=\"photo\"] img')).slice(0,20).map(img => ({src: img.src, alt: img.alt || ''})))"
Шаг 3: Анализ каждого фото
Для каждого фото используй image_analysis:
image_analysis:
imageSource: [URL фото]
prompt: "Оцени качество выполненной работы на этом фото. Определи: качество материалов, аккуратность исполнения, соответствует ли заявленной категории услуг. Оцени от 1 до 10. Укажи: что сделано хорошо, что можно улучшить."
Шаг 4: Сводная оценка портфолио
АНАЛИЗ ПОРТФОЛИО: [Имя исполнителя]
Площадка: [Profi.ru / Avito / Яндекс.Услуги / YouDo]
Фото проанализировано: [N] из [M]
Средняя оценка качества: X.X / 10
Распределение:
- Отлично (8-10): N фото (XX%)
- Хорошо (6-7): N фото (XX%)
- Средне (4-5): N фото (XX%)
- Плохо (1-3): N фото (XX%)
Сильные стороны:
- [конкретные наблюдения]
Слабые стороны:
- [конкретные наблюдения]
Вердикт: [Высокое / Среднее / Низкое] качество работ.
Рекомендация: [стоит нанимать / с осторожностью / не рекомендуется]
Workflow 3: Проверка репутации
Шаг 1: Поиск отзывов
# Поиск отзывов через web_search
web_search "ИМЯ_ИСПОЛНИТЕЛЯ отзывы ГОРОД"
web_search "ИМЯ_ИСПОЛНИТЕЛЯ мошенчик обман ГОРОД"
web_search "ИМЯ_ИСПОЛНИТЕЛЯ Profi.ru Avito отзывы"
Шаг 2: Проверка на сайтах отзывов
# Прочитать страницу отзывов
web_reader "https://otzovik.com/search/?q=ИМЯ_ИСПОЛНИТЕЛЯ"
web_reader "https://irecommend.ru/search?query=ИМЯ_ИСПОЛНИТЕЛЯ"
Шаг 3: Проверка через web_search
# Поиск жалоб
web_search "ИМЯ_ИСПОЛНИТЕЛЯ жалоба Роспотребнадзор"
web_search "ИМЯ_ИСПОЛНИТЕЛЯ суд иск некачественные услуги"
# Поиск на форумах
web_search "ИМЯ_ИСПОЛНИТЕЛЯ forum отзыв опыт"
Шаг 4: Сводка репутации
ПРОВЕРКА РЕПУТАЦИИ: [Имя исполнителя]
Отзывы на площадках:
- Profi.ru: X.X (N отзывов)
- Avito: X.X (N отзывов)
- Яндекс.Услуги: X.X (N отзывов)
- YouDo: X.X (N отзывов)
Внешние источники:
- otzovik.com: [найдено / не найдено]
- irecommend.ru: [найдено / не найдено]
- Форумы: [найдено / не найдено]
Красные флаги:
- [список или «Не обнаружено»]
Частая похвала:
- [топ-3 позитивных темы в отзывах]
Общий настрой отзывов: [Положительный / Смешанный / Отрицательный]
Рекомендация: [Высокая надёжность / Средняя / Есть риски / Не рекомендуется]
Workflow 4: Связь и бронирование
Шаг 1: Генерация сообщения
Составь персонализированное сообщение на основе требований пользователя:
Здравствуйте, [Имя мастера]!
Меня интересует [тип услуги]. Детали:
- Адрес: [район/адрес]
- Объём работ: [описание]
- Желаемые сроки: [когда]
- Бюджет: [диапазон]
Подскажите, когда сможете посмотреть объект и оценить стоимость?
Шаг 2: Навигация к форме связи
# Открыть профиль исполнителя
browser-use --headed open "URL_ПРОФИЛЯ"
sleep 4
# Найти кнопку связи
browser-use state
# Или через eval:
browser-use eval "JSON.stringify(Array.from(document.querySelectorAll('button, a')).filter(el => /написать|связаться|заказать|сообщение|заказать/i.test(el.textContent)).map(el => ({text: el.textContent.trim(), tag: el.tagName})))"
Шаг 3: Заполнение формы
# Кликнуть кнопку связи
browser-use click "text=Написать"
# Заполнить сообщение
browser-use type "Здравствуйте, ..."
# Заполнить телефон (ТОЛЬКО если пользователь разрешил!)
# НИКОГДА не вводи телефон/email без явного подтверждения пользователя
Шаг 4: Подтверждение перед отправкой
КРИТИЧЕСКОЕ ПРАВИЛО: Никогда не отправляй сообщение без подтверждения пользователя!
ГОТОВО К ОТПРАВКЕ:
Кому: [Имя мастера] на [Платформа]
Сообщение:
---
[текст сообщения]
---
Отправить? (Да / Нет / Изменить)
Только после ответа «Да» — нажимай кнопку отправки.
Шаг 5: Отправка
browser-use click "text=Отправить"
sleep 2
browser-use state
Шаг 6: Отслеживание отправленных запросов
Храни список отправленных запросов в контексте:
SENT_INQUIRIES:
1. [Имя мастера] | [Платформа] | [Дата] | [Статус: отправлено/ответ получен]
2. [Имя мастера] | [Платформа] | [Дата] | [Статус: отправлено/ожидает]
Workflow 5: Оценка стоимости услуг
Шаг 1: Сбор рыночных цен
# Поиск текущих цен
web_search "ремонт квартир цена ГОРОД 2026 за м²"
web_search "стоимость услуг электрика ГОРОД 2026"
web_search "[тип услуги] расценки прайс ГОРОД"
Шаг 2: Чтение прайс-листов
# Прочитать страницу с ценами
web_reader "https://profi.ru/ГОРОД/remont/kalkulyator/"
web_reader "https://uslugi.yandex.ru/calc/[категория]"
Шаг 3: Сравнение с предложением подрядчика
ОЦЕНКА СТОИМОСТИ: [тип услуги] в [город]
Рыночный диапазон:
- Минимум: X XXX ₽
- Среднее: X XXX ₽
- Максимум: X XXX ₽
Предложение подрядчика: X XXX ₽
Позиция на рынке: [Ниже рынка / В пределах нормы / Выше рынка]
Если значительно ниже рынка:
ВНИМАНИЕ: Цена значительно ниже рыночной. Возможные причины:
- Недостаточный опыт
- Скрытые доплаты
- Некачественные материалы
Рекомендация: уточните, что включено в стоимость
Если значительно выше рынка:
Проверьте, что входит в стоимость:
- Материалы
- Гарантия
- Уборка после работ
- Срочность
Шаг 4: Факторы, влияющие на цену
| Фактор | Влияние на цену |
|---|---|
| Срочность (сегодня/завтра) | +20-50% |
| Выходные / праздники | +20-30% |
| Центр города | +10-20% |
| Высотные работы | +30-100% |
| Демонтаж старого | +15-30% |
| Вывоз мусора | +5-15% |
| Гарантия на работы | +10-20% |
| Закупка материалов подрядчиком | +10-25% (наценка) |
JavaScript Eval-сниппеты
Универсальные проверки
# Сколько результатов на странице?
browser-use eval "document.querySelectorAll('[class*=\"card\"], [class*=\"item\"], [class*=\"result\"]').length"
# Название первого результата
browser-use eval "document.querySelector('[class*=\"name\"], [class*=\"title\"], h3')?.textContent?.trim()"
# Рейтинг первого результата
browser-use eval "document.querySelector('[class*=\"rating\"], [class*=\"stars\"]')?.textContent?.trim()"
# Есть ли кнопка для связи?
browser-use eval "!!document.querySelector('button, a')?.textContent?.match(/написать|связаться|заказать/i)"
# Закрыть модальное окно
browser-use eval "document.querySelector('[class*=\"modal\"], [class*=\"popup\"]')?.querySelector('[class*=\"close\"], [aria-label=\"Закрыть\"]')?.click()"
Profi.ru — детальное извлечение
# Полная карточка мастера
browser-use eval "const c = document.querySelector('[class*=\"card\"]'); JSON.stringify({name: c?.querySelector('[class*=\"name\"]')?.textContent?.trim(), rating: c?.querySelector('[class*=\"rating\"]')?.textContent?.trim(), reviews: c?.querySelector('[class*=\"count\"]')?.textContent?.trim(), price: c?.querySelector('[class*=\"price\"]')?.textContent?.trim(), link: c?.querySelector('a')?.href})"
# Время ответа
browser-use eval "document.querySelector('[class*=\"response\"], [class*=\"reply\"]')?.textContent?.trim()"
# Портфолио — количество фото
browser-use eval "document.querySelectorAll('[class*=\"portfolio\"] img').length"
# Все отзывы на странице
browser-use eval "JSON.stringify(Array.from(document.querySelectorAll('[class*=\"review\"]')).slice(0,10).map(r => r.textContent?.trim()?.substring(0, 200)))"
Avito — детальное извлечение (с оглядкой на антибот)
# Цена из мета-данных
browser-use eval "document.querySelector('[itemprop=\"price\"]')?.getAttribute('content') || document.querySelector('[class*=\"price\"]')?.textContent?.trim()"
# Дата регистрации продавца
browser-use eval "document.querySelector('[class*=\"registration\"], [class*=\"member-since\"]')?.textContent?.trim()"
# Количество объявлений у продавца
browser-use eval "document.querySelector('[class*=\"count\"], [class*=\"total\"]')?.textContent?.match(/\\d+/)?.[0]"
# Все фото в объявлении
browser-use eval "JSON.stringify(Array.from(document.querySelectorAll('[class*=\"photo\"] img, [class*=\"gallery\"] img')).slice(0,10).map(i => i.src))"
Яндекс.Услуги — детальное извлечение
# Статус верификации
browser-use eval "document.querySelector('[class*=\"verified\"], [class*=\"badge\"], [class*=\"confirm\"]')?.textContent?.trim() || 'Не верифицирован'"
# Диапазон цен
browser-use eval "JSON.stringify({min: document.querySelector('[class*=\"price-min\"]')?.textContent?.trim(), max: document.querySelector('[class*=\"price-max\"]')?.textContent?.trim(), text: document.querySelector('[class*=\"price\"]')?.textContent?.trim()})"
# Категории услуг мастера
browser-use eval "JSON.stringify(Array.from(document.querySelectorAll('[class*=\"category\"], [class*=\"tag\"]')).map(c => c.textContent?.trim()))"
YouDo — детальное извлечение
# Выполненные задачи
browser-use eval "document.querySelector('[class*=\"completed\"]')?.textContent?.match(/\\d+/)?.[0]"
# Рейтинг и отзывы
browser-use eval "JSON.stringify({rating: document.querySelector('[class*=\"rating\"]')?.textContent?.trim(), reviews: document.querySelector('[class*=\"review-count\"]')?.textContent?.trim()})"
# Навыки / специализации
browser-use eval "JSON.stringify(Array.from(document.querySelectorAll('[class*=\"skill\"], [class*=\"tag\"]')).map(s => s.textContent?.trim()))"
Обнаружение мошенничества
При анализе профилей проверяй на красные флаги:
| Признак | Описание | Уровень риска |
|---|---|---|
| Слишком низкая цена | Цена на 50%+ ниже рынка | Высокий |
| Нет отзывов | Ни одного отзыва при «большом опыте» | Средний |
| Требует предоплату 100% | Просит полную оплату до начала работ | Высокий |
| Нет реального адреса | Только «выезд по городу», без офиса | Низкий |
| Недавняя регистрация | Аккаунт создан менее месяца назад | Средний |
| Одинаковые отзывы | Текст отзывов шаблонный или идентичный | Высокий |
| Нет портфолио | При «10+ лет опыта» нет фото работ | Средний |
| Давление срочностью | «Только сегодня», «Цена действует 1 час» | Высокий |
| Отказ от договора | Не хочет оформлять договор | Высокий |
| Только наличные | Отказ от безналичной оплаты | Средний |
Проверка подозрительного подрядчика
# Поиск информации о мошенничестве
web_search "ИМЯ_ИСПОЛНИТЕЛЯ мошенник обман"
web_search "ИМЯ_ИСПОЛНИТЕЛЯ кидалово отзывы"
web_search "НОМЕР_ТЕЛЕФОНА мошенник услуги"
При обнаружении высокого риска — предупреди пользователя:
ВНИМАНИЕ: Обнаружены красные флаги!
Подрядчик: [Имя]
Площадка: [Название]
Красные флаги:
- [список обнаруженных признаков]
Рекомендация: НЕ НАНИМАТЬ без дополнительной проверки.
Если решите продолжить:
1. Не вносите предоплату более 30%
2. Оформите письменный договор
3. Зафиксируйте объём работ и сроки
4. Сделайте фото объекта до начала работ
Правила: state vs eval
Делай state
- Первый раз при работе с каждой площадкой (определить структуру)
- Когда eval возвращает неожиданный результат (DOM изменился)
- При навигации на новую страницу (поиск -> профиль)
- Когда нужно найти индекс элемента для click
- При появлении модальных окон
НЕ делай state
- Для получения цены (используй eval)
- Для получения имени (используй eval)
- Для проверки загрузки страницы (используй eval)
- Для извлечения списков (используй eval)
- Между одинаковыми операциями на одной странице
- ОСОБЕННО на Avito — антибот-защита реагирует на частые state-вызовы
Быстрые eval-проверки вместо state
# Загрузились результаты?
browser-use eval "document.querySelectorAll('[class*=\"card\"], [class*=\"item\"]').length > 0"
# Цена первого результата
browser-use eval "document.querySelector('[class*=\"price\"]')?.textContent?.trim()"
# Название первого результата
browser-use eval "document.querySelector('[class*=\"name\"], [class*=\"title\"]')?.textContent?.trim()?.substring(0, 100)"
# Есть ли модальное окно?
browser-use eval "!!document.querySelector('[class*=\"modal\"], [class*=\"popup\"]')"
Правила безопасности
Никогда не делай
- НЕ отправляй формы без подтверждения пользователя — всегда показывай текст и спрашивай «Отправить?»
- НЕ вводи телефон/email пользователя автоматически — только после явного разрешения
- НЕ сохраняй платёжные данные — никаких реквизитов карт
- НЕ нажимай «Оплатить» или «Забронировать» (если это требует оплаты) без подтверждения
- НЕ авторизуйся от имени пользователя — если нужна авторизация, попроси пользователя войти вручную
Всегда делай
- Всегда закрывай браузер после завершения:
browser-use close --all - Всегда используй
--headedрежим — пользователь должен видеть что происходит - Закрывай модальные окна перед любыми действиями на странице
- Обрабатывай одну площадку за раз — не открывай несколько вкладок
- Проверяй на капчу и проси пользователя пройти вручную при необходимости
Формат вывода для compartir
Результаты поиска можно показать в формате для шаринга:
НАЙДЕНО С AGENTHERE.RU
Подрядчики: [тип услуги] в [город]
Дата: [Сегодня]
Топ-5 по рейтингу:
1. [Имя] | 4.9 (*) | 127 отзывов | от 3 000 ₽
Площадки: Profi.ru, Яндекс.Услуги
Специализация: [описание]
Ответ: < 30 мин
2. [Имя] | 4.8 | 89 отзывов | от 2 500 ₽
Площадки: Avito
Специализация: [описание]
Ответ: < 1 час
...
Рыночная цена: 2 000 — 8 000 ₽
Лучшее соотношение цена/качество: #[N]
agenthere.ru — ваш AI-ассистент для поиска подрядчиков
Обработка ошибок
| Проблема | Решение |
|---|---|
| CAPTCHA на Avito | Подожди 30-60 сек, обнови. Попроси пользователя пройти вручную в headed-режиме |
| Пустые результаты на площадке | Упрости запрос, попробуй другую формулировку, расширь географию |
| Страница не загружается | Увеличь sleep до 5-6 сек. Тяжёлые SPA. Проверь интернет. |
| Селекторы не работают | Сделай browser-use state для актуальной DOM-структуры. Селекторы меняются. |
| Модальное окно блокирует | Закрой через eval: document.querySelector('[class*="close"]')?.click() или Escape |
| Сессия зависла | browser-use close --all, начни заново |
| Цены не отображаются | Многие исполнители не указывают цену. Это нормально — укажи «Цена по запросу» |
| Дубликаты в результатах | Дедуплицируй по имени и номеру телефона. Объедини данные с разных площадок. |
| Профиль недоступен | Объявление может быть снято. Перейди к следующему результату. |
| Авторизация требуется | Попроси пользователя войти вручную в открытом браузере |
| Anti-bot на Avito | Минимизируй state-вызовы, делай паузы между действиями 3-5 сек |
| Яндекс.Услуги показывает мало результатов | Попробуй другую формулировку запроса или категорию напрямую |
| YouDo не загружает список | YouDo тяжёлый SPA — подожди 5 сек. Проверь через eval наличие элементов |
| Некорректные символы в URL | Кодируй кириллицу: encodeURI('сантехник') → %D1%81%D0%B0%D0%BD%D1%82%D0%B5%D1%85%D0%BD%D0%B8%D0%BA |
| Element not found после навигации | DOM перерисовался — сделай state заново для свежих индексов |
Оптимизация для повторных запросов
Если пользователь ищет несколько подрядчиков подряд:
- Не закрывай браузер между поисками — переходи по новому URL
- Используй один профиль для сохранения авторизации:
browser-use --profile "contractor-search" - Кешируй структуру DOM — если площадка не обновлялась, селекторы те же
- Группируй запросы — если 3+ категории, спрашивай «Искать все сразу или по очереди?»
- Сохраняй контекст — предыдущие результаты могут помочь с дедупликацией
Cleanup
# Закрыть текущую вкладку
browser-use close
# Закрыть ВСЕ сессии (использовать после завершения работы)
browser-use close --all
Советы
- Всегда
close --allпервым — старые сессии — причина зависаний - Жди 4-5 секунд после навигации — все площадки тяжёлые SPA
- Проверяй модалки перед любыми действиями — особенно на Avito
- Используй eval вместо state — eval в 10 раз быстрее и не забивает контекст
- Дедуплицируй — хороший мастер часто на 2-3 площадках
- Проверяй репутацию — даже при высоком рейтинге на площадке, гугли отзывы
- Сравнивай с рынком — слишком низкая цена = красный флаг
- Никогда не отправляй сообщения без подтверждения пользователя
- Анализируй портфолио через image_analysis — фото говорят больше отзывов
- Начинай с Profi.ru — там больше данных и лучше фильтрация