JavaRush /Java Blog /Random-KO /우리는 며칠 저녁에 Telegram을 위한 간단한 날씨 봇을 만듭니다.
Philip J.
레벨 40
Днепр

우리는 며칠 저녁에 Telegram을 위한 간단한 날씨 봇을 만듭니다.

Random-KO 그룹에 게시되었습니다
안녕하세요 여러분! 텔레그램용 봇을 만드는 주제는 다소 험난하고 많은 가이드가 작성되었습니다(예: 이 가이드 ). 따라서 일부 타사 API 작업에 대해 자세히 살펴보는 것이 좋습니다. 이는 모든 웹 개발자에게 중요한 기술이기 때문입니다. 이 애플리케이션은 가장 기능적이고 유용한 예측을 제공하기 위해 시작된 것이 아니며, 기상 사이트와 경쟁할 이유가 없으며, Java를 사용하여 원격 연결 및 데이터 구문 분석 작업 방법을 배우는 것이 중요했습니다. 그럼 먼저 필요한 것이 무엇인지 알아보겠습니다. 우리 애플리케이션은 기본적으로 세 가지 논리적 부분으로 구성됩니다.
  • 사용자의 메시지 수락
  • 메시지를 처리하고 유효한 명령인 경우 응답을 위한 데이터를 준비합니다. 우리의 경우 사용자가 올바른 도시를 입력하면 일기 예보를 준비합니다.
  • 채팅에서 사용자에게 준비된 정보를 보냅니다.
첫 번째와 세 번째 사항은 매우 간단하며 Telegram API 작업에만 관련됩니다. 관심 있는 사람은 위에 왼쪽 링크를 연구할 수 있습니다. 우리는 두 번째 점에 초점을 맞출 것입니다. API는 일부 개발자가 자신의 데이터에 대한 액세스를 다른 개발자에게 제공하려고 할 때 사용됩니다. 예를 들어 VKontakte를 살펴보겠습니다. 모든 사람은 친구 목록을 가지고 있으며 VK 서버의 데이터베이스 어딘가에 저장되어 있습니다. 어떤 프로그래머가 친구들과 함께 체커 게임을 만들기로 결정했다고 가정해 보겠습니다. 그의 응용 프로그램이 제대로 작동하려면 프로그램이 모든 플레이어의 친구 목록을 얻을 수 있어야 합니다. 이를 위해 프로그래머는 VK API에 대한 문서를 찾고 이 목록을 얻기 위해 어떤 요청이 필요한지 살펴봅니다. 이 요청을 HTTP 요청이라고 합니다. 그리고 가장 일반적인 두 가지 HTTP 요청은 GET과 POST입니다. 인터넷에도 그에 대한 내용이 충분히 있으므로 말리지 않겠습니다. 우리의 목적, 즉 일기 예보 데이터를 얻으려면 간단한 GET 요청으로 충분합니다. 일반 웹 서버에 GET 요청을 하면 브라우저가 스타일, 스크립트 등을 적용하여 사용자 친화적인 페이지로 변환하는 HTML 코드를 반환하는 경우가 많습니다. API 서버에 이러한 요청을 하면 응답은 다음과 같습니다. 일반적으로 스타일과 스크립트 없이 원시 데이터만 반환됩니다. 브라우저 창에는 다음과 같이 표시됩니다. 우리는 며칠 저녁에 Telegram을 위한 간단한 날씨 봇을 만듭니다 - 1이 데이터는 사람을 위한 것이 아니라 다른 프로그램을 위한 것이므로 해당 페이지에는 정보 자체 외에는 추가 항목이 없습니다. 원시 데이터는 JSON 또는 XML이라는 두 가지 표준 중 하나를 사용하여 전송되는 경우가 가장 많습니다. 각각에는 장단점이 있지만 두 가지를 모두 이해하는 것이 중요합니다. 위 스크린샷에서 이미 JSON을 보셨고, XML은 다음과 같습니다. 우리는 며칠 저녁에 Telegram을 위한 간단한 날씨 봇을 만듭니다 - 2짧은 검색 끝에 영어 Open Weather Map 프로젝트가 발견되었습니다. 이 프로젝트는 분당 50개 이상 요청하지 않으면 무료로 데이터를 제공합니다. 이것은 우리에게 충분합니다. 우리는 등록하고 서버가 우리가 사기꾼이 아니라 괜찮은 미래 개발자임을 알 수 있는 고유한 토큰(코드)을 받습니다. API 문서( tyts ) 가 있는 페이지로 이동하여 양식 요청을 보내면 모든 도시에 대한 5일 일기예보를 얻을 수 있음을 알 수 있습니다.
https://api.openweathermap.org/data/2.5/forecast?q=(город)&APPID=(уникальный токен, полученный при регистрации)
이러한 요청에 대한 응답이 브라우저에서 어떻게 보이는지 확인할 수 있으며 실제로 올바른 링크를 따라가기만 하면 서버가 필요한 데이터를 제공한다는 것을 이미 알고 있습니다. 남은 것은 Java를 사용하여 이를 수행하는 방법을 배우는 것입니다. Java의 간단한 GET 요청은 다음과 같습니다.
//создаём строку со ссылкой на нужную page,
//я тут её склеиваю из заранее определённых констант, меняя только сам город
String urlString = API_CALL_TEMPLATE + city + API_KEY_TEMPLATE;
//создаём an object который будет содержать ссылку
URL urlObject = new URL(urlString);
//создаём соединение, используя an object
HttpURLConnection connection = (HttpURLConnection) urlObject.openConnection();
//выбираем тип requestа (GET)
connection.setRequestMethod("GET");
//тут мы указываем, данные о себе, что мы можем принять всё то,
//что примет и любой современный браузер
connection.setRequestProperty("User-Agent", "Mozilla/5.0");
//В начало ответа server всегда вставляет число, по которому можно судить, прошло ли всё хорошо.
//200 - значит OK
int responseCode = connection.getResponseCode();
//на несуществующий город or город с опечаткой, server выдаст code ответа 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();
요청이 정확하고 서버를 사용할 수 있는 경우 유용한 정보와 현재 필요하지 않은 정보가 혼합된 데이터 시트를 받게 됩니다. JSON 및 XML에서 필요한 데이터를 편리하게 추출하기 위해 모든 취향에 맞게 Java용으로 수많은 라이브러리가 작성되었습니다. 저는 JSON을 선호했기 때문에 이를 처리하기 위해 Jackson이라는 매우 인기 있는 라이브러리를 선택했습니다. 그건 그렇고, JavaRush에서는 일부 높은 수준에서 약간 연구되었습니다. 대량의 JSON 데이터를 처리하려면 문서의 구조를 이해하는 것이 중요합니다. 이와 같은 유용한 사이트가 도움 이 됩니다 . 왼쪽에는 원본 JSON이 있고 오른쪽에는 구조화된 JSON이 있습니다. 우리는 며칠 저녁에 Telegram을 위한 간단한 날씨 봇을 만듭니다 - 3 응답은 5개의 최상위 JSON 개체로 구성되어 있으며 그 중 2개는 복잡하고 다음 분기에 대한 노드입니다. 우리가 관심 있는 데이터는 목록 노드에 저장됩니다 . 내부 목록은 각각 특정 시간의 날씨를 설명하는 38개의 JSON 라인 배열입니다. 즉, 뿌리, 가지, 잔가지, 심지어 잎까지 있는 일종의 나무와 같은 구조입니다. :) 그리고 노드에서 분기가 발생합니다. 운 좋게도 Jackson은 유효한 JSON을 트리로 표현할 수 있습니다. 따라서 필요한 속성의 이름(예: 기온)과 해당 속성이 나무의 어느 수준에 있는지 알면 이를 얻는 데 큰 문제가 되지 않습니다. 먼저 "목록" 배열에서 모든 행을 추출하여 별도의 목록에 추가했습니다. 대략적으로 말하면 데이터가 포함된 시트를 조각으로 잘라냈는데, 각 조각은 별도의 예측입니다. 작은 부품은 기억하고 조작하기가 더 쉽습니다.
//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());
            }
      }
}
그래서 우리는 각 줄이 특정 시간의 JSON 일기 예보를 나타내는 문자열 목록을 얻었습니다. 남은 것은 원하는 것을 추출하고 형식을 지정하는 것입니다. 다음과 같은 줄이 있다면:
"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}
그러면 이것은 "main"이라는 노드입니다. 예를 들어 해수면과 같은 데이터를 얻으려면 다음 코드로 충분합니다.
ObjectMapper objectMapper = new ObjectMapper();
//line - это наша JSON-строка
mainNode = objectMapper.readTree(line).get("main");
String seaLevel = mainNode.get("sea_level");
Jackson을 사용하면 데이터를 숫자 형식으로 즉시 표현할 수 있습니다.
double seaLevel = mainNode.get("sea_level").asDouble();
이제 우리는 예측에서 모든 데이터를 추출할 수 있으며, 남은 것은 원하는 대로 이를 연결하여 Telegram을 통해 사용자에게 보내는 것뿐입니다. 전체 소스 코드는 내 github 에 있지만 링크를 사용 하거나 Telegram 검색에서 @denifoBot을 찾아 실제 봇을 사용해 볼 수 있습니다 . 도시 이름은 "Kyiv" 또는 "Moscow"와 같이 라틴어 음역으로 작성되어야 합니다. 고맙습니다. 끝까지 해내셨다면 합당한 비판을 받아들입니다. 저는 단지 우리 도시의 배고픈 인재들과 경쟁하기 위해 GitHub에서 간단한 프로젝트를 배우고 개발하고 있기 때문입니다 :) 모두 안녕! PS 여기에 오타가 있을 수 있다고 생각하므로 모든 내용을 개인 메시지로 보내거나 정말로 화가 나면 댓글로 보내셔도 됩니다 :)
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION