JavaRush /Blog Java /Random-PL /W kilka wieczorów tworzymy prostego bota pogodowego dla T...
Philip J.
Poziom 40
Днепр

W kilka wieczorów tworzymy prostego bota pogodowego dla Telegramu

Opublikowano w grupie Random-PL
Cześć wszystkim! Temat tworzenia botów do Telegramów jest nieco oklepany, a napisano wiele poradników (przykładowo ten ) . Dlatego lepiej przyjrzyjmy się bliżej pracy z interfejsem API innej firmy, ponieważ jest to kluczowa umiejętność dla każdego programisty internetowego. Od razu powiem, że aplikacja nie miała na celu dostarczania najbardziej funkcjonalnej i użytecznej prognozy pogody, nie ma co konkurować z serwisami pogodowymi, ważne było, aby nauczyć się pracy z połączeniami zdalnymi i analizowania danych w Javie. Najpierw dowiedzmy się, czego potrzebujemy. Nasza aplikacja składa się zasadniczo z trzech logicznych części:
  • zaakceptuj wiadomość od użytkownika
  • przetworzyć wiadomość i, jeśli jest to polecenie prawidłowe, przygotować dane do odpowiedzi. W naszym przypadku przygotuj prognozę pogody, jeśli użytkownik wpisał właściwe miasto
  • wyślij gotowe informacje użytkownikowi na czacie
Punkty pierwszy i trzeci są dość proste i dotyczą jedynie pracy z API Telegramu; zainteresowani mogą zapoznać się z linkiem pozostawionym powyżej. Skupimy się na drugim punkcie. Interfejsy API są używane, gdy niektórzy programiści chcą zapewnić dostęp do swoich danych innym programistom. Weźmy na przykład VKontakte. Każdy ma listę znajomych, jest ona przechowywana gdzieś w bazie danych na serwerach VK. Załóżmy, że jakiś programista postanowił stworzyć ze znajomymi grę w warcaby. Aby jego aplikacja działała poprawnie, program musi być w stanie uzyskać listę znajomych dowolnego gracza. W tym celu programista znajduje dokumentację API VK i sprawdza, jakie żądanie należy wykonać, aby uzyskać tę listę. To żądanie nazywa się żądaniem HTTP. Dwa najczęstsze żądania HTTP to GET i POST. W Internecie też jest o nich wystarczająco dużo, nie będę Was zatrzymywał. Dla naszych celów, czyli uzyskania danych dotyczących prognozy pogody, wystarczy proste żądanie GET. Jeśli zwrócimy się do zwykłego serwera WWW z żądaniem GET, często zwróci on kod HTML, który przeglądarka konwertuje na przyjazną dla użytkownika stronę, stosując style, skrypty itp. Jeśli złożymy takie żądanie do serwera API, odpowiedź zazwyczaj Zwracane są tylko surowe dane bez stylów i skryptów. W oknie przeglądarki wygląda to mniej więcej tak: W kilka wieczorów tworzymy prostego bota pogodowego dla Telegramu - 1Dane te nie są przeznaczone dla ludzi, ale dla innych programów, więc na takich stronach nie ma nic dodatkowego poza samą informacją. Surowe dane najczęściej przesyłane są przy wykorzystaniu jednego z dwóch standardów: JSON lub XML. Każde z nich ma swoje zalety i wady, jednak ważne jest, aby zrozumieć oba. JSON widziałeś już na powyższym zrzucie ekranu, a XML wygląda tak: W kilka wieczorów tworzymy prostego bota pogodowego dla Telegramu - 2Po krótkim wyszukiwaniu odnaleziono anglojęzyczny projekt Open Weather Map, który udostępnia dane za darmo, jeśli nie wykonasz więcej niż 50 żądań na minutę. To nam w zupełności wystarczy, rejestrujemy się, otrzymujemy unikalny token (kod), po którym serwer będzie wiedział, że nie jesteśmy oszustami, ale porządnymi przyszłymi programistami. Wchodzimy na stronę z dokumentacją API ( tyts ) i dowiadujemy się, że wysyłając żądanie formularza, można uzyskać 5-dniową prognozę dla dowolnego miasta.
https://api.openweathermap.org/data/2.5/forecast?q=(город)&APPID=(уникальный токен, полученный при регистрации)
Możesz zobaczyć jak wygląda odpowiedź na takie żądanie w przeglądarce.My już przekonaliśmy się, że tak naprawdę wystarczy wejść w odpowiedni link, a serwer udostępni niezbędne dane. Pozostaje tylko nauczyć się, jak to zrobić za pomocą Java. Proste żądanie GET w Javie wygląda następująco:
//создаём строку со ссылкой на нужную strona,
//я тут её склеиваю из заранее определённых констант, меняя только сам город
String urlString = API_CALL_TEMPLATE + city + API_KEY_TEMPLATE;
//создаём obiekt который будет содержать ссылку
URL urlObject = new URL(urlString);
//создаём соединение, используя obiekt
HttpURLConnection connection = (HttpURLConnection) urlObject.openConnection();
//выбираем тип wniosekа (GET)
connection.setRequestMethod("GET");
//тут мы указываем, данные о себе, что мы можем принять всё то,
//что примет и любой современный браузер
connection.setRequestProperty("User-Agent", "Mozilla/5.0");
//В начало ответа serwer всегда вставляет число, по которому можно судить, прошло ли всё хорошо.
//200 - значит OK
int responseCode = connection.getResponseCode();
//на несуществующий город Lub город с опечаткой, serwer выдаст kod ответа 404,
//бросаем на него исключение, чтобы обработать на уровне повыше и предложить
//пользователю ввести город заново
if (responseCode == 404) {
     throw new IllegalArgumentException();
}
// создаём поток, вычитываем все строки, и склеиваем в одну большую строку,
//которую будем потом обрабатывать в других методах
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
     response.append(inputLine);
}
in.close();
return response.toString();
Jeżeli żądanie było prawidłowe i serwer był dostępny, otrzymamy arkusz danych, w którym przydatne informacje wymieszane zostaną z informacjami, które nie są już potrzebne. Aby wygodnie wyodrębnić niezbędne dane z JSON i XML, napisano mnóstwo bibliotek dla Java, które zaspokoją każdy gust. Ponieważ wolałem JSON, do przetwarzania go wybrałem bardzo popularną bibliotekę o nazwie Jackson. Nawiasem mówiąc, jest to trochę badane w JavaRush na niektórych wysokich poziomach. Aby przetwarzać duże ilości danych JSON, ważne jest zrozumienie struktury dokumentu. Z pomocą przychodzą pomocne strony takie jak ta . Po lewej stronie mamy oryginalny JSON, po prawej ustrukturyzowany: W kilka wieczorów tworzymy prostego bota pogodowego dla Telegramu - 3 Można zauważyć, że odpowiedź składa się z 5 obiektów JSON najwyższego poziomu, z czego 2 są złożone i stanowią węzły dla kolejnych gałęzi. Interesujące nas dane przechowywane są w węźle listy . Lista wewnętrzna to tablica 38 linii JSON, z których każda opisuje pogodę w określonym czasie. Oznacza to, że jest to rodzaj struktury przypominającej drzewo, w której znajduje się korzeń, gałęzie, gałązki, a nawet liście :) A w węzłach następuje rozgałęzienie. Na szczęście Jackson może reprezentować dowolny prawidłowy JSON jako drzewo. Zatem znając nazwę potrzebnego nam atrybutu (np. temperatura powietrza) i na jakim poziomie drzewa się on znajduje, jego zdobycie nie będzie stanowić większego problemu. Najpierw wyodrębniłem wszystkie linie z tablicy „list” i dodałem je do osobnej listy. Z grubsza arkusz z danymi pociąłem na kawałki, z których każdy stanowi osobną prognozę. Małe części są łatwiejsze do zapamiętania i obsługi.
//JsonNode - это один из узлов в древовидной иерархии, от которого идут ветви
//получаем узел, который называется "list"
JsonNode arrNode = new ObjectMapper().readTree(data).get("list");
//если это действительно массив узлов
if (arrNode.isArray()) {
//выполняем для каждого узла, который содержится в массиве
      for (final JsonNode objNode : arrNode) {
//в атрибуте "dt_txt" каждого маленького узла хранилось время прогноза, я отобрал данные за 9 утра и 6 вечера
                String forecastTime = objNode.get("dt_txt").toString();
                if (forecastTime.contains("09:00") || forecastTime.contains("18:00")) {
                weatherList.add(objNode.toString());
            }
      }
}
Daje nam to listę ciągów, z których każdy reprezentuje raport JSON dotyczący pogody w określonym czasie. Pozostaje tylko wyodrębnić to, co chcesz i sformatować. Jeśli mamy taką linię:
"main":{"temp":261.45,"temp_min":259.086,"temp_max":261.45,"pressure":1023.48,"sea_level":1045.39,"grnd_level":1023.48,"humidity":79,"temp_kf":2.37}
to jest to węzeł zwany „głównym”. Aby wydobyć z niego jakiekolwiek dane, np. poziom morza, wystarczy poniższy kod:
ObjectMapper objectMapper = new ObjectMapper();
//line - это наша JSON-строка
mainNode = objectMapper.readTree(line).get("main");
String seaLevel = mainNode.get("sea_level");
Jackson pozwala na natychmiastowe przedstawienie danych w formacie numerycznym:
double seaLevel = mainNode.get("sea_level").asDouble();
Teraz możemy wyciągnąć z prognozy dowolne dane, pozostaje tylko skleić je według uznania i wysłać użytkownikowi w Telegramie. Pełny kod źródłowy znajduje się na moim githubie , ale możesz wypróbować bota w akcji , korzystając z łącza lub znajdując @denifoBot w wyszukiwarce Telegramu. Nazwę miasta należy zapisać w transliteracji łacińskiej, np. „Kijów” lub „Moskwa”. Dziękuję, jeśli dotarliście do końca, przyjmę rozsądną krytykę, ponieważ dopiero uczę się i rozwijam proste projekty na GitHubie, aby konkurować z głodnymi talentami z mojego miasta :) Cześć wszystkim! PS Myślę, że mogą się tu pojawić literówki, więc wszystko możesz wysłać w wiadomości prywatnej, lub w komentarzu, jeśli naprawdę jesteś zły :)
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION