# ПлюсАгент. ТЗ на импорт объявлений со сторонних площадок
Данное ТЗ описывает процесс загрузки объявлений с классифайдов "Авито" и "Циан" для платформы ПлюсАгент.
## Прототип
Прототип доступен по [ссылке](https://www.figma.com/proto/Gs4n0ZHP3m9mdUcwDAqXpf/PlusAgentNew-%D0%98%D0%BC%D0%BF%D0%BE%D1%80%D1%82-%D0%BE%D0%B1%D1%8A%D1%8F%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F?node-id=1%3A2&scaling=min-zoom). На первом экране необходимо нажать на ссылку "загрузить из площадки объявлений".
Далее приведён перечень возможных вопросов и ответов по данному прототипу.
#### На втором экране прототипа пользователю предлагается ввести ссылку. Какие правила валидации этого поля?
Поле не должно быть пустым. Поле должно содержать ссылку; если опущен протокол (`https://` или `http://`), подставлять `https://`. Если вставлена некорректная ссылка, вывести ошибку валидации *"Указана неправильная ссылка"*. Возможные домены: `avito.ru` и `cian.ru` (а также `www.avito.ru`, `www.cian.ru`). Если указан некорректный домен, вывести ошибку валидации *"Укана ссылка на неподдерживаемую площадку объявлений. К сожалению, на данный момент невозможно загрузить это объявление."*.
#### Что делать, если ссылка содержит некорректное объявление?
Действительно, система на данный момент поддерживает не все типы (и категории) объявлений. Кроме того, на сайтах Циан, и тем более Авито большое количество "неподходящих страниц". Поэтому процесс парсинга необходимо разделить на две стадии - проверка страницы и загрузка данных.
Проверка страницы приблизительно сводится к двум шагам:
1. Определить, является ли данная страница объявлением по недвижимости. В случае, если нет, вывести ошибку валидации *"Указаная ссылка не содержит объявление по недвижимости"*. Это можно сделать, например, по URL-адресу.
2. Определить, имеет ли объявление нужный тип (и категорию) объявления. При проверки типа иметь ввиду, что список поддерживаемых типов будет расширяться (см. раздел ["Нефункциональные требования"](#Нефункциональные-требования), пункт 1)
#### На третьем экране поля формы (Категория, Тип, Адрес) уже заполнены. Подразумевается, что это сделал пользователь, или система сама заполнила поля?
Подразумевается, что система заполнила поля сама. Поля "Категория" и "Тип" система уже определила, так как объявление должно было пройти проверку (см. предущий вопрос).
Поле "Адрес" можно заполнить следующим образом:
1. Получить координаты объекта из объявления (для этого нужно будет понять, как получить их из карты)
2. Отправить координаты в геокодер (сервис реализован в классе `HereMapsGeocodeService`) и подставить полученный адрес
Если получить координаты из карты не получится, можно отправлять в геокодер строковое представление адреса.
#### На третьем экране формы содержится название объявления. Как его получить?
Необходимо спарсить тег `<title>` и убрать оттуда упоминание площадки. Примеры:
- Заголовок `Продаю многокомнатную квартиру 259м² Университетская ул., 9, Сургут, Ханты-Мансийский АО, мкр. 19-й - база ЦИАН, объявление 205254965` нужно привести к `Продаю многокомнатную квартиру 259м² Университетская ул., 9, Сургут, Ханты-Мансийский АО, мкр. 19-й`,
- Заголовок `Коттедж 385.9 м² на участке 3 сот. в Сургуте | Недвижимость | Авито` привести к `Коттедж 385.9 м² на участке 3 сот. в Сургуте`
## Дополнительные сведения
### Поля для объявлений на площадках
Список полей можно определить по формату XML-импорта площадок:
- [Формат XML Циан](https://www.cian.ru/xml_import/doc/#common_cat)
- [Формат XML Авито](https://autoload.avito.ru/format/realty/)
### Примеры объявлений для парсинга
Ниже перечислены наиболее заполненные объявления типов "Квартира" и "Дом" на площадках.
- [Циан, квартира](https://surgut.cian.ru/sale/flat/205254965/). Обратить внимание на раздел "Общая информация" и "О доме"
- [Циан, дом](https://surgut.cian.ru/sale/suburban/233379163/). Обратить внимание на раздел "Общая информация"
- [Авито, квартира](https://www.avito.ru/surgut/kvartiry/6-k_kvartira_210_m_55_et._1264724113)
- [Авито, дом](https://www.avito.ru/surgut/doma_dachi_kottedzhi/kottedzh_385.9_m_na_uchastke_3_sot._1932985260)
В случае удаления перечисленных объявлений можно [скачать сохраненные версии страниц](https://gofile.io/d/J3cZzJ).
## Нефункциональные требования
#### 1. Архитектура парсинга должна быть расширяемой
Решение должно быть спроектировано таким образом, чтобы в дальнейшем можно было быстро добавить:
- парсинг других типов объявлений, в частности "Гаражи" и "Коммерческая недвижимость"
- другие площадки объявлений
#### 2. Логика загрузки страниц должен быть выделена в отдельный сервис
В дальнейшем, возможно, придётся усложнять логику загрузки (т. е. код, получающий html-код страницы объявления). Например, Циан периодически показывает капчу вместо страницы, и необходимо будет закупить пул прокси-адресов и делать запросы через них. Эта логика не связана с предметной областью и должна быть выделена в отдельный сервис снаружи `domain`-слоя.
## Рекоммендации по выполнению
#### Библиотека cheerio
Для непосредственно извлечения данных из html-страницы можно использовать библиотеку [cheerio](https://github.com/cheeriojs/cheerio). Она предоставляет знакомый jQuery-синтаксис, который позволяет с помощью css-селекторов быстро извлечь нужные данные из DOM-дерева.