Коммерческая недвижимость — актив, в котором каждая деталь имеет значение: местоположение, планировка, техническое состояние, спрос на рынке и даже имидж владельца. Когда приходит время продать, сдать в аренду или рассчитать налоговую базу, без профессиональной оценки стоимости помещения
Я очень люблю готовить, поэтому постоянно закупаюсь ингредиентами для различных блюд. Однако, в последний раз я закупил их слишком много, теперь срок их годности подходит к концу. Но не выкидывать же продукты в мусорную корзину? Конечно, я бы мог использовать их все разом, но вряд ли блюдо в таком случае получится вкусным. Или же приготовить множес…
Новый год — время подарков. Но если вы арбитражник — это время еще и для того, чтобы собирать сливки. Новогодний VK-бот для розыгрышей Дед Мороз совмещает в себе и то и другое, а заодно соберет информацию о пользователях, чтобы ваши рекламные кампании в 2023-м были еще эффективнее.
Представьте ситуацию: вас назначили спикером на мероприятии, и вы даже знаете, о чем хотите рассказать аудитории. Но будет ли публикой воспринят ваш доклад так, как вы себе это представляли? Давайте посмотрим, что может пойти не так и как это исправить.
Как часто нам приходится выступать с докладом, презентацией, проводить обучение, быть спик…
В этой статье я вкратце расскажу как работать с Ether-based блокчейнами на примере Binance Smart Chain Первым делом необходимо установить модуль web3. Модуль web3 предоставляет API для взаимодействия между приложениями разработанными на Python и блокчейном Ethereum (BSC и проч.)
Привет! Я Владимир Малюгин, CEO агентства performance-маркетинга Digital Geeks. Мы активно автоматизируем процессы: это удобно и выгодно. В статье я расскажу, как создать алгоритм, который проверяет наличие товаров в десятке маркетплейсов. А затем останавливает или запускает контекстную рекламу без участия человека.
Недавно мы решали следующую задачу – необходимо найти и удалить содержащие номера карт файлы, размещенные на общем ресурсе. Если нужно было бы искали что-то, определенное и однозначное, мы могли бы воспользоваться поиском в самой операционной системе (используя стандартны поиск текста в содержимом файла). Но, как правило, поиск стандартными средств…
Рассмотрим еще один практический кейс парсинга сайтов с помощью библиотеки BeautifulSoup: что делать, если на сайте нет готовой выгрузки с данными и нет API для удобной работы, а страниц для ручного копирования очень много?
Коммерческая недвижимость — актив, в котором каждая деталь имеет значение: местоположение, планировка, техническое состояние, спрос на рынке и даже имидж владельца. Когда приходит время продать, сдать в аренду или рассчитать налоговую базу, без профессиональной оценки стоимости помещения
Я очень люблю готовить, поэтому постоянно закупаюсь ингредиентами для различных блюд. Однако, в последний раз я закупил их слишком много, теперь срок их годности подходит к концу. Но не выкидывать же продукты в мусорную корзину? Конечно, я бы мог использовать их все разом, но вряд ли блюдо в таком случае получится вкусным. Или же приготовить множес…
Новый год — время подарков. Но если вы арбитражник — это время еще и для того, чтобы собирать сливки. Новогодний VK-бот для розыгрышей Дед Мороз совмещает в себе и то и другое, а заодно соберет информацию о пользователях, чтобы ваши рекламные кампании в 2023-м были еще эффективнее.
Представьте ситуацию: вас назначили спикером на мероприятии, и вы даже знаете, о чем хотите рассказать аудитории. Но будет ли публикой воспринят ваш доклад так, как вы себе это представляли? Давайте посмотрим, что может пойти не так и как это исправить.
Как часто нам приходится выступать с докладом, презентацией, проводить обучение, быть спик…
В этой статье я вкратце расскажу как работать с Ether-based блокчейнами на примере Binance Smart Chain Первым делом необходимо установить модуль web3. Модуль web3 предоставляет API для взаимодействия между приложениями разработанными на Python и блокчейном Ethereum (BSC и проч.)
Привет! Я Владимир Малюгин, CEO агентства performance-маркетинга Digital Geeks. Мы активно автоматизируем процессы: это удобно и выгодно. В статье я расскажу, как создать алгоритм, который проверяет наличие товаров в десятке маркетплейсов. А затем останавливает или запускает контекстную рекламу без участия человека.
Недавно мы решали следующую задачу – необходимо найти и удалить содержащие номера карт файлы, размещенные на общем ресурсе. Если нужно было бы искали что-то, определенное и однозначное, мы могли бы воспользоваться поиском в самой операционной системе (используя стандартны поиск текста в содержимом файла). Но, как правило, поиск стандартными средств…
Рассмотрим еще один практический кейс парсинга сайтов с помощью библиотеки BeautifulSoup: что делать, если на сайте нет готовой выгрузки с данными и нет API для удобной работы, а страниц для ручного копирования очень много?
7
Что теперь?`[index] ==\"Нет в наличии\" )\n {\n ads_to_stop <-rbind(ads_to_stop,my_camp$Id[i])\n }\n if (surveyresults
Коммерческая недвижимость — актив, в котором каждая деталь имеет значение: местоположение, планировка, техническое состояние, спрос на рынке и даже имидж владельца. Когда приходит время продать, сдать в аренду или рассчитать налоговую базу, без профессиональной оценки стоимости помещения
Я очень люблю готовить, поэтому постоянно закупаюсь ингредиентами для различных блюд. Однако, в последний раз я закупил их слишком много, теперь срок их годности подходит к концу. Но не выкидывать же продукты в мусорную корзину? Конечно, я бы мог использовать их все разом, но вряд ли блюдо в таком случае получится вкусным. Или же приготовить множес…
Новый год — время подарков. Но если вы арбитражник — это время еще и для того, чтобы собирать сливки. Новогодний VK-бот для розыгрышей Дед Мороз совмещает в себе и то и другое, а заодно соберет информацию о пользователях, чтобы ваши рекламные кампании в 2023-м были еще эффективнее.
Представьте ситуацию: вас назначили спикером на мероприятии, и вы даже знаете, о чем хотите рассказать аудитории. Но будет ли публикой воспринят ваш доклад так, как вы себе это представляли? Давайте посмотрим, что может пойти не так и как это исправить.
Как часто нам приходится выступать с докладом, презентацией, проводить обучение, быть спик…
В этой статье я вкратце расскажу как работать с Ether-based блокчейнами на примере Binance Smart Chain Первым делом необходимо установить модуль web3. Модуль web3 предоставляет API для взаимодействия между приложениями разработанными на Python и блокчейном Ethereum (BSC и проч.)
Привет! Я Владимир Малюгин, CEO агентства performance-маркетинга Digital Geeks. Мы активно автоматизируем процессы: это удобно и выгодно. В статье я расскажу, как создать алгоритм, который проверяет наличие товаров в десятке маркетплейсов. А затем останавливает или запускает контекстную рекламу без участия человека.
Недавно мы решали следующую задачу – необходимо найти и удалить содержащие номера карт файлы, размещенные на общем ресурсе. Если нужно было бы искали что-то, определенное и однозначное, мы могли бы воспользоваться поиском в самой операционной системе (используя стандартны поиск текста в содержимом файла). Но, как правило, поиск стандартными средств…
Рассмотрим еще один практический кейс парсинга сайтов с помощью библиотеки BeautifulSoup: что делать, если на сайте нет готовой выгрузки с данными и нет API для удобной работы, а страниц для ручного копирования очень много?
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 платформа с интуитивно-понятным интерфейсом. Для работы с ней не нужно уметь программировать — достаточно понимать структуру и логику соединяемых систем, а также знать английский язык, чтобы читать названия полей сервиса.
Публикую пошаговый визуал по настройке рассылки в 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 минут. А специалисты агентства вместо перехода по ссылкам и изучения таблиц могут заняться задачами, которые требуют креативности и интеллекта.
Не менее очевидна выгода для заказчика. Благодаря автоматизации он может быть уверен, что бюджет не уходит на рекламу страниц товара, который нельзя заказать.
Cоздание индивидуальных алгоритмов вместо выбора готовых сервисов ежемесячно экономит компании порядка 150 тыс. рублей.А оперативное оповещение о том, какой товар на каком сайте закончился, помогает нашему партнеру вовремя пополнять запасы продукции во всех интернет-магазинах, не допуская простоя.
Если вы хотите знать больше о продвижении в интернете, загляните в наш телеграм-канал 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":"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. Этот бот ответственен за регистрацию всех остальных ботов;
3) Отправляем имя бота (оно может быть любым) и ник бота (обязательно должен оканчиваться на «bot»). Если у тебя выходит ошибка, то значит этот ник занят. Пробуй другой.
Супер! Бот создан и уже доступен внутри Telegram по нику. Можешь вбить в поиске и убедиться. Также ты можешь найти его по ссылке t.me/НикТвоегоБота. Например на скриншоте я зарегистрировал SayMyAddressBot, значит его ссылка t.me/SayMyAddressBot. Сохрани такую ссылку с ником твоего бота. Скоро она нам пригодится.
"}},{"type":"header","cover":false,"hidden":false,"anchor":"","data":{"style":"h2","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":"
"}},{"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.: параметров гораздо больше, но нам они не нужны. Подробнее можешь почитать тут.
Токен активируется через 15 минут после создания. Можешь прямо в браузере (Chrome, Safari или что там у тебя) вбить (не забудь подставить свой токен в конце).
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":"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":"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":"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 с помощью команды:
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 и сохраняем этот код в нём.
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":"
"}}],"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":"
Недавно мы решали следующую задачу – необходимо найти и удалить содержащие номера карт файлы, размещенные на общем ресурсе. Если нужно было бы искали что-то, определенное и однозначное, мы могли бы воспользоваться поиском в самой операционной системе (используя стандартны поиск текста в содержимом файла). Но, как правило, поиск стандартными средствами занимает очень много времени. А если еще нужно хотите использовать маски или регулярные выражения, то как быть? Поделимся, как мы решили эту задачу.
Данную задачу можно решить на многих языках взяв за основу идею, описанную в этой статье. Я буду делать реализацию на языке Python, а инструменты использовать «из коробки», без импорта сторонних библиотек. Почему я не использовал библиотеку Pandas? Pandas хороший инструмент для работы с файлами Excel, но он достаточно массивный и ресурсоемкий для решения нашей задачи.
Углубимся в формат XLSX. Что он из себя представляет? Файл Excel — это обычный структурированный архив с расширением. XLSX. Если мы изменим расширение на. ZIP, то сможем открыть его с помощью архиватора, установленного в вашей операционной системе.
В файле [sharedString.xml] хранятся все текстовые поля, которые есть на листах в Excel, т.е. если поле текстовое, то оно будет хранится в этом файле, а ссылка на это поле будет находится в директории [worksheets] на соответствующем листе. Если в нескольких ячейках будет одно и тоже слово, то в файле будет одно слово, а в ячейках будет указана одна ссылка на это слово (см. рис.).
Итак, мы знаем, что номер карты является текстовым полем, соответственно он будет находится в этом файле. Приступим к написанию кода. Нам понадобятся следующие библиотеки: 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":"
Наша работа сделана. Ждем, когда отработает скрипт и получим итоговый файл для анализа. Вы зададите вопрос, почему я сразу не стал удалять файлы? Потому что поиск основан на простом регулярном выражении и туда могут попасть номера заявок, договоров и т.д.
"}}],"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 для удобной работы, а страниц для ручного копирования очень много?
Недавно мне понадобилось получить данные с одного сайта. Готовой выгрузки с информацией на сайте нет. Данные я вижу, вот они передо мной, но не могу их выгрузить и обработать. Возник вопрос: как их получить? Немного «погуглив», я понял, что придется засучить рукава и самостоятельно парсить страницу (HTML). Какой тогда инструмент выбрать? На каком языке писать, чтобы с ним не возникло проблем? Языков программирования для данной задачи большой набор, выбор пал на Python за его большое разнообразие готовых библиотек.
"}},{"type":"list","cover":false,"hidden":false,"anchor":"","data":{"items":["Загружаем страницу в память компьютера или в текстовый файл.","Разбираем содержимое (HTML), получаем необходимые данные (сущности). ","Сохраняем в необходимый формат, например, Excel. "],"type":"OL"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"
Для начала нам необходимо отправлять HTTP-запросы на выбранный сайт. У Python для отправки запросов библиотек большое количество, но самые распространённые urllib/urllib2 и Requests. На мой взгляд, Requests — удобнее, примеры буду показывать на ней.
А теперь сам процесс. Были мысли пойти по тяжелому пути и анализировать страницу на предмет объектов, содержащих нужную информацию, проводить ручной поиск и разбирать каждый объект по частям для получения необходимого результата. Но немного походив по просторам интернета, я получил ответ: BeautifulSoup – одна из наиболее популярных библиотек для парсинга. Библиотеки найдены, приступаем к самому интересному: к получению данных.
Попробуем отправить запрос 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.
Теперь очередь для разбора страницы на нужные фрагменты. Обрабатывать будем последние 10 страниц плюс добавим модуль Pandas для сохранения результата в Excel.
Подгружаем необходимые библиотеки и задаем первоначальные настройки.
"}},{"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":"
На данном этапе необходимо понять, где находятся необходимые фрагменты. Изучаем разметку страницы с отзывами и определяем, какие объекты будем вытаскивать из страницы.
Подробно покопавшись во внутренностях страницы, мы увидим, что необходимые данные «вопросы-ответы» находятся в блоках <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":"
В результате мы научились парсить web-сайты, познакомились с библиотеками Requests, BeautifulSoup, а также получили пригодные для дальнейшего анализа данные об отзывах с сайта banki.ru. А вот и сама результирующая таблица.
Приобретенные навыки можно использовать для получения данных с других сайтов и получать обобщенную и структурированную информацию с бескрайних просторов Интернета.
Я надеюсь, моя статья была полезна. Спасибо за внимание.
"}}],"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}};