Как мы делали оповещения о поломках метро
Давным-давно, примерно с год назад, когда Московское метро ломалось в рандомных местах и удивительно часто, у нас (dcoder_mm & Irenica) возникла мысль: сделать какой нибудь сервис, для оповещения о поломках.
Вам эта идея может показаться странной, dcoder_mm тоже так казалось, до тех пор, пока сам в одну из таких поломок не попал. Стоять на переполненной платформе 10 минут в ожидании поезда, как оказалось неприятно, да так, что впредь решил так не попадаться.
После этого происшествия решили полистать twitter: пишут ли что-нибудь о происшествиях в метро. Как выяснилось, пишут. Причем первые твиты об этом были минут за 10 до того как зашел в метро.
Тут потихоньку и начала зарождаться идея: собираем информацию из twitter, ищем упоминания поломок метро и оповещаем пользователя, если что-то нашлось.
Правда потом эта идея была заброшена на долгое время, но осенью 2014 мы снова о ней вспомнили — метро опять стало регулярно ломаться.
В качестве способа оповещения решено было использовать смс. Можно было, конечно, использовать что-то другое, хоть твиттер-бота для аггрегации сообщений о метро завести, но у смс есть одно преимущество — они доходят даже когда нет нормального подключения к интернету. А в метро его часто не бывает, но при этом GSM ловится нормально. (Когда мы начали делать сервис, Wifi во всем метро еще не было).
Дело оставалось за малым — собственно, сделать парсилку твитов и отправку смс.
Для проверки боем был написан простенький однострочный скрипт, получающий через поиск (curl search.twitter.com) последние твиты с хештегом #метро, выделяющий из них нужные по ключевым словам, и отправляющий нам смс.
curl -ssl «https://twitter.com/search? f=realtime&q=%23%D0%BC%D0%B5%D1%82%D1%80%D0%BE&src=typd» | grep -E -o «js-tweet-text tweet-text.*<\/p>» | sed -e 's;[><\"=-]; ;g;s;js tweet text tweet text lang ru data aria label part 0;;g;s;/a;;g;s;\/\(a\|p\); ;g;s;\(.span\|.strong\|class\|twitter\|timeline\|link\|js display url\|invisible|\tco ellipsis\|href\|nofollow\|dir\|ltr\|data\|expanded\|url\|invisible\|tco\|ellipsis\|google&\;utm_medium\|banner&\;utm_campaign\|business_news\|target\|_blank\|title\|atreply\|pretty\| \;\|rel\|s\|?utm_source\|draggable\|false\|alt\|aria\|label\|u\|hidden\|pre\|embedded|\true\|b\|a\|qery\|orce\|hahtag_click\|hahtag\|j\|nav\|emedded\|tre\|&qot\;\|emedded\|tre\|rc\|hh\|qery\|orce\|hhtg_click\|hhtg\|img\);;g;s; ; ;g;s; \; ;;g;s;&qot\;;;g;s;emedded;;g;s;tre;;g;s; \/ ;;g;s;hhtg_click hhtg;;g;s;hh;;g;s;qery oe;;g;s;\/tg\/[a-zA-Z]*;;g;s;tweet;;g;s;text;;g;s;lng;;g;s;nd;;g;s;prt;;g;s;http://intgrm.com\s\/[a-zA-Z]*\/;;g;s;[A-Z%a-z]*;;g;s;[\/_\/:\/?\.@&…]*;;g;s;^[0-9]*;;g;s;[0-9]\{3,\};;g;s;^\s*;;g;s; *; ;g;s;^[0-9] ;;g;s;# ;#;g;s;[0-9 #]*$;;g' | grep -E -i "жертв|авари|ЧП|неполадки|не будет работать|закр|перебои|застрял|интервал|катастрофа|перекрыт|остановлен|простоял|битком|затык|интервал|не ходят|ремонт|приостановлено|сбой|неисправ|сломался поезд|бомб|взрыв|теракт|затруднен|приостанов|траур|давк|дым|взорв|стрел|наводнен|вода|потоп|затопил|на рельсы|не ходят|не идут|напряжение" | grep -E -i "Марьин|Достоевск|Трубн|Сретенск|Чкаловск|Римск|Крестьянск|Дубровк|Кожуховск|Печатник|Волжск|Люблин|Братиславск|Марьин|Борисов|Шипиловск|ЗябликовВаршавск|Каховск|Лесопарков|Старокачаловск|Скобелевск|Ушаков|Горчаков|БунинскРокоссовс|Черкизовс|Преображенск|Сокольн|Красносельск|Красн|Чисты|Лубянк|Охотн|Библиотек|Кропоткинск|Фрунзенск|Спортивн|Воробьёв|Университет|Вернадск|ЮгоЗападн|Западн|Юго Западн|Тропарев|Алма|Красногвардейск|Домодедовск|Орехов|Царицын|Кантемировск|Каширск|Коломенск|Автозаводск|Новокузнецк|Театральн|Тверск|Маяковск|Динам|Аэропорт|Сокол|Войковск|Водн|Речн|Пятницк|Митин|Волоколамск|Мякинин|Строгин|Крылатск|Молодежн|Кунцевск|Славянск|Побед|Смоленск|Арбат|Революц|Бауманск|Электрозаводск|Семеновск|Партизанск|Измайловск|Первомайск|Щелковск|Александровск|Смоленск|Выставочн|Международн|Студенческ|Кутузовск|Фил|Багратионовск|Филевск|Пионерск|Белорусск|Новослободск|проспект Мир|Комсомольск|Курск|Таганск|Павелецк|Добрынинск|Октябрьск|культур|Киевск|КраснопресненскМедведков|Бабушкинск|Свиблов|Ботаническ|ВДНХ|Алексеевск|Рижск|Сухаревск|Тургеневск|Третьяковск|Шаболовск|Ленинск|Академическ|Профсоюзн|Черемушк|Калужск|Беляев|Коньков| Стан |Ясенев|Новоясеневск|Жулебин|Лермонтовск|Выхин|Рязанск|Кузьминк|Текстильщик|Волгоградск|Пролетарск|Китай-город|Кузнецк|Пушкинск|Баррикадн|1905|Бегов|Полежаевск|Октябрьск[а-я ]поле|Щ[ую]кинск|Спартак|Тушинск|Сходненск|Планерн|Новокосин|Новогиреев|Перов|Энтузиаст|Авиамоторн|Ильич|Марксистск|Третьяковск|Делов|Алтуфьев|Бибирев|Отрадн|Владыкин|Петровск|Разумовск|Тимирязевск|Дмитровск|Савеловск|Менделеевск|Цветн|Чеховск|Боровицк|Полянк|Серпуховск|Тульск|Нагатинск|Нагорн|Нахимовск|Севастопольск|Чертановск|Южна|Пражск|Янгел|Аннин|Донск|арбатско-покровск| апл | син[яиюе]|таганско-краснопресненск| ткл |фиолетов[аоу][йюя]|замоскворецк| зл |зел[её]н[аоу][йюя]|серпуховско-тимизязевск| стл | сер[уоа][яйю]|сокольническ| сл | красн[аоу][яйу]|фил[её]вск| фл |голуб[аоу][йюя]|кольц|калужско-рижск| крл | рыж[еау][йюя]|калининск| кл |ж[её]лт[аоу][йюя]|оранжев[оау][йюя]|люблинск|салатов| лк |каховск|бутовск" | grep -i -v -E "лет назад|год назад|года назад|вспомнил|одесс|украин|спб|питер|петербург|санкт-петербург|повер|резиден|память|годжи|ягод|такси|окна|займ|деньг|iphone|худе|акци|скидк|порн|porn|pron|прон|диет|follow|retweet|скачать|бесплатн|курит смес|спайс|минск|истор|жизнь прекрасна|крещатник|квартир|выжил|прокуратур|киев |киеве|уголовное|Лесн|Геро Днепр|Сырецк|Черниговск|Минск|Дорогожичи|Дарниц|Оболон|Лукьяновск|Левобережн|Петровк|Золот ворот|Гидропарк|Тарас Шевченк|Дворец Спорт|Днепр|Контрактов площад|Кловск|Арсенальн|Почтов площад|Печерск|Крещатик|Майдан Независимост|Дружб Народ|площад Льв Толстог|Выдубич|Олимпийск|Славутич|Вокзальн|Дворец Украин|Осокорк|Политехническ институт|Лыбедск|Позняк|Шулявск|Димеевск|Харьковск|Берестейск|Голосеевск|Вырлиц|Нивк|Васильковск|Бориспольск|Святошин|Красн хутор|Житомирск|Ипподром|Академгородок|Теремк|париж|больниц|бостон|голос|кровь" | sort | uniq И как ни странно, оно вполне нормально заработало. Иногда, конечно, попадались ложные срабатывания, но главное — оповещения приходили при всех мало-мальски важных поломках. И приходили быстро — значительно раньше, чем эта информация появлялась в СМИ или где нибудь еще.
Теперь, настала очередь фильтровать ложные срабатывания. Самый наглый и очевидный спам, например, реклама с хештегом #метро, не проходил, потому что не содержал ключевых слов (вроде «авария» или «поломка»). Но это не спасало, к примеру, от сообщений о поломках метро в других городах (не всегда в твите о поломке метро в Питере напишут слово «питер»). Поэтому пришлось ввести список «стоп-слов» при наличии которых сообщение не отправлялось. В него были включены некоторые названия станций других городов, ключевые слова, которые часто встречались в рекламе и т.д.
Проблему с тем, что на одно событие может приходится пара десятков твитов, и столько-же смс, решили в лоб: просто блокируем все сообщения про эту ветку метро на определенное время.
Впрочем, были и другие причины ложных срабатываний: сообщения о поломках другого транспорта (но при этом с тегом «метро»), сообщения, о старых поломках метро (пара аккаунтов пишет твиты о трагедии в метро летом 2014, так как будто это случилось только что).
Когда оно наконец-то стало более-менее стабильно работать, мы сделали веб интерфейс с возможностью регистрации по номеру телефона. Потихоньку начали подтягиваться еще люди, и естественно, в полном соответствии с законом подлости, случилось еще несколько ложных срабатываний. Чтобы больше такого не повторялось, сделали премодерацию: То есть сначала сообщения приходят нам, и если мы за пару минут не запретим их отправку, рассылаются всем остальным пользователям.
А еще у нас есть статистика. Ну, если уж ты собираешь данные, то грех не завести по ним статистику. В нашем случае это пока просто отображение количества поломок по веткам за определенный период времени. И краткое описание каждой поломки. В будущем наверное добавим еще что-нибудь, для начала надо побольше данных собрать.
В общем, кому это интересно: msk-metro.ru Вот мы. Можно считать, что проект еще на стадии от бета тестирования, поэтому если вам случайно придет левая смс — не расстраивайтесь. Мы это исправим, и в следующий раз такая-же смс точно не придет :)
А живет это все на Raspberry Pi на debian.