Оценка стоимости помещения для продажи, аренды и налогообложения

Оценка стоимости помещения от Первого бюро Оценки и Экспертизы

Коммерческая недвижимость — актив, в котором каждая деталь имеет значение: местоположение, планировка, техническое состояние, спрос на рынке и даже имидж владельца. Когда приходит время продать, сдать в аренду или рассчитать налоговую базу, без профессиональной оценки стоимости помещения

Получаем много виртуальных карт

Получаем много виртуальных карт

Регестрируем множество карт почти бесплатно!

Избавляемся от продуктов априори – использование ассоциативных правил для поиска комбинаций

Я очень люблю готовить, поэтому постоянно закупаюсь ингредиентами для различных блюд. Однако, в последний раз я закупил их слишком много, теперь срок их годности подходит к концу. Но не выкидывать же продукты в мусорную корзину? Конечно, я бы мог использовать их все разом, но вряд ли блюдо в таком случае получится вкусным. Или же приготовить множес…

5

Как создать VK-бот Дед Мороз для розыгрышей — пошаговый гайд

Как создать VK-бот Дед Мороз для розыгрышей — пошаговый гайд

Новый год — время подарков. Но если вы арбитражник — это время еще и для того, чтобы собирать сливки. Новогодний VK-бот для розыгрышей Дед Мороз совмещает в себе и то и другое, а заодно соберет информацию о пользователях, чтобы ваши рекламные кампании в 2023-м были еще эффективнее.

Текст-майнинг с пандами, облаками и яблоками

Представьте ситуацию: вас назначили спикером на мероприятии, и вы даже знаете, о чем хотите рассказать аудитории. Но будет ли публикой воспринят ваш доклад так, как вы себе это представляли? Давайте посмотрим, что может пойти не так и как это исправить.

Как часто нам приходится выступать с докладом, презентацией, проводить обучение, быть спик…

2

Как работать с Binance Smart Chain (BEP20) используя python

В этой статье я вкратце расскажу как работать с Ether-based блокчейнами на примере Binance Smart Chain
Первым делом необходимо установить модуль web3. Модуль web3 предоставляет API для взаимодействия между приложениями разработанными на Python и блокчейном Ethereum (BSC и проч.)

pip install web3
4

Вместо трех дней — 10 минут: как автоматизировать проверку товарных остатков и остановку/запуск контекстной рекламы

Привет! Я Владимир Малюгин, CEO агентства performance-маркетинга Digital Geeks. Мы активно автоматизируем процессы: это удобно и выгодно. В статье я расскажу, как создать алгоритм, который проверяет наличие товаров в десятке маркетплейсов. А затем останавливает или запускает контекстную рекламу без участия человека.

Внутри — код и пошаговая…

17

Telegram-бот для получения адреса по локации или координатам (Python)

Привет! Представь ситуацию, когда тебе скинули координаты или локацию, но ты хочешь срочно узнать адрес этого места.

Сегодня попробуем написать Telegram-бота для получения адреса по координатам или локации.

13

Как найти однотипную информацию в большом количестве файлов, используя Python?

Недавно мы решали следующую задачу – необходимо найти и удалить содержащие номера карт файлы, размещенные на общем ресурсе. Если нужно было бы искали что-то, определенное и однозначное, мы могли бы воспользоваться поиском в самой операционной системе (используя стандартны поиск текста в содержимом файла). Но, как правило, поиск стандартными средств…

5

Web Parsing. Основы на Python

Рассмотрим еще один практический кейс парсинга сайтов с помощью библиотеки BeautifulSoup: что делать, если на сайте нет готовой выгрузки с данными и нет API для удобной работы, а страниц для ручного копирования очень много?

Web Parsing. Основы на Python
7

Оценка стоимости помещения для продажи, аренды и налогообложения

Оценка стоимости помещения от Первого бюро Оценки и Экспертизы

Коммерческая недвижимость — актив, в котором каждая деталь имеет значение: местоположение, планировка, техническое состояние, спрос на рынке и даже имидж владельца. Когда приходит время продать, сдать в аренду или рассчитать налоговую базу, без профессиональной оценки стоимости помещения

Получаем много виртуальных карт

Получаем много виртуальных карт

Регестрируем множество карт почти бесплатно!

Избавляемся от продуктов априори – использование ассоциативных правил для поиска комбинаций

Я очень люблю готовить, поэтому постоянно закупаюсь ингредиентами для различных блюд. Однако, в последний раз я закупил их слишком много, теперь срок их годности подходит к концу. Но не выкидывать же продукты в мусорную корзину? Конечно, я бы мог использовать их все разом, но вряд ли блюдо в таком случае получится вкусным. Или же приготовить множес…

5

Как создать VK-бот Дед Мороз для розыгрышей — пошаговый гайд

Как создать VK-бот Дед Мороз для розыгрышей — пошаговый гайд

Новый год — время подарков. Но если вы арбитражник — это время еще и для того, чтобы собирать сливки. Новогодний VK-бот для розыгрышей Дед Мороз совмещает в себе и то и другое, а заодно соберет информацию о пользователях, чтобы ваши рекламные кампании в 2023-м были еще эффективнее.

Текст-майнинг с пандами, облаками и яблоками

Представьте ситуацию: вас назначили спикером на мероприятии, и вы даже знаете, о чем хотите рассказать аудитории. Но будет ли публикой воспринят ваш доклад так, как вы себе это представляли? Давайте посмотрим, что может пойти не так и как это исправить.

Как часто нам приходится выступать с докладом, презентацией, проводить обучение, быть спик…

2

Как работать с Binance Smart Chain (BEP20) используя python

В этой статье я вкратце расскажу как работать с Ether-based блокчейнами на примере Binance Smart Chain
Первым делом необходимо установить модуль web3. Модуль web3 предоставляет API для взаимодействия между приложениями разработанными на Python и блокчейном Ethereum (BSC и проч.)

pip install web3
4

Вместо трех дней — 10 минут: как автоматизировать проверку товарных остатков и остановку/запуск контекстной рекламы

Привет! Я Владимир Малюгин, CEO агентства performance-маркетинга Digital Geeks. Мы активно автоматизируем процессы: это удобно и выгодно. В статье я расскажу, как создать алгоритм, который проверяет наличие товаров в десятке маркетплейсов. А затем останавливает или запускает контекстную рекламу без участия человека.

Внутри — код и пошаговая…

17

Telegram-бот для получения адреса по локации или координатам (Python)

Привет! Представь ситуацию, когда тебе скинули координаты или локацию, но ты хочешь срочно узнать адрес этого места.

Сегодня попробуем написать Telegram-бота для получения адреса по координатам или локации.

13

Как найти однотипную информацию в большом количестве файлов, используя Python?

Недавно мы решали следующую задачу – необходимо найти и удалить содержащие номера карт файлы, размещенные на общем ресурсе. Если нужно было бы искали что-то, определенное и однозначное, мы могли бы воспользоваться поиском в самой операционной системе (используя стандартны поиск текста в содержимом файла). Но, как правило, поиск стандартными средств…

5

Web Parsing. Основы на Python

Рассмотрим еще один практический кейс парсинга сайтов с помощью библиотеки BeautifulSoup: что делать, если на сайте нет готовой выгрузки с данными и нет API для удобной работы, а страниц для ручного копирования очень много?

Web Parsing. Основы на Python
7
Что теперь?`[index] ==\"Нет в наличии\" )\n {\n ads_to_stop <-rbind(ads_to_stop,my_camp$Id[i])\n }\n if (surveyresults

Оценка стоимости помещения для продажи, аренды и налогообложения

Оценка стоимости помещения от Первого бюро Оценки и Экспертизы

Коммерческая недвижимость — актив, в котором каждая деталь имеет значение: местоположение, планировка, техническое состояние, спрос на рынке и даже имидж владельца. Когда приходит время продать, сдать в аренду или рассчитать налоговую базу, без профессиональной оценки стоимости помещения

Получаем много виртуальных карт

Получаем много виртуальных карт

Регестрируем множество карт почти бесплатно!

Избавляемся от продуктов априори – использование ассоциативных правил для поиска комбинаций

Я очень люблю готовить, поэтому постоянно закупаюсь ингредиентами для различных блюд. Однако, в последний раз я закупил их слишком много, теперь срок их годности подходит к концу. Но не выкидывать же продукты в мусорную корзину? Конечно, я бы мог использовать их все разом, но вряд ли блюдо в таком случае получится вкусным. Или же приготовить множес…

5

Как создать VK-бот Дед Мороз для розыгрышей — пошаговый гайд

Как создать VK-бот Дед Мороз для розыгрышей — пошаговый гайд

Новый год — время подарков. Но если вы арбитражник — это время еще и для того, чтобы собирать сливки. Новогодний VK-бот для розыгрышей Дед Мороз совмещает в себе и то и другое, а заодно соберет информацию о пользователях, чтобы ваши рекламные кампании в 2023-м были еще эффективнее.

Текст-майнинг с пандами, облаками и яблоками

Представьте ситуацию: вас назначили спикером на мероприятии, и вы даже знаете, о чем хотите рассказать аудитории. Но будет ли публикой воспринят ваш доклад так, как вы себе это представляли? Давайте посмотрим, что может пойти не так и как это исправить.

Как часто нам приходится выступать с докладом, презентацией, проводить обучение, быть спик…

2

Как работать с Binance Smart Chain (BEP20) используя python

В этой статье я вкратце расскажу как работать с Ether-based блокчейнами на примере Binance Smart Chain
Первым делом необходимо установить модуль web3. Модуль web3 предоставляет API для взаимодействия между приложениями разработанными на Python и блокчейном Ethereum (BSC и проч.)

pip install web3
4

Вместо трех дней — 10 минут: как автоматизировать проверку товарных остатков и остановку/запуск контекстной рекламы

Привет! Я Владимир Малюгин, CEO агентства performance-маркетинга Digital Geeks. Мы активно автоматизируем процессы: это удобно и выгодно. В статье я расскажу, как создать алгоритм, который проверяет наличие товаров в десятке маркетплейсов. А затем останавливает или запускает контекстную рекламу без участия человека.

Внутри — код и пошаговая…

17

Telegram-бот для получения адреса по локации или координатам (Python)

Привет! Представь ситуацию, когда тебе скинули координаты или локацию, но ты хочешь срочно узнать адрес этого места.

Сегодня попробуем написать Telegram-бота для получения адреса по координатам или локации.

13

Как найти однотипную информацию в большом количестве файлов, используя Python?

Недавно мы решали следующую задачу – необходимо найти и удалить содержащие номера карт файлы, размещенные на общем ресурсе. Если нужно было бы искали что-то, определенное и однозначное, мы могли бы воспользоваться поиском в самой операционной системе (используя стандартны поиск текста в содержимом файла). Но, как правило, поиск стандартными средств…

5

Web Parsing. Основы на Python

Рассмотрим еще один практический кейс парсинга сайтов с помощью библиотеки BeautifulSoup: что делать, если на сайте нет готовой выгрузки с данными и нет API для удобной работы, а страниц для ручного копирования очень много?

Web Parsing. Основы на Python
7
Что теперь?`[index] ==\"Товар в наличии\" )\n {\n ads_to_start <-rbind(ads_to_start,my_camp$Id[i])\n }\n }\n \n i <- i+1\n \n}\n\n\nif (length(ads_to_start)>0)\n{\n colnames(ads_to_start) <- c(\"Campaign\")\n #Возобнолвям показы объявлений для Товар наличии\n err <- yadirStartAds(Login = accounts[1],\n AgencyAccount = \"login@yandex.ru\",\n Ids = ads_to_start$Campaign) \n}\n\nif (length(ads_to_stop)>0)\n{\n colnames(ads_to_stop) <- c(\"Campaign\")\n # #Останавливаем показы объявлений для товаров НЕТ в наличии\n err <- yadirStopAds(Login = accounts[1],\n AgencyAccount = \"login@yandex.ru\",\n Ids = ads_to_stop$Campaign) \n}","lang":""}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"Как настроить отправку данных в мессенджер?"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Чтобы контекстолог не тратил время на проверку таблицы, мы настроили автоматическое оповещение в Telegram. Это можно сделать с помощью сервиса для автоматизации Make (прежнее название — Integromat). Это no-code платформа с интуитивно-понятным интерфейсом. Для работы с ней не нужно уметь программировать — достаточно понимать структуру и логику соединяемых систем, а также знать английский язык, чтобы читать названия полей сервиса.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Публикую пошаговый визуал по настройке рассылки в Make.

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"Первый шаг: создаем триггер — ссылку, по которой переходит парсер после завершения проверки остатков. Это позволяет сразу же запустить следующий этап работы алгоритма","image":{"type":"image","data":{"uuid":"552d27a0-b93a-562b-a5e4-fbf5cc847151","width":621,"height":383,"size":18205,"type":"png","color":"f4f3f3","hash":"","external_service":[]}}}]}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"Второй шаг: проверяем, есть ли изменения статусов товаров в Google Sheets","image":{"type":"image","data":{"uuid":"7d396c26-eb7d-5a75-8564-9ab03b775a59","width":1145,"height":849,"size":36441,"type":"png","color":"f7f7f7","hash":"","external_service":[]}}}]}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"Третий шаг: настраиваем отправку сообщений в чат о том, что парсер закончил работу и обнаружил изменения","image":{"type":"image","data":{"uuid":"e14acc71-7a1e-5bd4-8d79-7c4eaa062a06","width":778,"height":766,"size":27341,"type":"png","color":"f6f7f7","hash":"","external_service":[]}}}]}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"Четвертый шаг: формируем одну таблицу со всеми изменениями","image":{"type":"image","data":{"uuid":"0fec07c4-928c-53f1-b15f-8ac7d1ac65f5","width":826,"height":831,"size":31855,"type":"png","color":"f6f6f6","hash":"","external_service":[]}}}]}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"Пятый шаг: настраиваем автоматическую отправку данных на электронную почту","image":{"type":"image","data":{"uuid":"44dde904-89f5-5440-8f49-cff34f5b3fc9","width":605,"height":792,"size":20316,"type":"png","color":"f7f6f6","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Благодаря этому решению, когда оба скрипта завершают свою работу, в проектный чат приходит информация о числе товаров, статус которых изменился. Подробности можно узнать из письма, которое система автоматически отправляет на почту сотрудников Digital Geeks и Panasonic.

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"Сбор результатов парсинга, отправка данных в Telegram и на почту","image":{"type":"image","data":{"uuid":"b9ccb9cf-fbe6-50a2-9585-63f39d9c2d30","width":1106,"height":688,"size":25110,"type":"png","color":"faf9fa","hash":"","external_service":[]}}}]}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"Формат шаблона письма в среде Make","image":{"type":"image","data":{"uuid":"5f9fa95a-5ad2-55f3-9d1d-11620b24c5e4","width":378,"height":326,"size":5825,"type":"png","color":"f2f1f2","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Такая система уже работает как часы, но можно еще кое-что улучшить. К примеру, сделать так, чтобы алгоритм сохранял данные последовательно, пропуская URL с ошибками. Наш скрипт сначала собирает информацию, а затем размещает ее таблицу, поэтому при любой проблеме на одной из страниц начинает все заново. Чтобы система действовала еще быстрее, можно добавить многопоточность организовать параллельный сбор данных сразу с нескольких адресов.

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"Экономия 150 тыс. рублей в месяц и другие выгоды от автоматизации"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Благодаря внедрению этого решения мы сэкономили на оплате труда новых сотрудников, которых пришлось бы нанимать для проверки товарных остатков. При этом скрипты работают несравнимо быстрее человека: вместо 2-3 дней они тратят около 10 минут. А специалисты агентства вместо перехода по ссылкам и изучения таблиц могут заняться задачами, которые требуют креативности и интеллекта.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Не менее очевидна выгода для заказчика. Благодаря автоматизации он может быть уверен, что бюджет не уходит на рекламу страниц товара, который нельзя заказать.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Cоздание индивидуальных алгоритмов вместо выбора готовых сервисов ежемесячно экономит компании порядка 150 тыс. рублей.А оперативное оповещение о том, какой товар на каком сайте закончился, помогает нашему партнеру вовремя пополнять запасы продукции во всех интернет-магазинах, не допуская простоя.

"}},{"type":"delimiter","cover":false,"hidden":false,"anchor":"","data":{"type":"default"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Если вы хотите знать больше о продвижении в интернете, загляните в наш телеграм-канал Digital Geeks. Его цель — облегчить жизнь директорам и менеджерам по Digital-маркетингу, а также предпринимателям, которые привлекают клиентов в Сети. В постах мы рассказываем, например, как построить эффективную систему управления SЕО, используя принципы регулярного менеджмента; как быстрее получить результаты; как автоматизировать различные процессы и сделать команду эффективнее.

"}}],"summaryContent":null,"isExistSummaryContent":false,"warningFromEditor":null,"warningFromEditorTitle":null,"counters":{"comments":3,"favorites":34,"reposts":0,"views":94,"hits":835,"reads":null,"online":0},"dateFavorite":0,"hitsCount":835,"isCommentsEnabled":true,"isLikesEnabled":true,"isRemovedByUserRequest":false,"isFavorited":false,"isPinned":false,"repostId":null,"repostData":null,"subscribedToTreads":false,"isEditorial":false,"isAudioAvailable":false,"audioUrl":null,"isAudioAvailableToGenerate":false,"commentEditor":{"enabled":true,"who":null,"text":"","until":null,"reason":null,"type":"everybody"},"isBlur":false,"isPublished":true,"isDisabledAd":false,"withheld":[],"ogTitle":null,"ogDescription":null,"url":"https://vc.ru/marketing/483722-vmesto-treh-dnei-10-minut-kak-avtomatizirovat-proverku-tovarnyh-ostatkov-i-ostanovku-zapusk-kontekstnoi-reklamy","author":{"id":722317,"name":"Малюгин Geeks","nickname":"vova_geeks","description":"Руковожу Digital Geeks — агентством performance-маркетинга с уклоном в SEO и GEO-продвижение в нейросетях. Канал: https://t.me/digitalgeeks","uri":"/vova_geeks","avatar":{"type":"image","data":{"uuid":"ce4ff37e-c704-5ab3-9054-2d9cb6c6ab03","width":334,"height":340,"size":55711,"type":"png","color":"95a7a6","hash":"","external_service":[],"base64preview":"/9j/4AAQSkZJRgABAQIAHAAcAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCAAKAAoDAREAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAABQf/xAAmEAACAQIEBQUAAAAAAAAAAAABAgMEEQAFBhIHEyEiYSMxMlHR/8QAGAEAAwEBAAAAAAAAAAAAAAAAAwUGAgT/xAAiEQACAQMEAgMAAAAAAAAAAAABAgADBBEFEyFRMZGhscH/2gAMAwEAAhEDEQA/AHMz0lGeN4parMqxttBCaGCKtdIILt38yIHa5br8hcC3jHPeX1yL2kKbYU+f2Z07TrRtLrNVXLjOD9Slto6bcbBLX6emv5hxvL38yb2n6HoQHT0MMvEOKaSJHdsuWUsygkvtbuv9+cKnUF0OO5TU2IpuAeOJTkY7F6n2GCmBwJ//2Q=="}},"cover":null,"achievements":[{"title":"Год на vc.ru","code":"registration_1_year","description":"Первый год с vc.ru. Получена 24 июля 2025.","previewUuid":"0d11c244-49de-50e7-894e-b9b27945d42b","formats":{"glb":"https://static.vc.ru/achievements/fish.glb","usdz":"https://static.vc.ru/achievements/fish.usdz"},"viewData":{"contentColor":"#C67AA3","textMaxWidth":0.634765625,"textX":0.5888671875,"textY":0.54296875,"logoX":0.5859375,"logoY":0.6669921875,"logoXNoText":0.6044921875,"logoYNoText":0.5439453125},"id":4710099,"userId":722317,"count":0,"shareImage":"https://api.vc.ru/achievements/share/4710099"},{"title":"3 года на vc.ru","code":"registration_3_years","description":"Провёл 3 года вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"d9d72ac5-bcb5-55e0-8c72-b99251e5cdd9","formats":{"glb":"https://static.vc.ru/achievements/shark.glb","usdz":"https://static.vc.ru/achievements/shark.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.5205078125,"textY":0.341796875,"logoX":0.5205078125,"logoY":0.4609375,"logoXNoText":0.5,"logoYNoText":0.3662109375},"id":1086012,"userId":722317,"count":0,"shareImage":"https://api.vc.ru/achievements/share/1086012"}],"lastModificationDate":1764937377,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":true,"badgeId":"1ee4281e-b189-6840-aca8-c2b27ffffb1a","isDonationsEnabled":false,"isPlusGiftEnabled":true,"isUnverifiedBlogForCompanyWithoutPro":false,"isRemovedByUserRequest":false,"isFrozen":false,"isDisabledAd":false,"isPlus":true,"isVerified":false,"isPro":false,"yandexMetricaId":null,"badge":"plus","isOnline":false,"tgChannelShortname":"digitalgeeks","isUnsubscribable":true,"type":1,"subtype":"personal_blog"},"subsite":{"id":199113,"name":"Маркетинг","description":"Рекламные кейсы из России и других стран, советы по продвижению, маркетинг и digital.","uri":"/marketing","avatar":{"type":"image","data":{"uuid":"d66009fe-9bf0-52da-bdbf-4c758eba39e7","width":2400,"height":2400,"size":841299,"type":"jpg","color":"f97373","hash":"0c1cf06cf0d010","external_service":[]}},"cover":{"type":"image","data":{"uuid":"5488a646-f32d-57a6-a31f-d290afc4388a","width":960,"height":280,"size":177,"type":"png","color":"fc7c7c","hash":"","external_service":[]}},"lastModificationDate":1661337194,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":false,"isDisabledAd":false,"nickname":"marketing","isUnsubscribable":true,"badge":null,"badgeId":null,"isDonationsEnabled":false,"isOnline":false,"isPlus":false,"isUnverifiedBlogForCompanyWithoutPro":false,"isVerified":false,"isRemovedByUserRequest":false,"isFrozen":false,"isPro":false,"type":2,"subtype":"community"},"reactions":{"counters":[{"id":1,"count":17}],"reactionId":0},"isNews":false,"source":null,"clusters":[],"donations":{"amount":0,"isDonated":false},"commentsSeenCount":null}},{"type":"entry","data":{"id":156853,"customUri":null,"subsiteId":590818,"title":"Telegram-бот для получения адреса по локации или координатам (Python)","date":1599644149,"dateModified":1599644149,"blocks":[{"type":"text","cover":true,"hidden":false,"anchor":"","data":{"text":"

Привет! Представь ситуацию, когда тебе скинули координаты или локацию, но ты хочешь срочно узнать адрес этого места.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Сегодня попробуем написать Telegram-бота для получения адреса по координатам или локации.

"}},{"type":"media","cover":true,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"e9eb8348-8946-b2ed-e0f6-a7b94e1afccd","width":1266,"height":1518,"size":3961991,"type":"png","color":"a6bb8e","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

В итоге у тебя получится вот такой бот @SayMyAddressBot.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Что нам для этого потребуется?

"}},{"type":"list","cover":false,"hidden":false,"anchor":"","data":{"items":["Бот в Telegram;","Обратный геокодинг от Яндекса. Геокодинг это такой сервис, который позволяет получить из адреса координаты, а нам нужно наоборот, поэтому «обратный геокодинг»;","Установленный Python и библиотека requests для посылки запросов;
","Установленная библиотека Python-telegram-bot.
"],"type":"UL"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Но давай обо всём по порядку!

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"Создаём бота в Telegram."}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

1) Ищем в поиске Telegram бота по нику @botfather. Этот бот ответственен за регистрацию всех остальных ботов;

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"@botfather","image":{"type":"image","data":{"uuid":"0597c3bf-19bb-243f-7dcc-edb4a9d62671","width":566,"height":254,"size":157068,"type":"png","color":"05a5dc","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

2) Отправляем ему /newbot и начинаем создание бота;

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

3) Отправляем имя бота (оно может быть любым) и ник бота (обязательно должен оканчиваться на «bot»). Если у тебя выходит ошибка, то значит этот ник занят. Пробуй другой.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

4) Получаем токен бота (скопируй этот токен и никому не давай😅).

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Скриншот ниже (токен выделен красной рамкой).

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"7c291b61-a714-2d44-942f-1acb4bdaa4cb","width":1258,"height":1378,"size":2743887,"type":"png","color":"aabc92","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Супер! Бот создан и уже доступен внутри Telegram по нику. Можешь вбить в поиске и убедиться. Также ты можешь найти его по ссылке t.me/НикТвоегоБота. Например на скриншоте я зарегистрировал SayMyAddressBot, значит его ссылка t.me/SayMyAddressBot. Сохрани такую ссылку с ником твоего бота. Скоро она нам пригодится.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Отлично. С ботом разобрались.

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"Обратный геокодинг от Яндекса."}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Я надеюсь, что у тебя есть аккаунт на Яндексе. Если нет, то тебе сюда.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Итак. Как работает обратный геокодинг от Яндекса?

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Всё очень просто. Нужно отправить GET запрос с координатами и получить в ответ адрес.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Вот пример такого запроса:

"}},{"type":"incut","cover":false,"hidden":false,"anchor":"","data":{"text":"

https://geocode-maps.yandex.ru/1.x? format=json&lang=ru_RU&kind=house&geocode=37.617585,55.751903&apikey=ТОКЕН

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"Что мы тут видим?"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Запрос:

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

https://geocode-maps.yandex.ru/1.x/

Параметры:

"}},{"type":"list","cover":false,"hidden":false,"anchor":"","data":{"items":["format: в каком формате возвращать данные. В данном случае json;","lang: язык возвращаемых данных. В данном случае ru_RU (русский);","kind: вид адреса. В данном случае house (точность до дома);","geocode: координаты (сначала идет долгота, затем широта);","apikey: токен для доступа.
"],"type":"UL"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

P.S.: параметров гораздо больше, но нам они не нужны. Подробнее можешь почитать тут.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Просто, правда? Послал запрос с координатами, получил адрес 😊.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Как видишь у нас есть все данные кроме токена. Займемся его получением!

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"Получаем токен."}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

1) Заходим на страницу разработчика и входим в кабинет (аккаунт на Яндексе у тебя уже есть).

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

2) Получилось? Отлично. Далее ты увидишь вот такую страницу.

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"Пустой кабинет разработчика","image":{"type":"image","data":{"uuid":"974c5b05-5df7-3789-5cdd-f2cae67d2ad7","width":2480,"height":1412,"size":1857583,"type":"png","color":"f0d45e","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Жми желтую кнопку «Подключить API»

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

3) Теперь нужно выбрать какой именно токен нам нужен.

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"Нам нужен HTTP геокодер","image":{"type":"image","data":{"uuid":"cebcc860-1d72-c661-b4e0-09a4b552859f","width":1170,"height":1466,"size":1033724,"type":"png","color":"e3e3e2","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Выбирай «JavaScript API и HTTP геокодер». За ним мы и пришли.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

4) Далее заполняем формочку твоими данными.

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"bca11b54-a5fb-e723-9865-001b78dd4023","width":1182,"height":1166,"size":891201,"type":"png","color":"caccd1","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

В поле «Ссылка на ваш сайт» пиши ссылку на своего бота, которую мы сохранили ранее.

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"b1434b90-0fa8-4cca-c485-1ae06a05920a","width":1130,"height":964,"size":655927,"type":"png","color":"d6d3d1","hash":"","external_service":[]}}}]}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"b9ee8d8c-7ecc-be0d-baec-e54d96449293","width":1126,"height":624,"size":498625,"type":"png","color":"e6e6e6","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Ну и тыкай кнопку «Продолжить».

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

5) Тебе должно всплыть окошко с сообщением об успешной регистрации.

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"f8891857-7369-4807-94bd-55ca44a5adbd","width":1136,"height":536,"size":353460,"type":"png","color":"d1d2d1","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Жми «Перейти к API».

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

6) Вот и всё. На открывшейся странице уже лежит наш искомый токен геокодера (выделил красной рамкой). Его тоже сохрани и никому не давай.

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"2b8c7247-7aa5-86d6-9e96-681314ba868e","width":1974,"height":1350,"size":1503336,"type":"png","color":"121818","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Токен активируется через 15 минут после создания. Можешь прямо в браузере (Chrome, Safari или что там у тебя) вбить (не забудь подставить свой токен в конце).

"}},{"type":"incut","cover":false,"hidden":false,"anchor":"","data":{"text":"

https://geocode-maps.yandex.ru/1.x? format=json&lang=ru_RU&kind=house&geocode=37.617585,55.751903&apikey=ТОКЕН

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

и получить ответ в json виде:

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"{\n \"response\": {\n \"GeoObjectCollection\": {\n \"metaDataProperty\": {\n \"GeocoderResponseMetaData\": {\n \"Point\": {\n \"pos\": \"37.617585 55.751903\"\n },\n \"boundedBy\": {\n \"Envelope\": {\n \"lowerCorner\": \"37.615084 55.749405\",\n \"upperCorner\": \"37.620079 55.7544\"\n }\n },\n \"request\": \"37.617585,55.751903\",\n \"results\": \"10\",\n \"found\": \"2\"\n }\n },\n \"featureMember\": [\n {\n \"GeoObject\": {\n \"metaDataProperty\": {\n \"GeocoderMetaData\": {\n \"precision\": \"exact\",\n \"text\": \"Russia, Moscow, Moscow Kremlin, 1\",\n \"kind\": \"house\",\n \"Address\": {\n \"country_code\": \"RU\",\n \"formatted\": \"Russia, Moscow, Moscow Kremlin, 1\",\n \"Components\": [\n {\n \"kind\": \"country\",\n \"name\": \"Russia\"\n },\n {\n \"kind\": \"province\",\n \"name\": \"Tsentralny federalny okrug\"\n },\n {\n \"kind\": \"province\",\n \"name\": \"Moscow\"\n },\n {\n \"kind\": \"locality\",\n \"name\": \"Moscow\"\n },\n {\n \"kind\": \"district\",\n \"name\": \"Moscow Kremlin\"\n },\n {\n \"kind\": \"house\",\n \"name\": \"1\"\n }\n ]\n },\n \"AddressDetails\": {\n \"Country\": {\n \"AddressLine\": \"Russia, Moscow, Moscow Kremlin, 1\",\n \"CountryNameCode\": \"RU\",\n \"CountryName\": \"Russia\",\n ...","lang":""}},{"type":"delimiter","cover":false,"hidden":false,"anchor":"","data":{"type":"default"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Пол дела сделано. У нас есть и Telegram бот (с его токеном) и геокодер (с его токеном).

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Теперь с помощью Python мы их объединим!

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Python у тебя уже установлен? Если нет, то тебе сюда.

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"Получаем адрес по координатам на Python."}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

В Python есть библиотека requests и она позволяет посылать запросы (как ты только что делал в браузере). Это нам подходит.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

1) Открывай консоль (терминал) и устанавливай requests с помощью команды:

"}},{"type":"incut","cover":false,"hidden":false,"anchor":"","data":{"text":"

pip install requests

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"901d24ad-e437-f676-0646-a2434c4ef658","width":508,"height":54,"size":33226,"type":"png","color":"1c1c1c","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Подробнее тут.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

2) Теперь нужно будет написать небольшой код на Python для получения адреса по координатам.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Открывай свою среду разработки или просто текстовый файл (нужно будет сохранить его с окончанием. py, а не. txt). Назовём файл main.py.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

И добавляй туда этот код. Он полностью расписан в комментариях.

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"#импортируем библиотеку requests\nimport requests\n\n#создаем функцию get_address_from_coords с параметром coords, куда мы будем посылать координаты и получать готовый адрес.\ndef get_address_from_coords(coords):\n #заполняем параметры, которые описывались выже. Впиши в поле apikey свой токен!\n PARAMS = {\n \"apikey\":\"ТОКЕН\",\n \"format\":\"json\",\n \"lang\":\"ru_RU\",\n \"kind\":\"house\",\n \"geocode\": coords\n }\n\n #отправляем запрос по адресу геокодера.\n try:\n r = requests.get(url=\"https://geocode-maps.yandex.ru/1.x/\", params=PARAMS)\n #получаем данные\n json_data = r.json()\n #вытаскиваем из всего пришедшего json именно строку с полным адресом.\n address_str = json_data[\"response\"][\"GeoObjectCollection\"][\"featureMember\"][0][\"GeoObject\"][\"metaDataProperty\"][\"GeocoderMetaData\"][\"AddressDetails\"][\"Country\"][\"AddressLine\"]\n #возвращаем полученный адрес\n return address_str\n except Exception as e:\n #если не смогли, то возвращаем ошибку\n return \"error\"\n\nif __name__ == '__main__':\n #даем запрос на получение адреса с координатами 37.617585, 55.751903\n address_str = get_address_from_coords(\"37.617585,55.751903\")\n #распечатываем адрес\n print(address_str)","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

3) В консоли (терминале) переходим в папку с нашим файлом через команду «cd» (у меня он лежит в папке Documents/Python/).

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"c9590c85-4cf0-ca1d-482e-1f3615cd1fe9","width":520,"height":54,"size":37165,"type":"png","color":"1e1e1e","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

И запускаем файл с помощью «python3».

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"6946e602-9508-e56e-6b96-171067e521a0","width":414,"height":46,"size":24907,"type":"png","color":"1c1c1c","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Как результат, ты получишь адрес координат из кода.

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"10c338ee-65d5-cd99-a174-b42365896e9a","width":488,"height":40,"size":24584,"type":"png","color":"1c1c1c","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Мы почти закончили! Осталось совсем немного.

"}},{"type":"delimiter","cover":false,"hidden":false,"anchor":"","data":{"type":"default"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"Программируем Telegram бота на Python"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Здесь в целом всё точно также, как и в предыдущей части.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Нам необходимо:

"}},{"type":"list","cover":false,"hidden":false,"anchor":"","data":{"items":["Установить библиотеку python-telegram-bot для управления нашим ботом.","Написать немного кода.
"],"type":"UL"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Поехали!

"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"Установка библиотеки python-telegram-bot"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

1) Снова открывай консоль (терминал) и устанавливай python-telegram-bot с помощью команды:

"}},{"type":"incut","cover":false,"hidden":false,"anchor":"","data":{"text":"

pip install python-telegram-bot

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"6fe2f558-67c2-a74b-f349-69578fc5e23d","width":698,"height":52,"size":44367,"type":"png","color":"1c1c1c","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Подробнее тут.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

2) Пришло время написать код нашего бота. Я снова всё опишу в комментариях (не забудь поставить токен геокодера и токен бота в нужных местах в коде)!

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"#Подлкючаем библиотеку requests\nimport requests\n#Подключаем нужные для бота модули из библиотеки telegram.ext\nfrom telegram.ext import Updater, CommandHandler, MessageHandler, Filters\n\n#это наша функция для получения адреса по координатам. С ней мы знакомы.\ndef get_address_from_coords(coords):\n PARAMS = {\n \"apikey\": \"ТОКЕН_ГЕОКОДЕРА\",\n \"format\": \"json\",\n \"lang\": \"ru_RU\",\n \"kind\": \"house\",\n \"geocode\": coords\n }\n\n try:\n r = requests.get(url=\"https://geocode-maps.yandex.ru/1.x/\", params=PARAMS)\n json_data = r.json()\n address_str = json_data[\"response\"][\"GeoObjectCollection\"][\"featureMember\"][0][\"GeoObject\"][\"metaDataProperty\"][\n \"GeocoderMetaData\"][\"AddressDetails\"][\"Country\"][\"AddressLine\"]\n return address_str\n\n except Exception as e:\n #единственное что тут изменилось, так это сообщение об ошибке.\n return \"Не могу определить адрес по этой локации/координатам.\\n\\nОтправь мне локацию или координаты (долгота, широта):\"\n\n\n#Эта функция будет использоваться когда человек первый нажал в боте START\ndef start(update, context):\n #эта строка отправляет сообщение пользователю с просьбой послать локацию или координаты\n update.message.reply_text('Отправь мне локацию или координаты (долгота, широта):')\n\n#Эта функция будет использоваться, если пользователь послал в бота любой текст.\n#Мы ожидаем координаты, но если прийдет что-то другое не страшно, ведь мы описали в функции получения адреса возвращение ошибки в случае чего. \ndef text(update, context):\n #получаем текст от пользователя\n coords = update.message.text\n #отправляем текст в нашу функцио получения адреса из координат\n address_str = get_address_from_coords(coords)\n #вовщращаем результат пользователю в боте\n update.message.reply_text(address_str)\n\n#Эта функция будет использоваться, если пользователь послал локацию.\ndef location(update, context):\n #получаем обьект сообщения (локации)\n message = update.message\n #вытаскиваем из него долготу и ширину\n current_position = (message.location.longitude, message.location.latitude)\n #создаем строку в виде ДОЛГОТА,ШИРИНА\n coords = f\"{current_position[0]},{current_position[1]}\"\n #отправляем координаты в нашу функцию получения адреса\n address_str = get_address_from_coords(coords)\n #вовщращаем результат пользователю в боте\n update.message.reply_text(address_str)\n\n#Это основная функция, где запускается наш бот\ndef main():\n #создаем бота и указываем его токен\n updater = Updater(\"ТОКЕН_БОТА\", use_context=True)\n #создаем регистратор событий, который будет понимать, что сделал пользователь и на какую функцию надо переключиться.\n dispatcher = updater.dispatcher\n\n #регистрируем команду /start и говорим, что после нее надо использовать функцию def start\n dispatcher.add_handler(CommandHandler(\"start\", start))\n #регистрируем получение текста и говорим, что после нее надо использовать функцию def text\n dispatcher.add_handler(MessageHandler(Filters.text, text))\n #регистрируем получение локации и говорим, что после нее надо использовать функцию def location\n dispatcher.add_handler(MessageHandler(Filters.location, location))\n #запускаем бота\n updater.start_polling()\n updater.idle()\n\nif __name__ == '__main__':\n #запускаем функцию def main\n main()","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

3) Создаем файл main_bot.py и сохраняем этот код в нём.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

4) В консоли (терминале) переходим в папку с нашим файлом через команду «cd» (у меня он лежит в папке Documents/Python/).

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"c9590c85-4cf0-ca1d-482e-1f3615cd1fe9","width":520,"height":54,"size":37165,"type":"png","color":"1e1e1e","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

5) И снова запускаем файл с помощью «python3». Теперь уже это файл нашего готового бота!

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"c581e42b-9901-03ad-6d63-e22133944753","width":482,"height":44,"size":26495,"type":"png","color":"1c1c1c","hash":"","external_service":[]}}}]}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","text":"Всё! Заходи в своего бота в Telegram (ищи по нику) и используй🤩🥳."}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Моего бота можно посмотреть тут @SayMyAddressBot.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

P. S. Это моя первая инструкция на портале. Старался сделать так, чтобы было понятно даже совсем начинающим. Спасибо за то, что прочёл до конца!

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

#selectel_инструкция

"}}],"summaryContent":null,"isExistSummaryContent":false,"warningFromEditor":null,"warningFromEditorTitle":null,"counters":{"comments":10,"favorites":61,"reposts":2,"views":53,"hits":101030,"reads":null,"online":0},"dateFavorite":0,"hitsCount":101030,"isCommentsEnabled":true,"isLikesEnabled":true,"isRemovedByUserRequest":false,"isFavorited":false,"isPinned":false,"repostId":null,"repostData":null,"subscribedToTreads":false,"isEditorial":false,"isAudioAvailable":false,"audioUrl":null,"isAudioAvailableToGenerate":false,"commentEditor":{"enabled":true,"who":null,"text":"","until":null,"reason":null,"type":"everybody"},"isBlur":false,"isPublished":true,"isDisabledAd":false,"withheld":[],"ogTitle":null,"ogDescription":null,"url":"https://vc.ru/dev/156853-telegram-bot-dlya-polucheniya-adresa-po-lokacii-ili-koordinatam-python","author":{"id":590818,"name":"Dan","nickname":null,"description":null,"uri":"","avatar":{"type":"image","data":{"uuid":"407e6c9d-96d5-5856-8b0c-3e23e94edd31","width":1796,"height":1792,"size":152978,"type":"png","color":"68bdfb","hash":"","external_service":[]}},"cover":null,"achievements":[{"title":"5 лет на vc.ru","code":"registration_5_years","description":"Провёл 5 лет вместе с vc.ru. Получена 9 сентября 2025.","previewUuid":"a9140d54-73b8-5f40-afa8-449fbaafd42b","formats":{"glb":"https://static.vc.ru/achievements/whale.glb","usdz":"https://static.vc.ru/achievements/whale.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.533203125,"textY":0.658203125,"logoX":0.533203125,"logoY":0.77734375,"logoXNoText":0.4375,"logoYNoText":0.66015625},"id":5693051,"userId":590818,"count":0,"shareImage":"https://api.vc.ru/achievements/share/5693051"},{"title":"Год на vc.ru","code":"registration_1_year","description":"Первый год с vc.ru. Получена 24 июля 2025.","previewUuid":"0d11c244-49de-50e7-894e-b9b27945d42b","formats":{"glb":"https://static.vc.ru/achievements/fish.glb","usdz":"https://static.vc.ru/achievements/fish.usdz"},"viewData":{"contentColor":"#C67AA3","textMaxWidth":0.634765625,"textX":0.5888671875,"textY":0.54296875,"logoX":0.5859375,"logoY":0.6669921875,"logoXNoText":0.6044921875,"logoYNoText":0.5439453125},"id":4839183,"userId":590818,"count":0,"shareImage":"https://api.vc.ru/achievements/share/4839183"},{"title":"3 года на vc.ru","code":"registration_3_years","description":"Провёл 3 года вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"d9d72ac5-bcb5-55e0-8c72-b99251e5cdd9","formats":{"glb":"https://static.vc.ru/achievements/shark.glb","usdz":"https://static.vc.ru/achievements/shark.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.5205078125,"textY":0.341796875,"logoX":0.5205078125,"logoY":0.4609375,"logoXNoText":0.5,"logoYNoText":0.3662109375},"id":1215096,"userId":590818,"count":0,"shareImage":"https://api.vc.ru/achievements/share/1215096"}],"lastModificationDate":1764937377,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":true,"badgeId":null,"isDonationsEnabled":false,"isPlusGiftEnabled":true,"isUnverifiedBlogForCompanyWithoutPro":false,"isRemovedByUserRequest":false,"isFrozen":false,"isDisabledAd":false,"isPlus":false,"isVerified":false,"isPro":false,"yandexMetricaId":null,"badge":null,"isOnline":false,"tgChannelShortname":null,"isUnsubscribable":true,"type":1,"subtype":"personal_blog"},"subsite":{"id":235819,"name":"Разработка","description":"Сообщество разработчиков: публикации о личном опыте, выдающиеся приёмы при решении рутинных задач, полезные материалы для профессионального роста.","uri":"/dev","avatar":{"type":"image","data":{"uuid":"fef5b5fb-e488-5b7f-8445-e3a26a910b44","width":1200,"height":1200,"size":7757,"type":"png","color":"343434","hash":"04042b2b1c1000","external_service":[]}},"cover":{"type":"image","data":{"uuid":"2a214cc5-35cc-58ca-bc07-fc1c892d2101","width":960,"height":280,"size":177,"type":"png","color":"343434","hash":"","external_service":[]}},"lastModificationDate":1642411346,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":false,"isDisabledAd":false,"nickname":"dev","isUnsubscribable":true,"badge":null,"badgeId":null,"isDonationsEnabled":false,"isOnline":false,"isPlus":false,"isUnverifiedBlogForCompanyWithoutPro":false,"isVerified":false,"isRemovedByUserRequest":false,"isFrozen":false,"isPro":false,"type":2,"subtype":"community"},"reactions":{"counters":[{"id":1,"count":13}],"reactionId":0},"isNews":false,"source":null,"clusters":[],"donations":{"amount":0,"isDonated":false},"commentsSeenCount":null}},{"type":"entry","data":{"id":156704,"customUri":null,"subsiteId":447345,"title":"Как найти однотипную информацию в большом количестве файлов, используя Python?","date":1599576898,"dateModified":1599576898,"blocks":[{"type":"text","cover":true,"hidden":false,"anchor":"","data":{"text":"

Недавно мы решали следующую задачу – необходимо найти и удалить содержащие номера карт файлы, размещенные на общем ресурсе. Если нужно было бы искали что-то, определенное и однозначное, мы могли бы воспользоваться поиском в самой операционной системе (используя стандартны поиск текста в содержимом файла). Но, как правило, поиск стандартными средствами занимает очень много времени. А если еще нужно хотите использовать маски или регулярные выражения, то как быть? Поделимся, как мы решили эту задачу.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Инструменты

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Данную задачу можно решить на многих языках взяв за основу идею, описанную в этой статье. Я буду делать реализацию на языке Python, а инструменты использовать «из коробки», без импорта сторонних библиотек. Почему я не использовал библиотеку Pandas? Pandas хороший инструмент для работы с файлами Excel, но он достаточно массивный и ресурсоемкий для решения нашей задачи.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Решение задачи

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Углубимся в формат XLSX. Что он из себя представляет? Файл Excel — это обычный структурированный архив с расширением. XLSX. Если мы изменим расширение на. ZIP, то сможем открыть его с помощью архиватора, установленного в вашей операционной системе.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Давайте так и сделаем:

"}},{"type":"media","cover":true,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"7a65bdd3-ca64-15a4-dde3-65c9a47ffa4f","width":624,"height":391,"size":239894,"type":"png","color":"eeeeec","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Файл Excel открылся в архиваторе, и мы видим структуру самого архива. Нам нужна папка [xl]. Проваливаемся в нее и видим:

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"ea9346db-b35f-dcbb-7beb-fd94ce7cf9fa","width":624,"height":391,"size":252336,"type":"png","color":"eeedec","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Нам интересны директория [worksheets] и файл [sharedStrings.xml].

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

В файле [sharedString.xml] хранятся все текстовые поля, которые есть на листах в Excel, т.е. если поле текстовое, то оно будет хранится в этом файле, а ссылка на это поле будет находится в директории [worksheets] на соответствующем листе. Если в нескольких ячейках будет одно и тоже слово, то в файле будет одно слово, а в ячейках будет указана одна ссылка на это слово (см. рис.).

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"077a1e9a-47c9-2c1b-d046-477c631e391d","width":624,"height":444,"size":397744,"type":"png","color":"276244","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Итак, мы знаем, что номер карты является текстовым полем, соответственно он будет находится в этом файле. Приступим к написанию кода. Нам понадобятся следующие библиотеки: os – для работы с путями ОС, zipfile – для работы с архивами, re – для работы с регулярными выражениями — паттернами.

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"import os, zipfile, re #импортируем библиотеки\n\n#Определяем регулярные выражения\npattern_card16=rb\"(\\b\\d{16}\\b|\\b\\d{4}\\s\\d{4}\\s\\d{4}\\s\\d{4}\\b|\\b\\d{8}\\s\\d{8}\\b)\"\npattern_card18=rb\"(\\b\\d{18}\\b|\\b\\d{8}\\s\\d{10}\\b)\"","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Далее пишем функцию, которая будет сканировать выбранную нами директорию:

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"def find_file(dirn, path): # функция принимает os.listdir, и путь на папку\n try:\n for i in dirn:\n if os.path.isfile(path+'/'+i): #проверяем что перед нами, файл или нет\n #Проверяем расширение файла и исключаем системные которые начинаются на [~$] \n if i.find('.xlsx')!=-1and i.find('~ )==-1 and i.find('.xlsx.')==-1:\n open_arch(path+'/'+i) #Функция по обработке архивов\n else:\n #Если это директория, то проваливаемся в нее\n find_file(os.listdir(path+'/'+i),path+'/'+i)\n except Exception as err:\n print(err,path+'/'+i)","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Теперь напишем саму функцию, которая будет обрабатывать найденные по условию файлы:

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"def open_arch(path_file):\n z = zipfile.ZipFile(path_file, 'r') #открываем архив\n files=z.namelist() #получаем список файлов в архиве\n try:\n for f in files:\n if f=='xl/sharedStrings.xml':\n if re.search(pattern_card16, z.read(f))!=None or re.search(pattern_card18, z.read(f))!=None:\n list_file.write(path_file+'\\n') #Если находит совпадение, то пишем путь в файл\n #print(re.findall(pattern_card16, z.read(r))) # если вам нужно \n #print(re.findall(pattern_card18, z.read(r))) # выводить совпадения\n except Exception as err:\n print(err, files)","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Определяем директорию для поиска и запускаем функцию для поиска:

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"path='Y:' #указываем путь к общему ресурсу, здесь я его подцепил как диск Y: \n\nlist_file=open('list_file', 'w+') #открываем файл для записи\nfind_file(os.listdir(path), path) #запускаем обработку","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Резюме

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Наша работа сделана. Ждем, когда отработает скрипт и получим итоговый файл для анализа. Вы зададите вопрос, почему я сразу не стал удалять файлы? Потому что поиск основан на простом регулярном выражении и туда могут попасть номера заявок, договоров и т.д.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

В результате нам удалось избежать ручного анализа более 154 тысяч файлов и сократить выборку более чем в 100 раз.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Я надеюсь, моя инструкция была полезна. Спасибо за внимание.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

#selectel_инструкция

"}}],"summaryContent":null,"isExistSummaryContent":false,"warningFromEditor":null,"warningFromEditorTitle":null,"counters":{"comments":0,"favorites":8,"reposts":0,"views":6,"hits":2345,"reads":null,"online":0},"dateFavorite":0,"hitsCount":2345,"isCommentsEnabled":true,"isLikesEnabled":true,"isRemovedByUserRequest":false,"isFavorited":false,"isPinned":false,"repostId":null,"repostData":null,"subscribedToTreads":false,"isEditorial":false,"isAudioAvailable":false,"audioUrl":null,"isAudioAvailableToGenerate":false,"commentEditor":{"enabled":true,"who":null,"text":"","until":null,"reason":null,"type":"everybody"},"isBlur":false,"isPublished":true,"isDisabledAd":false,"withheld":[],"ogTitle":null,"ogDescription":null,"url":"https://vc.ru/dev/156704-kak-naiti-odnotipnuyu-informaciyu-v-bolshom-kolichestve-failov-ispolzuya-python","author":{"id":447345,"name":"NTA","nickname":null,"description":null,"uri":"","avatar":{"type":"image","data":{"uuid":"e7175678-aaab-09f8-0271-7b3af7ac4670","width":1207,"height":1207,"size":83090,"type":"jpg","color":"e3ebf8","hash":"","external_service":[]}},"cover":{"cover":{"type":"image","data":{"uuid":"8575b55d-a1f0-53ee-9ad6-78268f9ea45c","width":1280,"height":373,"size":56005,"type":"jpg","color":"b0b9ca","hash":"","external_service":[]}},"cover_y":0},"achievements":[{"title":"Год на vc.ru","code":"registration_1_year","description":"Первый год с vc.ru. Получена 24 июля 2025.","previewUuid":"0d11c244-49de-50e7-894e-b9b27945d42b","formats":{"glb":"https://static.vc.ru/achievements/fish.glb","usdz":"https://static.vc.ru/achievements/fish.usdz"},"viewData":{"contentColor":"#C67AA3","textMaxWidth":0.634765625,"textX":0.5888671875,"textY":0.54296875,"logoX":0.5859375,"logoY":0.6669921875,"logoXNoText":0.6044921875,"logoYNoText":0.5439453125},"id":4980908,"userId":447345,"count":0,"shareImage":"https://api.vc.ru/achievements/share/4980908"},{"title":"3 года на vc.ru","code":"registration_3_years","description":"Провёл 3 года вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"d9d72ac5-bcb5-55e0-8c72-b99251e5cdd9","formats":{"glb":"https://static.vc.ru/achievements/shark.glb","usdz":"https://static.vc.ru/achievements/shark.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.5205078125,"textY":0.341796875,"logoX":0.5205078125,"logoY":0.4609375,"logoXNoText":0.5,"logoYNoText":0.3662109375},"id":1356821,"userId":447345,"count":0,"shareImage":"https://api.vc.ru/achievements/share/1356821"},{"title":"5 лет на vc.ru","code":"registration_5_years","description":"Провёл 5 лет вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"a9140d54-73b8-5f40-afa8-449fbaafd42b","formats":{"glb":"https://static.vc.ru/achievements/whale.glb","usdz":"https://static.vc.ru/achievements/whale.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.533203125,"textY":0.658203125,"logoX":0.533203125,"logoY":0.77734375,"logoXNoText":0.4375,"logoYNoText":0.66015625},"id":130113,"userId":447345,"count":0,"shareImage":"https://api.vc.ru/achievements/share/130113"}],"lastModificationDate":1764937376,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":true,"badgeId":null,"isDonationsEnabled":false,"isPlusGiftEnabled":true,"isUnverifiedBlogForCompanyWithoutPro":true,"isRemovedByUserRequest":false,"isFrozen":false,"isDisabledAd":false,"isPlus":false,"isVerified":false,"isPro":false,"yandexMetricaId":null,"badge":null,"isOnline":false,"tgChannelShortname":null,"isUnsubscribable":true,"type":1,"subtype":"personal_blog"},"subsite":{"id":235819,"name":"Разработка","description":"Сообщество разработчиков: публикации о личном опыте, выдающиеся приёмы при решении рутинных задач, полезные материалы для профессионального роста.","uri":"/dev","avatar":{"type":"image","data":{"uuid":"fef5b5fb-e488-5b7f-8445-e3a26a910b44","width":1200,"height":1200,"size":7757,"type":"png","color":"343434","hash":"04042b2b1c1000","external_service":[]}},"cover":{"type":"image","data":{"uuid":"2a214cc5-35cc-58ca-bc07-fc1c892d2101","width":960,"height":280,"size":177,"type":"png","color":"343434","hash":"","external_service":[]}},"lastModificationDate":1642411346,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":false,"isDisabledAd":false,"nickname":"dev","isUnsubscribable":true,"badge":null,"badgeId":null,"isDonationsEnabled":false,"isOnline":false,"isPlus":false,"isUnverifiedBlogForCompanyWithoutPro":false,"isVerified":false,"isRemovedByUserRequest":false,"isFrozen":false,"isPro":false,"type":2,"subtype":"community"},"reactions":{"counters":[{"id":1,"count":5}],"reactionId":0},"isNews":false,"source":null,"clusters":[],"donations":{"amount":0,"isDonated":false},"commentsSeenCount":null}},{"type":"entry","data":{"id":109368,"customUri":null,"subsiteId":447345,"title":"Web Parsing. Основы на Python","date":1582816399,"dateModified":1582816399,"blocks":[{"type":"text","cover":true,"hidden":false,"anchor":"","data":{"text":"

Рассмотрим еще один практический кейс парсинга сайтов с помощью библиотеки BeautifulSoup: что делать, если на сайте нет готовой выгрузки с данными и нет API для удобной работы, а страниц для ручного копирования очень много?

"}},{"type":"media","cover":true,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"e89e8872-2562-3026-edef-cc68aa7ebf3a","width":1000,"height":520,"size":214195,"type":"jpg","color":"d0cabb","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Недавно мне понадобилось получить данные с одного сайта. Готовой выгрузки с информацией на сайте нет. Данные я вижу, вот они передо мной, но не могу их выгрузить и обработать. Возник вопрос: как их получить? Немного «погуглив», я понял, что придется засучить рукава и самостоятельно парсить страницу (HTML). Какой тогда инструмент выбрать? На каком языке писать, чтобы с ним не возникло проблем? Языков программирования для данной задачи большой набор, выбор пал на Python за его большое разнообразие готовых библиотек.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Примером для разбора основ возьмем сайт с отзывами banki_ru и получим отзывы по какому-нибудь банку.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Задачу можно разбить на три этапа:

"}},{"type":"list","cover":false,"hidden":false,"anchor":"","data":{"items":["Загружаем страницу в память компьютера или в текстовый файл.","Разбираем содержимое (HTML), получаем необходимые данные (сущности).
","Сохраняем в необходимый формат, например, Excel.
"],"type":"OL"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Инструменты

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Для начала нам необходимо отправлять HTTP-запросы на выбранный сайт. У Python для отправки запросов библиотек большое количество, но самые распространённые urllib/urllib2 и Requests. На мой взгляд, Requests — удобнее, примеры буду показывать на ней.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

А теперь сам процесс. Были мысли пойти по тяжелому пути и анализировать страницу на предмет объектов, содержащих нужную информацию, проводить ручной поиск и разбирать каждый объект по частям для получения необходимого результата. Но немного походив по просторам интернета, я получил ответ: BeautifulSoup – одна из наиболее популярных библиотек для парсинга. Библиотеки найдены, приступаем к самому интересному: к получению данных.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Загрузка и обработка данных

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Попробуем отправить запрос HTTP на сайт, чтобы получить первую страницу с отзывами по какому-нибудь банку и сохранить в файл, для того, чтобы убедиться, получаем ли мы нужную нам информацию.

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"import requests\nfrom bs4 import BeautifulSoup\n\nbank_id = 1771062 #ID банка на сайте banki.ru\n\nurl = 'https://www.banki.ru/services/questions-answers/?id=%d&p=1' % (bank_id) # url страницы\nr = requests.get(url)\nwith open('test.html', 'w') as output_file:\n output_file.write(r.text)","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

После исполнения данного скрипта получится файл text.html.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Открываем данный файл и видим, что необходимые данные получили без проблем.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Теперь очередь для разбора страницы на нужные фрагменты. Обрабатывать будем последние 10 страниц плюс добавим модуль Pandas для сохранения результата в Excel.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Подгружаем необходимые библиотеки и задаем первоначальные настройки.

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"import requests\nfrom bs4 import BeautifulSoup\nimport pandas as pd\n\nbank_id = 1771062 #ID банка на сайте banki.ru\npage=1\nmax_page=10\n\nurl = 'https://www.banki.ru/services/questions-answers/?id=%d&p=%d' % (bank_id, page) # url страницы","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

На данном этапе необходимо понять, где находятся необходимые фрагменты. Изучаем разметку страницы с отзывами и определяем, какие объекты будем вытаскивать из страницы.

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"a76fac78-d9cc-a54a-575d-82f12bca1bde","width":855,"height":431,"size":122695,"type":"jpg","color":"e9f0ed","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Подробно покопавшись во внутренностях страницы, мы увидим, что необходимые данные «вопросы-ответы» находятся в блоках <table class:qaBlock >, соответственно, сколько этих блоков на странице, столько и вопросов.

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"result = pd.DataFrame()\n\nr = requests.get(url) #отправляем HTTP запрос и получаем результат\nsoup = BeautifulSoup(r.text) #Отправляем полученную страницу в библиотеку для парсинга\ntables=soup.find_all('table', {'class': 'qaBlock'}) #Получаем все таблицы с вопросами\nfor item in tables:\n res=parse_table(item)","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Приступая к получению самих данных, я кратко расскажу о двух функциях, которые будут использованы:

"}},{"type":"list","cover":false,"hidden":false,"anchor":"","data":{"items":["Find(‘table’) – проводит поиск по странице и возвращает первый найденный объект типа ‘table’. Вы можете искать и ссылки find(‘table’) и рисунки find(‘img’). В общем, все элементы, которые изображены на странице;","find_all(‘table’) – проводит поиск по странице и возвращает все найденные объекты в виде списка
"],"type":"UL"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

У каждой из этих функций есть методы. Я расскажу от тех, которые использовал:

"}},{"type":"list","cover":false,"hidden":false,"anchor":"","data":{"items":["find(‘table’).text – этот метод вернет текст, находящийся в объекте;","find(‘a’).get(‘href’) – этот метод вернет значение ссылки
"],"type":"UL"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Теперь, уже обладая этими знаниями и навыками программирования на Python, написал функцию, которая разбирает таблицу с отзывом на нужные данные. Каждые стадии кода дополнил комментариями.

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"def parse_table(table):#Функция разбора таблицы с вопросом\n res = pd.DataFrame()\n\n id_question=0\n link_question=''\n date_question=''\n question=''\n who_asked=''\n who_asked_id=''\n who_asked_link=''\n who_asked_city=''\n answer=''\n \n question_tr=table.find('tr',{'class': 'question'})\n #Получаем сам вопрос\n question=question_tr.find_all('td')[1].find('div').text.replace('
','\\n').strip()\n \n widget_info=question_tr.find_all('div', {'class':'widget__info'})\n #Получаем ссылку на сам вопрос\n link_question='https://www.banki.ru'+widget_info[0].find('a').get('href').strip()\n #Получаем уникальным номер вопроса\n id_question=link_question.split('=')[1]\n\n #Получаем того кто задал вопрос\n who_asked=widget_info[1].find('a').text.strip()\n #Получаем ссылку на профиль\n who_asked_link='https://www.banki.ru'+widget_info[1].find('a').get('href').strip()\n #Получаем уникальный номер профиля\n who_asked_id=widget_info[1].find('a').get('href').strip().split('=')[1]\n\n #Получаем из какого города вопрос\n who_asked_city=widget_info[1].text.split('(')[1].split(')')[0].strip()\n \n #Получаем дату вопроса\n date_question=widget_info[1].text.split('(')[1].split(')')[1].strip()\n \n #Получаем ответ если он есть сохраняем\n answer_tr=table.find('tr',{'class': 'answer'})\n if(answer_tr!=None):\n answer=answer_tr.find_all('td')[1].find('div').text.replace('
','\\n').strip() \n \n #Пишем в таблицу и возвращаем\n res=res.append(pd.DataFrame([[id_question,link_question,question,date_question,who_asked,who_asked_id,who_asked_link,who_asked_city,answer]], columns = ['id_question','link_question','question','date_question','who_asked','who_asked_id','who_asked_city','who_asked_link','answer']), ignore_index=True)\n #print(res)\n return(res)","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Функция возвращает DataFrame, который можно накапливать и экспортировать в EXCEL.

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"result = pd.DataFrame()\n\nr = requests.get(url) #отправляем HTTP запрос и получаем результат\nsoup = BeautifulSoup(r.text) #Отправляем полученную страницу в библиотеку для парсинга\ntables=soup.find_all('table', {'class': 'qaBlock'}) #Получаем все таблицы с вопросами\nfor item in tables:\n res=parse_table(item)\n result=result.append(res, ignore_index=True)\n\nresult.to_excel('result.xlsx')","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Резюме

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

В результате мы научились парсить web-сайты, познакомились с библиотеками Requests, BeautifulSoup, а также получили пригодные для дальнейшего анализа данные об отзывах с сайта banki.ru. А вот и сама результирующая таблица.

"}},{"type":"media","cover":false,"hidden":false,"anchor":"","data":{"items":[{"title":"","image":{"type":"image","data":{"uuid":"737e1ffd-5d13-b70a-3839-c59421008451","width":1273,"height":372,"size":306060,"type":"jpg","color":"eef0f0","hash":"","external_service":[]}}}]}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Приобретенные навыки можно использовать для получения данных с других сайтов и получать обобщенную и структурированную информацию с бескрайних просторов Интернета.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Я надеюсь, моя статья была полезна. Спасибо за внимание.

"}}],"summaryContent":null,"isExistSummaryContent":false,"warningFromEditor":null,"warningFromEditorTitle":null,"counters":{"comments":7,"favorites":80,"reposts":0,"views":0,"hits":113983,"reads":null,"online":0},"dateFavorite":0,"hitsCount":113983,"isCommentsEnabled":true,"isLikesEnabled":true,"isRemovedByUserRequest":false,"isFavorited":false,"isPinned":false,"repostId":null,"repostData":null,"subscribedToTreads":false,"isEditorial":false,"isAudioAvailable":false,"audioUrl":null,"isAudioAvailableToGenerate":false,"commentEditor":{"enabled":true,"who":null,"text":"","until":null,"reason":null,"type":"everybody"},"isBlur":false,"isPublished":true,"isDisabledAd":false,"withheld":[],"ogTitle":null,"ogDescription":null,"url":"https://vc.ru/id447345/109368-web-parsing-osnovy-na-python","author":{"id":447345,"name":"NTA","nickname":null,"description":null,"uri":"","avatar":{"type":"image","data":{"uuid":"e7175678-aaab-09f8-0271-7b3af7ac4670","width":1207,"height":1207,"size":83090,"type":"jpg","color":"e3ebf8","hash":"","external_service":[]}},"cover":{"cover":{"type":"image","data":{"uuid":"8575b55d-a1f0-53ee-9ad6-78268f9ea45c","width":1280,"height":373,"size":56005,"type":"jpg","color":"b0b9ca","hash":"","external_service":[]}},"cover_y":0},"achievements":[{"title":"Год на vc.ru","code":"registration_1_year","description":"Первый год с vc.ru. Получена 24 июля 2025.","previewUuid":"0d11c244-49de-50e7-894e-b9b27945d42b","formats":{"glb":"https://static.vc.ru/achievements/fish.glb","usdz":"https://static.vc.ru/achievements/fish.usdz"},"viewData":{"contentColor":"#C67AA3","textMaxWidth":0.634765625,"textX":0.5888671875,"textY":0.54296875,"logoX":0.5859375,"logoY":0.6669921875,"logoXNoText":0.6044921875,"logoYNoText":0.5439453125},"id":4980908,"userId":447345,"count":0,"shareImage":"https://api.vc.ru/achievements/share/4980908"},{"title":"3 года на vc.ru","code":"registration_3_years","description":"Провёл 3 года вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"d9d72ac5-bcb5-55e0-8c72-b99251e5cdd9","formats":{"glb":"https://static.vc.ru/achievements/shark.glb","usdz":"https://static.vc.ru/achievements/shark.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.5205078125,"textY":0.341796875,"logoX":0.5205078125,"logoY":0.4609375,"logoXNoText":0.5,"logoYNoText":0.3662109375},"id":1356821,"userId":447345,"count":0,"shareImage":"https://api.vc.ru/achievements/share/1356821"},{"title":"5 лет на vc.ru","code":"registration_5_years","description":"Провёл 5 лет вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"a9140d54-73b8-5f40-afa8-449fbaafd42b","formats":{"glb":"https://static.vc.ru/achievements/whale.glb","usdz":"https://static.vc.ru/achievements/whale.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.533203125,"textY":0.658203125,"logoX":0.533203125,"logoY":0.77734375,"logoXNoText":0.4375,"logoYNoText":0.66015625},"id":130113,"userId":447345,"count":0,"shareImage":"https://api.vc.ru/achievements/share/130113"}],"lastModificationDate":1764937376,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":true,"badgeId":null,"isDonationsEnabled":false,"isPlusGiftEnabled":true,"isUnverifiedBlogForCompanyWithoutPro":true,"isRemovedByUserRequest":false,"isFrozen":false,"isDisabledAd":false,"isPlus":false,"isVerified":false,"isPro":false,"yandexMetricaId":null,"badge":null,"isOnline":false,"tgChannelShortname":null,"isUnsubscribable":true,"type":1,"subtype":"personal_blog"},"subsite":{"id":447345,"name":"NTA","nickname":null,"description":null,"uri":"","avatar":{"type":"image","data":{"uuid":"e7175678-aaab-09f8-0271-7b3af7ac4670","width":1207,"height":1207,"size":83090,"type":"jpg","color":"e3ebf8","hash":"","external_service":[]}},"cover":{"cover":{"type":"image","data":{"uuid":"8575b55d-a1f0-53ee-9ad6-78268f9ea45c","width":1280,"height":373,"size":56005,"type":"jpg","color":"b0b9ca","hash":"","external_service":[]}},"cover_y":0},"achievements":[{"title":"Год на vc.ru","code":"registration_1_year","description":"Первый год с vc.ru. Получена 24 июля 2025.","previewUuid":"0d11c244-49de-50e7-894e-b9b27945d42b","formats":{"glb":"https://static.vc.ru/achievements/fish.glb","usdz":"https://static.vc.ru/achievements/fish.usdz"},"viewData":{"contentColor":"#C67AA3","textMaxWidth":0.634765625,"textX":0.5888671875,"textY":0.54296875,"logoX":0.5859375,"logoY":0.6669921875,"logoXNoText":0.6044921875,"logoYNoText":0.5439453125},"id":4980908,"userId":447345,"count":0,"shareImage":"https://api.vc.ru/achievements/share/4980908"},{"title":"3 года на vc.ru","code":"registration_3_years","description":"Провёл 3 года вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"d9d72ac5-bcb5-55e0-8c72-b99251e5cdd9","formats":{"glb":"https://static.vc.ru/achievements/shark.glb","usdz":"https://static.vc.ru/achievements/shark.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.5205078125,"textY":0.341796875,"logoX":0.5205078125,"logoY":0.4609375,"logoXNoText":0.5,"logoYNoText":0.3662109375},"id":1356821,"userId":447345,"count":0,"shareImage":"https://api.vc.ru/achievements/share/1356821"},{"title":"5 лет на vc.ru","code":"registration_5_years","description":"Провёл 5 лет вместе с vc.ru. Получена 23 июля 2025.","previewUuid":"a9140d54-73b8-5f40-afa8-449fbaafd42b","formats":{"glb":"https://static.vc.ru/achievements/whale.glb","usdz":"https://static.vc.ru/achievements/whale.usdz"},"viewData":{"contentColor":"#8E6F09","textMaxWidth":0.66796875,"textX":0.533203125,"textY":0.658203125,"logoX":0.533203125,"logoY":0.77734375,"logoXNoText":0.4375,"logoYNoText":0.66015625},"id":130113,"userId":447345,"count":0,"shareImage":"https://api.vc.ru/achievements/share/130113"}],"lastModificationDate":1764937376,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":true,"badgeId":null,"isDonationsEnabled":false,"isPlusGiftEnabled":true,"isUnverifiedBlogForCompanyWithoutPro":true,"isRemovedByUserRequest":false,"isFrozen":false,"isDisabledAd":false,"isPlus":false,"isVerified":false,"isPro":false,"yandexMetricaId":null,"badge":null,"isOnline":false,"tgChannelShortname":null,"isUnsubscribable":true,"type":1,"subtype":"personal_blog"},"reactions":{"counters":[{"id":1,"count":7}],"reactionId":0},"isNews":false,"source":null,"clusters":[],"donations":{"amount":0,"isDonated":false},"commentsSeenCount":null}}],"ogTitle":null,"ogDescription":null,"isAnonymized":true}};