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
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: 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 :)
GO TO FULL VERSION