본문 바로가기
텔레그램 봇

텔레그램 봇 (4) : (C#) 현재 날씨 받아오기

by Half-Dev 2020. 3. 23.

안녕하세요.

이번에는 현재 날씨를 받아오도록 하겠습니다.

 

날씨를 받아오기 위해서는 파싱을 해야 합니다.

찾아보니 파싱에 대한 기술이 몇 가지 있더군요.

 

저는 셀레니움으로 할까 하다가 WebBrowser 기능을 이용하도록 하겠습니다.

 


1. 간단한 테스트

저처럼 대충 모양에 맞게 WebBrowser를 추가합니다.

 

 

2. 코드 수정 및 추가

 

이벤트 수정

@날씨가 입력되면 Weather 메서드가 실행이 되도록 8번째 줄을 추가해 주도록 합니다.

 

1
2
3
4
5
6
7
8
9
private async void Bot_OnMessage(object sender, Telegram.Bot.Args.MessageEventArgs e)
{
    var message = e.Message;
    if (message == null || message.Type != MessageType.Text)
        return;
 
    if (message.Text == "@등록") await CheckUserAsync(message, message.Chat.Id);
    else if(message.Text == "@날씨") await Weather(message, message.Chat.Id);
}
cs

 

 

웹 브라우저 접근할 수 있도록 Weather 메서드 추가

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private async Task Weather(Telegram.Bot.Types.Message message, long chatId)
{
    bool nowTempFlag = true;
 
    string result, nowTemp = "", upTemp = "", downTemp = "", feelTemp = "";
    this.Invoke(new MethodInvoker(delegate ()
    {
        string strEncode = HttpUtility.UrlEncode("의정부 날씨");
        webBrowser1.Navigate("https://search.naver.com/search.naver?&query=" + strEncode);
        while (webBrowser1.ReadyState != WebBrowserReadyState.Complete) 
        { 
            //로딩 될동안 기다리기
            Application.DoEvents(); 
        }
 
        Doc = webBrowser1.Document;
    }));
    await Bot_SendMessage(chatId, "Success");
}
cs

 

 

WebBrowser 에는 의정부 날씨에 대한 웹페이지가 나오는 것을 볼 수 있습니다.

 

 

정상적으로 되었다면 텔레그램에서 Success라고 뜹니다.

 

 


3. 웹페이지의 값 받아오기

최종적으로 Weather 함수를 완성을 해보겠습니다.

 

전역 변수 추가

 

1
HtmlDocument Doc;
cs

 

 

Weather함수 수정

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
private async Task Weather(Telegram.Bot.Types.Message message, long chatId)
{
    bool nowTempFlag = true;
    bool nowStatus = true;
 
    string result = "", nowTemp = "", upTemp = "", downTemp = "", feelTemp = "";
    this.Invoke(new MethodInvoker(delegate ()
    {
        string strEncode = HttpUtility.UrlEncode("의정부 날씨");
        webBrowser1.Navigate("https://search.naver.com/search.naver?&query=" + strEncode);
        while (webBrowser1.ReadyState != WebBrowserReadyState.Complete) 
        { 
            //로딩 될동안 기다리기
            Application.DoEvents(); 
        }
 
        Doc = webBrowser1.Document;
    }));
    var links1 = Doc.GetElementsByTagName("p");
    var links2 = Doc.GetElementsByTagName("span");
 
    foreach(HtmlElement link in links1)
    {
        if(link.GetAttribute("className"== "cast_txt" && nowStatus)
        {
            result += link.InnerText + "\n";
            nowStatus = false;
        }
    }
 
    foreach (HtmlElement link in links2)
    {
        if (link.GetAttribute("className"== ""continue;
 
        if (link.GetAttribute("className"== "todaytemp" && nowTempFlag)
        {
            nowTemp = link.InnerText;
            nowTempFlag = false;
        }
 
        if (link.GetAttribute("className"== "sensible")
        {
            feelTemp = link.InnerText;
            string[] sp = feelTemp.Split(new string[] { "체감온도 " }, StringSplitOptions.None);
            feelTemp = sp[1];
        }
 
        if (link.GetAttribute("className"== "min") downTemp = link.InnerText;
        if (link.GetAttribute("className"== "max") upTemp = link.InnerText;
    }
    result +=
            "현재 온도 : " + nowTemp + "˚\n" + 
            "최고 온도 : " + upTemp + "\n" + 
            "최저 온도 : " + downTemp + "\n" + 
            "체감 온도 : " + feelTemp;
    await Bot_SendMessage(chatId, result);
}
cs

 


4. 지역 입력하기

 

@날씨 지역 입력하면 나오도록 이벤트를 수정하겠습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private async void Bot_OnMessage(object sender, Telegram.Bot.Args.MessageEventArgs e)
{
    string location;
    var message = e.Message;
    if (message == null || message.Type != MessageType.Text)
        return;
 
    if (message.Text == "@등록") await CheckUserAsync(message, message.Chat.Id);
    else if (message.Text.Contains("@날씨 "))
    {
        string[] sp = message.Text.Split(new string[] { "@날씨 " }, StringSplitOptions.None);
        location = sp[1];
        await Weather(location, message, message.Chat.Id);
    }
}
cs

 

 

지역을 받아야 하니 Weather메서드에서 string location을 추가해 줍니다.

 

1
private async Task Weather(string location, Telegram.Bot.Types.Message message, long chatId)
cs

 

 

UrlEncode 에서 location + " 날씨" 만 추가해 주시면 끝났습니다.

 

1
string strEncode = HttpUtility.UrlEncode(location + " 날씨");
cs

 

 


5. 예외 처리

장소가 이상하게 입력이 되면 아래처럼 출력이 됩니다.

 

 

이 부분을 처리해 주도록 하겠습니다.

Weather 메서드 아랫부분을 조금만 수정하면 됩니다.

 

1
2
3
4
5
6
7
8
9
10
11
result +=
            "현재 온도 : " + nowTemp + "˚\n" + 
            "최고 온도 : " + upTemp + "\n" + 
            "최저 온도 : " + downTemp + "\n" + 
            "체감 온도 : " + feelTemp;
 
    if(nowTemp == "" && upTemp == "" && downTemp == "" && feelTemp == "")
        await Bot_SendMessage(chatId, "오류가 났거나 찾을 수 없는 지역입니다.");
    else
        await Bot_SendMessage(chatId, result);
}
cs

 


6. 디자인 정리

WebBrowser를 오른쪽으로 옮긴 다음

 

 

칸을 줄여서 안 보이게 해 줍시다.

 


7. 최종


프로젝트 파일

텔레그램_현재날씨.zip
6.23MB

댓글