JavaRush /Blog Java /Random-ES /Creamos un sencillo robot meteorológico para Telegram en ...
Philip J.
Nivel 40
Днепр

Creamos un sencillo robot meteorológico para Telegram en unas tardes

Publicado en el grupo Random-ES
¡Hola a todos! El tema de la creación de bots para Telegram está algo trillado y se han escrito muchas guías (por ejemplo, esta ) . Por lo tanto, será mejor que analicemos más de cerca cómo trabajar con alguna API de terceros, ya que esta es una habilidad crítica para cualquier desarrollador web. Diré de inmediato que la aplicación no se propuso proporcionar el pronóstico más funcional y útil; no tiene sentido competir con sitios meteorológicos; era importante aprender a trabajar con conexiones remotas y análisis de datos usando Java. Entonces, averigüemos qué necesitamos primero. Nuestra aplicación consta esencialmente de tres partes lógicas:
  • aceptar mensaje del usuario
  • procesar el mensaje y, si es un comando válido, preparar datos para la respuesta. En nuestro caso, preparar un pronóstico del tiempo si el usuario ingresó la ciudad correcta
  • enviar información lista al usuario en el chat
El primer y tercer punto son bastante simples y sólo se refieren a trabajar con la API de Telegram; los interesados ​​pueden estudiar el enlace que dejamos arriba. Nos centraremos en el segundo punto. Las API se utilizan cuando algunos desarrolladores desean proporcionar acceso a sus datos a otros desarrolladores. Tomemos como ejemplo VKontakte. Todos tienen una lista de amigos, que se almacena en algún lugar de una base de datos en los servidores VK. Digamos que algún programador decidió crear un juego de damas con amigos. Para que su aplicación funcione correctamente, el programa debe poder obtener la lista de amigos de cualquier jugador. Para hacer esto, el programador busca la documentación de la API de VK y observa qué solicitud se debe realizar para obtener esta lista. Esta solicitud se llama solicitud HTTP. Y las dos solicitudes HTTP más comunes son GET y POST. También hay bastante sobre ellos en Internet, no te detendré. Para nuestros propósitos, es decir, obtener datos del pronóstico del tiempo, una simple solicitud GET será suficiente. Si realizamos una solicitud GET a un servidor web normal, a menudo devolverá código html, que el navegador convierte en una página fácil de usar, aplicando estilos, scripts, etc. Si realizamos dicha solicitud al servidor API, la respuesta Por lo general, solo se devuelven datos sin procesar, sin estilos ni secuencias de comandos. En la ventana del navegador se ve así: Creamos un robot meteorológico simple para Telegram en unas pocas noches - 1Estos datos no están destinados a personas, sino a otros programas, por lo que no hay nada extra en dichas páginas excepto la información en sí. Los datos sin procesar suelen enviarse utilizando uno de dos estándares: JSON o XML. Cada uno tiene sus pros y sus contras, sin embargo, es importante entender ambos. Ya ha visto JSON en la captura de pantalla anterior, y XML se ve así: Creamos un robot meteorológico sencillo para Telegram en unas pocas tardes - 2Después de una breve búsqueda, se encontró el proyecto Open Weather Map en inglés, que proporciona datos de forma gratuita si no realiza más de 50 solicitudes por minuto. Esto es suficiente para nosotros, nos registramos, recibimos un token (código) único mediante el cual el servidor sabrá que no somos impostores, sino futuros desarrolladores decentes. Vamos a la página con la documentación API ( tyts ) y descubrimos que se puede obtener un pronóstico de 5 días para cualquier ciudad enviando una solicitud del formulario.
https://api.openweathermap.org/data/2.5/forecast?q=(город)&APPID=(уникальный токен, полученный при регистрации)
Puedes ver cómo se ve la respuesta a dicha solicitud en el navegador. Ya hemos descubierto que, de hecho, basta con seguir el enlace correcto y el servidor le proporcionará los datos necesarios. Todo lo que queda es aprender a hacer esto usando Java. Una solicitud GET simple en Java se ve así:
//создаём строку со ссылкой на нужную página,
//я тут её склеиваю из заранее определённых констант, меняя только сам город
String urlString = API_CALL_TEMPLATE + city + API_KEY_TEMPLATE;
//создаём un objeto который будет содержать ссылку
URL urlObject = new URL(urlString);
//создаём соединение, используя un objeto
HttpURLConnection connection = (HttpURLConnection) urlObject.openConnection();
//выбираем тип pedidoа (GET)
connection.setRequestMethod("GET");
//тут мы указываем, данные о себе, что мы можем принять всё то,
//что примет и любой современный браузер
connection.setRequestProperty("User-Agent", "Mozilla/5.0");
//В начало ответа servidor всегда вставляет число, по которому можно судить, прошло ли всё хорошо.
//200 - значит OK
int responseCode = connection.getResponseCode();
//на несуществующий город o город с опечаткой, servidor выдаст código ответа 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();
Si la solicitud fue correcta y el servidor estaba disponible, recibiremos una hoja de datos en la que se mezcla información útil con información que no es necesaria ahora. Para extraer cómodamente los datos necesarios de JSON y XML, se han escrito toneladas de bibliotecas para Java para todos los gustos. Como prefería JSON, elegí una biblioteca muy popular llamada Jackson para procesarlo. Por cierto, se estudia un poco en JavaRush en algunos niveles altos. Para procesar grandes cantidades de datos JSON, es importante comprender la estructura del documento. Sitios útiles como este vienen al rescate . A la izquierda tenemos el JSON original, a la derecha el estructurado: Creamos un robot meteorológico sencillo para Telegram en unas pocas tardes - 3 Se puede ver que la respuesta consta de 5 objetos JSON de nivel superior, 2 de los cuales son complejos y son nodos para las siguientes ramas. Los datos que nos interesan se almacenan en el nodo de lista . Dentro de la lista hay una matriz de 38 líneas JSON, cada una de las cuales describe el clima en un momento determinado. Es decir, es una especie de estructura arbórea, donde hay raíz, ramas, ramitas e incluso hojas :) Y en los nodos se produce la ramificación. Afortunadamente, Jackson puede representar cualquier JSON válido como un árbol. Así, sabiendo el nombre del atributo que necesitamos (por ejemplo, temperatura del aire), y en qué nivel del árbol se encuentra, conseguirlo no será un gran problema. Primero, extraje todas las líneas de la matriz "lista" y las agregué a una lista separada. En términos generales, corté la hoja con los datos en pedazos, cada uno de los cuales es un pronóstico separado. Las piezas pequeñas son más fáciles de recordar y operar.
//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());
            }
      }
}
Entonces obtuvimos una lista de cadenas, en la que cada línea representa un informe meteorológico JSON en un momento determinado. Ya sólo queda extraer lo que quieras y formatearlo. Si tenemos una línea como esta:
"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}
entonces este es un nodo llamado "principal". Para obtener datos de él, por ejemplo el nivel del mar, es suficiente el siguiente código:
ObjectMapper objectMapper = new ObjectMapper();
//line - это наша JSON-строка
mainNode = objectMapper.readTree(line).get("main");
String seaLevel = mainNode.get("sea_level");
Jackson le permite representar datos inmediatamente en formato numérico:
double seaLevel = mainNode.get("sea_level").asDouble();
Ahora podemos extraer cualquier dato del pronóstico, y solo queda pegarlo como queramos y enviárselo al usuario en Telegram. El código fuente completo está en mi github , pero puedes probar el bot en acción usando el enlace o buscando @denifoBot en la búsqueda de Telegram. El nombre de la ciudad debe estar escrito en transliteración latina, por ejemplo "Kiev" o "Moscú". Gracias, si llegaste hasta el final, acepto críticas razonables, ya que apenas estoy aprendiendo y desarrollando proyectos simples en GitHub para poder competir con talentos hambrientos de mi ciudad :) ¡Adiós a todos! PD: Creo que puede haber errores tipográficos aquí, así que puedes enviar todo en un mensaje privado, o en un comentario si estás realmente enojado :)
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION