สวัสดีทุกคน! หัวข้อของการสร้างบอทสำหรับ Telegrams ค่อนข้างถูกแฮ็กและมีการเขียนคำแนะนำมากมาย (ตัวอย่างเช่น อันนี้ ) ดังนั้นเราจึงควรพิจารณาการทำงานกับ API ของบริษัทอื่นให้ละเอียดยิ่งขึ้น เนื่องจากนี่เป็นทักษะที่สำคัญสำหรับนักพัฒนาเว็บ ฉันจะบอกทันทีว่าแอปพลิเคชันไม่ได้ออกแบบมาเพื่อให้การคาดการณ์ที่มีประโยชน์และมีประโยชน์มากที่สุด ไม่มีประโยชน์ที่จะแข่งขันกับไซต์พยากรณ์อากาศ สิ่งสำคัญคือต้องเรียนรู้วิธีทำงานกับการเชื่อมต่อระยะไกลและการแยกวิเคราะห์ข้อมูลโดยใช้ Java ดังนั้นเรามาดูกันว่าเราต้องการอะไรก่อน แอปพลิเคชันของเราประกอบด้วยสามส่วนหลัก:
ข้อมูลนี้ไม่ได้มีไว้สำหรับบุคคล แต่สำหรับโปรแกรมอื่น ๆ ดังนั้นจึงไม่มีอะไรพิเศษในหน้าดังกล่าวยกเว้นข้อมูลนั้นเอง ข้อมูลดิบมักถูกส่งโดยใช้หนึ่งในสองมาตรฐาน: JSON หรือ XML แต่ละอย่างมีข้อดีข้อเสียต่างกันไป อย่างไรก็ตาม สิ่งสำคัญคือต้องเข้าใจทั้งสองอย่าง คุณได้เห็น JSON ในภาพหน้าจอด้านบนแล้ว และ XML มีลักษณะดังนี้:
หลังจากค้นหาสั้นๆ พบโครงการ Open Weather Map ภาษาอังกฤษ ซึ่งให้ข้อมูลฟรีหากคุณไม่ได้ส่งคำขอมากกว่า 50 รายการต่อนาที นี่เพียงพอสำหรับเรา เราลงทะเบียน เราได้รับโทเค็น (รหัส) ที่ไม่ซ้ำใคร ซึ่งเซิร์ฟเวอร์จะรู้ว่าเราไม่ใช่ผู้แอบอ้าง แต่เป็นนักพัฒนาที่ดีในอนาคต ไปที่หน้าพร้อมเอกสาร API ( tyts ) และพบว่าสามารถรับการคาดการณ์ 5 วันสำหรับเมืองใด ๆ ได้โดยส่งคำขอแบบฟอร์ม
จะเห็นได้ว่าการตอบสนองประกอบด้วยออบเจ็กต์ JSON ระดับบนสุด 5 รายการ โดย 2 รายการมีความซับซ้อนและเป็นโหนดสำหรับสาขาต่อไปนี้ ข้อมูลที่เราสนใจจะถูกเก็บไว้ในโหนดรายการ รายการภายในคืออาร์เรย์ของบรรทัด JSON 38 บรรทัด ซึ่งแต่ละบรรทัดอธิบายสภาพอากาศในช่วงเวลาหนึ่งๆ นั่นคือมันเป็นโครงสร้างคล้ายต้นไม้ซึ่งมีรากกิ่งก้านและแม้แต่ใบไม้ :) และที่โหนดการแตกแขนงก็เกิดขึ้น โชคดีที่ Jackson สามารถแสดง JSON ที่ถูกต้องเป็นต้นไม้ได้ ดังนั้นการรู้ชื่อของคุณลักษณะที่เราต้องการ (เช่น อุณหภูมิอากาศ) และต้นไม้นั้นอยู่ที่ระดับใด การจะได้มาจึงไม่ใช่ปัญหามากนัก ขั้นแรก ฉันแยกบรรทัดทั้งหมดออกจากอาร์เรย์ "รายการ" และเพิ่มลงในรายการแยกต่างหาก โดยคร่าวๆ ฉันตัดชีตที่มีข้อมูลออกเป็นชิ้นๆ ซึ่งแต่ละส่วนเป็นการคาดการณ์ที่แยกจากกัน ชิ้นส่วนขนาดเล็กง่ายต่อการจดจำและใช้งาน
- ยอมรับข้อความจากผู้ใช้
- ประมวลผลข้อความ และหากเป็นคำสั่งที่ถูกต้อง ให้เตรียมข้อมูลสำหรับการตอบกลับ ในกรณีของเรา ให้เตรียมพยากรณ์อากาศหากผู้ใช้ป้อนเมืองที่ถูกต้อง
- ส่งข้อมูลพร้อมให้กับผู้ใช้ในการแชท


https://api.openweathermap.org/data/2.5/forecast?q=(город)&APPID=(уникальный токен, полученный при регистрации)
คุณสามารถดูว่าการตอบสนองต่อคำขอดังกล่าวมีลักษณะอย่างไรในเบราว์เซอร์เรา พบแล้วว่า ที่จริงแล้ว คุณเพียงแค่ต้องคลิกลิงก์ที่ถูกต้องแล้วเซิร์ฟเวอร์จะให้ข้อมูลที่จำเป็น สิ่งที่เหลืออยู่คือการเรียนรู้วิธีการทำสิ่งนี้โดยใช้ Java คำขอ GET แบบธรรมดาใน Java มีลักษณะดังนี้:
//создаём строку со ссылкой на нужную 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 ดั้งเดิม ทางด้านขวา - แบบที่มีโครงสร้าง: 
//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 ของฉัน แต่คุณสามารถลองใช้บอทใช้งานได้โดยใช้ลิงก์หรือโดยการค้นหา @denifoBot ในการค้นหา Telegram ชื่อเมืองต้องเขียนเป็นภาษาละตินทับศัพท์ เช่น "เคียฟ" หรือ "มอสโก" ขอบคุณ ถ้าคุณทำจนจบ ฉันยอมรับคำวิจารณ์ที่สมเหตุสมผล เนื่องจากฉันแค่เรียนรู้และพัฒนาโครงการง่ายๆ บน GitHub เพื่อแข่งขันกับผู้มีความสามารถที่หิวโหยจากเมืองของฉัน :) ลาก่อนทุกคน! ป.ล. ฉันเชื่อว่าอาจมีการพิมพ์ผิดดังนั้นคุณสามารถส่งทุกอย่างในข้อความส่วนตัวหรือแสดงความคิดเห็นหากคุณโกรธจริงๆ :)
GO TO FULL VERSION