Як я зробив свій «Яндекс.Транспорт» з розкладом і автобусами

  1. З чого все почалося
  2. Де взяти дані?
  3. Чому Python?
  4. функціонал бота
  5. функціонал сайту

З чого все почалося

Восени 2014 року з'явилася радісна новина про те, що в Воронежі заробив Яндекс.Транспорт, який показує рух автобусів і тролейбусів. Було дуже круто прямо на зупинці відкрити розклад і дізнатися, що ваш автобус підійде через 5 хвилин.

Але вже через пару місяців все пішло по цілком передбачуваним сценарієм. Оскільки весь транспорт у Воронежі від тролейбуса до маршрутки працює «на готівці», кожен водій зацікавлений в тому, щоб перевезти якомога більше пасажирів. В результаті вони влаштовують гонки між собою.

Новий сервіс водії використовували, щоб стежити один за одним по карті, обганяючи і підрізаючи конкурентів на дорозі. У деяких почала падати виручка, вони стали скаржитися власникам маршрутів, а ті пішли до людей, які продають обладнання з ГЛОНАСС і GPS і відправляють дані про переміщення машин в Яндекс. На прохання господарів автопарків вони інформацію відправляти перестали, і автобуси відразу почали зникати з карти. Зараз їх стало трохи більше, але це все одно набагато менше, ніж насправді.

Для тих, кому ліньки читати далі, пропоную відео доповіді на цю тему:

Для інших - опишу проект у вигляді тексту.

Де взяти дані?

При цьому в в Воронежі є місце, де збираються всі дані - Центр Організації Дорожнього Руху (ЦОДД). У них на сайті є велике і важке веб-додаток з неотлаженностью JavaScript і іншими артефактами, при цьому всі в ньому йде POST-запитів і нічого не кешируєтся. За допомогою самого цього сайту можна запросто покласти сервіс, який збирає дані про пересування автобусів.

Там була опція, що дозволяє ткнути на карту і дізнатися, коли прийде автобус і яким він буде. За умови, що ви приблизно потрапляєте в зупинку (± 50 метрів). У меню можна було відкрити список маршрутів і подивитися, де саме їздять автобуси, але там була проблема - їздили вони дивно. Наприклад, по Кольцовском, вулиці в центрі, де особливо не розженешся, автобус переміщувався вперед і назад зі швидкістю приблизно 200 км / ч.

Чому Python?

Я вибрав Python бо він класний, батарейки в комплекті, і т. Д. А 3.6 тому, що тут є форматування строкових літералів, typing, ось це все. Давайте подивимося на те, що я в принципі використовував:

  • Багато скаржилися, що вбити точну назву зупинки зі всякими знаками пунктуації дуже важко. Тоді я реалізував можливість нечіткого пошуку і створив для нього перший юніт-тест.
  • Вся система хоститься на Heroku. Безкоштовно, оскільки у мене немає бази даних - я сподіваюся обійтися базою ЦОДД. Про її використанні я домовився з Центром, коли зрозумів, що даних, які я забираю через веб-інтерфейс, недостатньо.
  • Власне, хостинг йде через веб-сервер Tornado. Думаю, він знайомий кожному, хто стикався з веб-запитами в Python.
  • Пакет Pytz знадобився мені, тому що сервер Heroku знаходиться в іншому часовому поясі, а дані до мене надходять без вказівки тимчасової зони. Тому я сам подбав про локалізацію.
  • Для створення бота я використовував рекомендовану бібліотеку Python-telegram-bot . Документація тут цілком адекватна, і взагалі бібліотека відповідає вимогам minimum viable product. Спочатку весь проект був Telegram-бота, який у відповідь на відправку вашого місця розташування надсилав розклад автобусів.
  • Firebird, колишній Interbase - Open source база даних, з якої, гадаю, багато хто з вас працювали. Звичайно, вона не така крута, як той же самий PostgreSQL, але для дуже великої кількості запитів її досить. У нашому випадку більшого не потрібно.
  • Caсhetools - дуже простий модуль, який дозволяє кешувати обчислення. Мова тут, звичайно, не про memecached або кешування веб-сторінок, а про ті випадки, коли вам потрібна мемоізація на довгі запити. Просто берете, додаєте відповідний декоратор - і все працює. Кеш має різні варіанти, я використовую TTL-версію, який зберігає дані на вказаний час, тому що я знаю, що дані не будуть оновлюватися частіше, ніж через певні проміжки часу (в моєму випадку - 30 секунд).

функціонал бота

  • / Nextbus ім'я зупинки - очікуваний час прибуття;
  • / Last номери маршрутів через пробіл - останні зупинки;
  • Обмін розташуванням - очікуваний час прибуття для найближчих трьох зупинок;
  • Вільний введення - номери маршрутів і відстань до автобусів (при відправці розташування).

Команди я постарався описати досить повно, щоб люди не питали, як ними користуватися. Базових команд по суті дві: nextbus, коли ви пишете назву зупинки, і відправка місцеположення.

функціонал сайту

Bеб-сайт я зробив настільки мінімалістичним, наскільки це в принципі можливо. З сторонніх бібліотек використовував всього дві, для підтримки fetch і promise, тому що старі версії встановлених браузерів в телефонах не вміють обходитися без них. Якщо не підтримати ці методи, вийде досить важка локшина з коллбеков для самих запитів. З fetch все виглядає витонченіше.

Власне, функціонал тут складається з 4 пунктів:

  1. Прибуття. Можна просто подивитися зупинку. Натиснувши на кнопку (її, до речі, може бути, варто зробити побільше - я подумаю!), Ви відправляєте своє місце розташування, система шукає три найближчі до вас зупинки і показує інформацію по ним. Можна ввести назву зупинки і отримати інформацію по ній. Оскільки вам навряд чи потрібні всі 20-30 автобусів, які можуть приїхати до зупинки, ви можете відфільтрувати їх за маршрутами.
  2. Автобуси. На другій сторінці зібрана інформація по автобусах. Це пов'язано ще з однією історією, яка підштовхнула мене до цього проекту. В один прекрасний день я забув в автобусі шапку, подзвонив в диспетчерську, пояснив, де це сталося. Диспетчер запропонував мені ловити свій автобус в центрі, куди він повернеться, розвернувшись на кінцевій. Я згадав, що у мене є логін і пароль від системи Центру організації дорожнього руху, але виявилося, що відстежити місце розташування потрібної мені машини я через веб-інтерфейс все одно не можу. Шапку я повернув, але з великими труднощами.
    Я подумав, що пошук автобуса міг би бути набагато простіше. Написав номер маршруту, а система показує тобі машини на лінії, їх поточне місце розташування і час, коли вони проходили зупинки по шляху. І навіть якщо ви знаєте номер маршруту, але ви знаєте номер автобуса (таке теж буває), ви все одно зможете його знайти.
  3. Мапа. Карта на сайті без анімації. Тут можна вибирати автобуси зі списку або вводити номера вручну, можна їх відфільтрувати. На карті можуть бути показані до 600 автобусів, хоча вже після 20 знайти щось в центрі стає складно, просто тому, що маршрути все сконцентровані тут. Тому краще обмежувати пошук параметрами більш жорстко.
  4. Про проект. Зараз у проекту є сайт, є Telegram-бот, групи в соціальних мережах.

На щастя, Python - це мова з батарейками з коробки. Для нескладних речей, вам навіть нічого скачувати не потрібно, достатньо уважно прочитати документацію.

Зрозуміло, такі сервіси можна робити і для інших міст, більш того, в деяких вони вже працюють. Багато що залежить від місцевого ЦОДД, подекуди, наприклад, в Санкт-Петербурзі є навіть API для розробників. Але найголовніше - городяни, які хочуть змінювати своє місто на краще.

Чому Python?
Де взяти дані?
Чому Python?