JavaRush /Blog Java /Random-VI /Chúng tôi tạo một bot thời tiết đơn giản cho Telegram tro...
Philip J.
Mức độ
Днепр

Chúng tôi tạo một bot thời tiết đơn giản cho Telegram trong vài buổi tối

Xuất bản trong nhóm
Chào mọi người! Chủ đề tạo bot cho Telegram có phần hơi nhàm chán và rất nhiều hướng dẫn đã được viết (ví dụ: hướng dẫn này ) . Do đó, tốt hơn hết chúng ta nên xem xét kỹ hơn khi làm việc với một số API của bên thứ ba, vì đây là một kỹ năng quan trọng đối với bất kỳ nhà phát triển web nào. Tôi sẽ nói ngay rằng ứng dụng này không nhằm mục đích cung cấp dự báo hữu ích và hữu ích nhất; không có ích gì khi cạnh tranh với các trang web thời tiết; điều quan trọng là phải học cách làm việc với các kết nối từ xa và phân tích dữ liệu bằng Java. Vì vậy, hãy tìm hiểu những gì chúng ta cần trước tiên. Ứng dụng của chúng tôi về cơ bản bao gồm ba phần hợp lý:
  • chấp nhận tin nhắn từ người dùng
  • xử lý thông báo và nếu đó là lệnh hợp lệ, hãy chuẩn bị dữ liệu cho phản hồi. Trong trường hợp của chúng tôi, hãy chuẩn bị dự báo thời tiết nếu người dùng vào đúng thành phố
  • gửi thông tin sẵn sàng cho người dùng trong trò chuyện
Điểm thứ nhất và thứ ba khá đơn giản và chỉ liên quan đến việc làm việc với API Telegram; những ai quan tâm có thể nghiên cứu liên kết bên trái ở trên. Chúng ta sẽ tập trung vào điểm thứ hai. API được sử dụng khi một số nhà phát triển muốn cung cấp quyền truy cập vào dữ liệu của họ cho các nhà phát triển khác. Hãy lấy VKontakte làm ví dụ. Mọi người đều có một danh sách bạn bè, nó được lưu trữ ở đâu đó trong cơ sở dữ liệu trên máy chủ VK. Giả sử một lập trình viên nào đó quyết định tạo một trò chơi cờ đam với bạn bè. Để ứng dụng của anh ấy hoạt động chính xác, chương trình phải có khả năng lấy được danh sách bạn bè của bất kỳ người chơi nào. Để thực hiện việc này, lập trình viên sẽ tìm tài liệu về API VK và xem xét yêu cầu nào cần được thực hiện để có được danh sách này. Yêu cầu này được gọi là yêu cầu HTTP. Và hai yêu cầu HTTP phổ biến nhất là GET và POST. Trên Internet cũng có đủ về họ, tôi sẽ không ngăn cản bạn. Đối với mục đích của chúng tôi, cụ thể là lấy dữ liệu dự báo thời tiết, một yêu cầu GET đơn giản là đủ. Nếu chúng tôi thực hiện yêu cầu GET tới máy chủ web thông thường, nó thường sẽ trả về mã html mà trình duyệt chuyển đổi thành trang thân thiện với người dùng, áp dụng kiểu, tập lệnh, v.v. Nếu chúng tôi thực hiện yêu cầu như vậy đến máy chủ API, phản hồi sẽ thường là Chỉ dữ liệu thô được trả về mà không có kiểu và tập lệnh. Trong cửa sổ trình duyệt, nó trông giống như thế này: Chúng tôi tạo một bot thời tiết đơn giản cho Telegram trong vài buổi tối - 1Dữ liệu này không dành cho mọi người mà dành cho các chương trình khác, vì vậy không có gì bổ sung trong các trang đó ngoại trừ chính thông tin đó. Dữ liệu thô thường được gửi bằng một trong hai tiêu chuẩn: JSON hoặc XML. Mỗi cái đều có ưu và nhược điểm, tuy nhiên, điều quan trọng là phải hiểu cả hai. Bạn đã thấy JSON trong ảnh chụp màn hình ở trên và XML trông như thế này: Chúng tôi tạo một bot thời tiết đơn giản cho Telegram trong vài buổi tối - 2Sau một tìm kiếm ngắn, dự án Bản đồ thời tiết mở bằng tiếng Anh đã được tìm thấy, dự án này cung cấp dữ liệu miễn phí nếu bạn không thực hiện hơn 50 yêu cầu mỗi phút. Điều này là khá đủ đối với chúng tôi, chúng tôi đăng ký, chúng tôi nhận được một mã thông báo (mã) duy nhất mà máy chủ sẽ biết rằng chúng tôi không phải là kẻ mạo danh mà là những nhà phát triển tử tế trong tương lai. Chúng tôi truy cập trang có tài liệu API ( tyts ) và phát hiện ra rằng có thể nhận được dự báo trong 5 ngày cho bất kỳ thành phố nào bằng cách gửi yêu cầu theo biểu mẫu.
https://api.openweathermap.org/data/2.5/forecast?q=(город)&APPID=(уникальный токен, полученный при регистрации)
Bạn có thể xem phản hồi đối với yêu cầu như vậy trông như thế nào trong trình duyệt. Trên thực tế, chúng tôi đã phát hiện ra rằng bạn chỉ cần nhấp vào liên kết chính xác và máy chủ sẽ cung cấp dữ liệu cần thiết. Tất cả những gì còn lại là học cách thực hiện việc này bằng Java. Một yêu cầu GET đơn giản trong Java trông như thế này:
//создаём строку со ссылкой на нужную 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();
Nếu yêu cầu đúng và máy chủ khả dụng, chúng tôi sẽ nhận được một bảng dữ liệu trong đó thông tin hữu ích được trộn lẫn với thông tin hiện không cần thiết. Để trích xuất dữ liệu cần thiết từ JSON và XML một cách thuận tiện, rất nhiều thư viện đã được viết cho Java để phù hợp với mọi sở thích. Vì tôi thích JSON hơn nên tôi đã chọn một thư viện rất phổ biến tên là Jackson để xử lý nó. Nhân tiện, nó được nghiên cứu một chút về JavaRush ở một số cấp độ cao. Để xử lý lượng lớn dữ liệu JSON, điều quan trọng là phải hiểu cấu trúc của tài liệu. Các trang web hữu ích như thế này sẽ ra tay giải cứu . Bên trái chúng ta có JSON gốc, bên phải - JSON có cấu trúc: Chúng tôi tạo một bot thời tiết đơn giản cho Telegram trong vài buổi tối - 3 Có thể thấy phản hồi bao gồm 5 đối tượng JSON cấp cao nhất, trong đó có 2 đối tượng phức tạp và là các nút cho các nhánh sau. Dữ liệu chúng ta quan tâm được lưu trữ trong nút danh sách . Danh sách bên trong là một mảng gồm 38 dòng JSON, mỗi dòng mô tả thời tiết tại một thời điểm nhất định. Nghĩa là, nó là một loại cấu trúc giống như cây, trong đó có rễ, cành, cành và thậm chí cả lá :) Và tại các nút, quá trình phân nhánh diễn ra. May mắn thay, Jackson có thể biểu diễn bất kỳ JSON hợp lệ nào dưới dạng cây. Do đó, biết tên của thuộc tính chúng ta cần (ví dụ: nhiệt độ không khí) và nó nằm ở cấp độ nào của cây, việc lấy nó sẽ không gặp nhiều vấn đề. Đầu tiên, tôi trích xuất tất cả các dòng từ mảng "danh sách" và thêm chúng vào một danh sách riêng. Nói một cách đại khái, tôi cắt tờ dữ liệu thành nhiều phần, mỗi phần là một dự báo riêng biệt. Các bộ phận nhỏ dễ ghi nhớ và thao tác hơn.
//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());
            }
      }
}
Điều này cung cấp cho chúng ta một danh sách các chuỗi, trong đó mỗi chuỗi biểu thị một báo cáo JSON về thời tiết tại một thời điểm nhất định. Tất cả những gì còn lại là trích xuất những gì bạn muốn và định dạng nó. Nếu chúng ta có một dòng như thế này:
"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}
thì đây là nút được gọi là "chính". Để lấy bất kỳ dữ liệu nào từ nó, ví dụ như mực nước biển, đoạn mã sau là đủ:
ObjectMapper objectMapper = new ObjectMapper();
//line - это наша JSON-строка
mainNode = objectMapper.readTree(line).get("main");
String seaLevel = mainNode.get("sea_level");
Jackson cho phép bạn biểu diễn ngay dữ liệu ở định dạng số:
double seaLevel = mainNode.get("sea_level").asDouble();
Bây giờ chúng tôi có thể trích xuất bất kỳ dữ liệu nào từ dự báo và tất cả những gì còn lại là dán nó lại với nhau như mong muốn và gửi cho người dùng trong Telegram. Mã nguồn đầy đủ có trên github của tôi , nhưng bạn có thể thử hoạt động của bot bằng liên kết hoặc bằng cách tìm @denifoBot trong tìm kiếm Telegram. Tên của thành phố phải được viết bằng phiên âm Latinh, ví dụ "Kyiv" hoặc "Moscow". Cảm ơn bạn, nếu bạn đã làm đến cùng, tôi chấp nhận những lời chỉ trích hợp lý, vì tôi chỉ đang học và phát triển các dự án đơn giản trên GitHub để cạnh tranh với những tài năng đang khao khát từ thành phố của mình :) Tạm biệt mọi người! Tái bút Tôi tin rằng có thể có lỗi chính tả ở đây, vì vậy bạn có thể gửi mọi thứ trong tin nhắn riêng tư hoặc trong bình luận nếu bạn thực sự tức giận :)
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION