쇼핑몰 프로젝트 동영상

|

공공데이터API 활용-텔레그램 챗봇으로 잠시후도착 버스 정보 받기

|

전체코드보기


활용 API : 공공데이터포털

버스도착정보조회서비스

url 요청시 필수 파라미터 3가지

url요청시 필수 파라미터 3가지가 필요하다.

  1. serviceKey

    serviceKey번호는 공공데이터포털에 회원가입 후 고유 키 번호를 부여 받을 수 있다

  2. stationId

  3. routeId

내가 원하는 정류장 ID(stationid)와

노선번호(routeid)인 버스정보를 알아내기 위한 방법

[1] 경기버스정보에서 내가 찾고자하는 정류소를 입력 후

ex) http://www.gbis.go.kr/gbis2014/schBus.action?cmd=mainSearchText&searchText=만현10단지아이파크.현대성우5차

[2] 지도에서 해당 정류소 아이콘을 누르면

views
빨간색 원을 누른다.

[3] 개발자모드 network tab의 schBusAPl.action에서 쉽게 찾을 수 있다

views
views

해당 정류소에 오는 버스 정보인 busArrivalInfo 리스트가 보인다

views

눌러보면 routeIdstationId를 확인 할 수 있다

포스트맨으로 실험하기

views
통신 성공

포스트맨으로 데이터를 보내면 원하는 값을 얻을 수 있다!

내가 가져오고 싶은 정보는, 버스의 도착 정보은 predictTime1이다!

1 - Test Code

텔레그램 챗봇 사용하는 법

챗봇에 적용하기 전 local에서 테스트 코드를 먼저 짜보았다..

크롤링이 처음이여서,

xml파싱을 하는 효율적인 코드를 잘 몰라 일단 html 파싱 방법과 동일하게 코드를 작성했다

def find_bus():
    # 내가 원하는 버스 정류장에 오는 버스 정보를 dict 형태로 먼저 저장했다.
    route_list = {
        '234000026':'720-2',
        '241420004':'82',
        '241420009':'99',
        '234000316':'60',
        '200000040':'7-2',
        '241420006':'82-1',
        '234000027':'6900',
        '234000046':'660',
        '234000047':'720',
        '234000136':'1550',
        '234000148':'5500-2'
    }
	
    for routeId, busNo in route_list.items():
        serviceKey = key
        stationId='228000872'
        routeId=str(routeId)
        url = "http://openapi.gbis.go.kr/ws/rest/busarrivalservice?serviceKey={}&stationId={}&routeId={}".format(serviceKey, stationId,routeId)

        request = Request(url)

        response = urlopen(request)

        receive = response.read()
        html = receive.decode('utf-8', errors='replace')
        bs = BeautifulSoup(html, 'html.parser')

        if bs.resultmessage.text == '정상적으로 처리되었습니다.':
            print(busNo, ' : ', bs.predicttime1.text)
            print(busNo, ' : ', bs.predicttime2.text)



if __name__ == '__main__':
    find_bus()
720-2  :  3
720-2  :  15
60  :  12
60  :  29
7-2  :  51
7-2  :  91
660  :  42
660  :  127

잠시후 도착 버스와, 그 다음 버스 정보를 확인 할 수 있다!

2 - Telegram에 적용

AWS의 cloud9활용하여 telegram 챗봇을 이용하여, “버스”라는 단어를 입력하면,

바로 잠시 후 도착 정보를 보내주는 봇을 만들었다.

telegram 사용법 포스팅

from flask import Flask, request, render_template
import requests
import time
import json
import os
from bs4 import BeautifulSoup as bs

app = Flask(__name__)
TELEGRAM_TOKEN = os.getenv('TELEGRAM_TOKEN')
API_TOKEN = os.getenv('API_TOKEN')
TELEGRAM_URL = 'https://api.hphk.io/telegram'

@app.route('/{}'.format(os.getenv('TELEGRAM_TOKEN')), methods=['POST'])
def telegram() :
    # 텔레그램으로부터 요청이 들어 올 경우, 해당 요청을 처리하는 코드
    #print(request.get_json()["message"]["from"]["id"])
    #print(request.get_json()["message"]["text"])
    response = request.get_json()
    
    """
    response 데이터 확인하기
    {'update_id': 693359414, 'message': {'message_id': 22, 'from': {'id': 748290634, 
    'is_bot': False, 'first_name': 'Jungjung', 'language_code': 'ko'}, 'chat': {'id': 748290634, 
    'first_name': 'Jungjung', 'type': 'private'}, 'date': 1545292109, 'text': '하이하이'}}
    """
    
    chat_id = response["message"]["from"]["id"]
    txt = response["message"]["text"]

    if(txt == '안녕'):
        msg = "존댓말."
    elif txt == '버스':
        route_list = {
            '234000026':'720-2',
            '241420004':'82',
            '241420009':'99',
            '234000316':'60',
            '200000040':'7-2',
            '241420006':'82-1',
            '234000027':'6900',
            '234000046':'660',
            '234000047':'720',
            '234000136':'1550',
            '234000148':'5500-2'
        }
        results = []
        for routeId, busNo in route_list.items():
            serviceKey = API_TOKEN
            stationId='228000872'
            routeId=str(routeId)
            url = "http://openapi.gbis.go.kr/ws/rest/busarrivalservice?serviceKey={}&stationId={}&routeId={}".format(serviceKey, stationId,routeId)
    
            response = requests.get(url).text

            bss = bs(response, 'html.parser')
    
            if bss.resultmessage.text == '정상적으로 처리되었습니다.':
                print(busNo, ' : ', bss.predicttime1.text)
                print(busNo, ' : ', bss.predicttime2.text)
                results.append([busNo, bss.predicttime1.text])
                results.append([busNo, bss.predicttime2.text])
        msg = ''
        for i in results:
            msg += '{} : {}분\n'.format(i[0], i[1])
            
    elif(txt == '안녕하세요') :
        msg = "넹"
        
    # 네이버 환율 크롤링 코드
    elif(txt == '환율') :
        url = 'http://info.finance.naver.com/marketindex/exchangeList.nhn'
        response = requests.get(url).text
        soup = bs(response, 'html.parser')
        soup = soup.find_all("td", {"class":{"tit", "sale"}})
        
        exchanges={}
        for i in range(88):
            if(i == 0 or i % 2 == 0):
                exchanges['국가'] = soup[i].text 
            elif(i % 2 == 1) :
                exchanges['환율'] = soup[i].text
        #print(exchanges)
        #print(exchanges[0])
        #print(exchanges[1]["cost"])

        for i in range(len(exchanges)):
            msg += ', '.join("{} = {}".format(key, val) for (key, val) in exchanges.items())
            
    else:
        msg = '등록되지 않은 메세지입니다.'

    url = 'https://api.hphk.io/telegram/bot{}/sendMessage'.format(TELEGRAM_TOKEN)

    requests.get(url, params = {"chat_id" : chat_id, "text" : msg})

    return '', 200
    
    
@app.route('/set_webhook')    # alert창 띄우기 
def set_webhook():
    url = TELEGRAM_URL + '/bot' + TELEGRAM_TOKEN + '/setWebhook'
    params = {
        'url' : 'https://sspy-week2-juneun.c9users.io/{}'.format(TELEGRAM_TOKEN)
    }
    response = requests.get(url, params = params).text
    return response

결과 확인

views
텔레그램 챗봇 확인

이제 아침에 급하게 뛰어나오면서 “버스”만 입력하면

잠시 후 도착 버스 정보를 확인할 수 있게 되었다 !

리눅스 파일 시스템 구조

|

리눅스의 디렉토리(혹은 파일 시스템 구조)는 윈도우와는 조금 다른 구조를 가지고 있다.

기본적으로 디렉토리를 구분하는 ‘/’(슬래시)는 리눅스에서 사용하고 윈도우는 반대인 ‘'(역슬래시)를 사용한다.

디렉토리 또한 그 명칭을 리눅스에서는 디렉토리(directory), 윈도우에서는 폴더(folder)라고 부른다.

views

리눅스 파일 시스템 구조

리눅스 시스템의 디렉토리 구조는 전체적으로 역 트리(tree) 구조를 하고 있습니다. 그리고 명령어의 종류와 성격, 사용권한등에 따라 각각의 디렉토리들로 구분됩니다. 리눅스 배포판들은 ‘리눅스 파일시스템 표준’ 인 FSSTND(LINUX FILE System Standard) 라는 표준을 준수하므로 대부분의 리눅스 배포판들은 그 기본 골격이 같습니다.

/(루트)

최상의 디렉토리인 루트 디렉토리를 의미하며, 리눅스의 모든 디렉토리들의 시작점이다. 즉, 모든 디렉토리들을 절대경로로 표기할 때에 이 디렉토리로부터 시작해야 한다.

/bin

기본적인 명령어가 저장된 디렉토리. 즉, 리눅스 시스템사용에 있어 가장 기본적이라고 할 수 있는 mv, cp, rm 등과 같은 명령어들이 이 디렉토리에 존재하며 root 사용자와 일반사용자가 함께 사용할 수 있는 명령어 디렉토리이다.

/boot

리눅스 부트로더(Boot Loader)가 존재하는 디렉토리. 즉, GRUB 과 같은 부트로더에 관한 파일들(grub.conf 등)이 이 디렉토리에 존재한다.

/dev

시스템 디바이스(device)파일을 저장하고 있는 디렉토리. 즉, 하드디스크 장치파일 /dev/sda, CD-ROM 장치파일 /dev/cdrom 등과 같은 장치파일들이 존재하는 디렉토리이다.

/etc

시스템의 거의 모든 설정파일이 존재하는 디렉토리. /etc/sysconfig(시스템 제어판용 설정파일), /etc/passwd(사용자관리 설정파일), /etc/named.conf(DNS 설정파일) 등과 같은 파일들이 존재한다.

/etc/mai/

sendmail.cf 나 access 파일등의 sendmail 의 설정파일들이 존재하는 디렉토리.

/etc/ssh/

SSH 서비스, 즉 sshd 데몬에서 사용하는 각종 설정파일들이 존재하는 디렉토리.

/etc/squid/

squid 프락시서버의 설정파일들이 저장된 디렉토리.

/etc/samba/

삼바관련 설정파일들이 저장된 디렉토리

/etc/skel/

계정사용자 생성시의 초기화파일들이 저장된 디렉토리(useradd 에서 사용함)

/etc/rc.d/

부팅레벨별 부팅스크립트파일들이 존재하는 디렉토리.

/etc/rc.d/init.d/

시스템 초기화 파일들의 실제파일들이 존재함.

/etc/pam.d/

PAM 설정 정보파일들이 저장된 디렉토리.

/etc/httpd/

RPM 으로 설치된 아파치 설정파일(httpd.conf 등)들이 저장된 디렉토리.

/etc/cron.d/, /etc/cron.daily/, /etc/cron.hourly/, /etc/cron.monthly/, /etc/cron.weekly/

모두 크론설정파일이 존재하는 디렉토리임.

/etc/xinetd.d/

xinetd 수퍼데몬에 의해 서비스되는 서비스설정파일이 존재함.

/home

사용자의 홈디렉토리, useradd 명령어로 새로운 사용자를 생성하면 대부분 사용자의 ID와 동일한 이름의 디렉토리가 자동으로 생성됨.

/lib

커널모듈파일과 라이브러리파일 즉, 커널이 필요로하는 커널모듈파일들과 프로그램(C, C++ 등)에 필요한 각종 라이브러리 파일들이 존재하는 디렉토리.

/media

DVD, CD-ROM, USB 등과 같은 탈부착이 가능한 장치들의 마운트포인트로 사용되는 디렉토리.

/mnt

/media 디렉토리와 비슷한 용도로 탈부착이 가능한 장치들에 대하여 일시적인 마운트포인트로 사용하는 디렉토리.

/proc

일명 “가상파일시스템” 이라고 하는 곳으로 현재 메모리에 존재하는 모든 작업들이 파일형태로 존재하는 곳이다. 디스크상에 실제 존재하는 것이 아니라 메모리상에 존재하기 때문에 가상파일시스템이라고 부른다. 실제 운용상태를 정확하게 파악할 수 있는 중요한 정보를 제공하며 여기에 존재하는 파일들 가운데 현재 실행중인 커널(kernel)의 옵션 값을 즉시 변경할 수 있는 파라미터파일들이 있기 때문에 시스템 운용에 있어 매우 중요한 의미를 가진다.

/root

시스템 최고관리자인 root 사용자의 개인 홈디렉토리.

/sbin

ifconfig, e2fsck, ethtool, halt 등과 같이 주로 시스템 관리자들이 사용하는 시스템관리자용 명령어를 저장하고 있는 디렉토리.

/tmp

일명 “공용디렉토리” . 시스템을 사용하는 모든 사용자들이 공동으로 사용하는 디렉토리. mysql 에서 사용하는 mysql.sock 등과 같은 소켓파일, 또는 아파치에서 사용하는 세션파일등이 생성되기도 한다. 웹해킹에 사용되기도 해서 주의를 요망.

/usr

시스템이 아닌 일반사용자들이 주로 사용하는 디렉토리. 즉, c++, chsh, cpp, crontab, du, find등과 같이 일반사용자들용 명령어들은 /usr/bin 에 위치한다.

/usr/bin/

일반 사용자들이 사용가능한 명령어 파일들이 존재하는 디렉토리.

/usr/X11R6/

X 윈도우 시스템의 루트 디렉토리.

/usr/include/

C 프로그램에 필요한 헤드파일(*.h) 디렉토리.

/usr/lib/

/lib 에 들어가지 않은 라이브러리 디렉토리.

/usr/sbin/

/bin 에 제외된 명령어와 네트워크관련 명령어가 들어있는 디렉토리.

/usr/src/

프로그램 소스(주로 커널소스)가 저장되는 디렉토리.

/usr/local/

MySQL, Apache, PHP 등과 같은 어플리케이션들을 소스로 컨파일설치할 때 사용되는 장소.

/usr/share/man/

명령어들의 도움말을 주는 메뉴얼(manual)페이지 디렉토리. 즉, 이 디렉토리에는 시스템에서 사용하는 모든 맨페이지파일(man page)이 존재함.

/var

시스템운용중에 생성되었다가 삭제되는 데이터를 일시적으로 저장하기 위한 디렉토리. 거의 모든 시스템로그파일은 /var/log 에 저장되고, DNS 의 zone 설정파일은 /var/named 에 저장되고, 메일파일은 /var/spool/mail 에 저장되며, 크론설정파일은 /var/spool/cron 디렉토리에 각각 저장됨.

/var/tmp/

/tmp 디렉토리와 같은 공용디렉토리. 즉, /tmp 디렉토리와 /var/tmp 디렉토리의 퍼미션은 1777 로서 sticky bit 가 설정되어 있는 공용디렉토리이다. 리눅스 시스템에서 공용디렉토리는 /tmp 와 /var/tmp 둘뿐이다.

/var/log/

시스템로그파일(messages, secure, xferlog 파일등)이 저장되는 디렉토리.

/var/ftp/

vsftp 등과 같은 FTP 서비스를 위한 다운로드될 파일들 즉, FTP 홈디렉토리.

/var/named/

BIND 즉, DNS 에서 사용하는 zone 파일들이 저장되는 디렉토리.

/var/spool/mail/

각 계정사용자들의 메일파일이 저장되는 디렉토리.

/var/spool/lpd/

프린트를 하기 위한 임시 디렉토리(스풀링 디렉토리).

/var/spool/mqueue/

발송을 위한 메일 일시저장 디렉토리.

/var/spool/cron/

각 사용자들의 cron 설정파일들이 저장된 디렉토리.

/var/spool/at/

atd 즉, 예약작업에 관한 파일들이 저장되는 디렉토리.

/lost+found

최상위 디렉토리인 / 디렉토리에만 존재하는 것이 아니라 파일시스템마다 존재할 수 있는 디렉토리임. 이 디렉토리는 fsck 또는 e2fsck 등과 같은 파일시스템 체크 및 복구유틸리티 실행후에 주로 생성이 되는 것으로서 복구되지 않은 채로 블록(block)만 존재하는 파일 즉, 연결이 끊어진 inode 들이 숫자파일형태로 존재하는 곳임. 숫자형태로 존재하는 파일들은 mv 명령어로 파일이름만 바꾸면 바로 복구될 수 있다.

ㅇㅇ

리눅스 소개

|

* Unix OS 계열 종류

unix system v

  • HP-UX

  • IBM AIX

  • IRIX

BSD

  • FreeBSD, open BSD
  • Sun OS (oracle)
    • solaris
  • NeXTSTEP
    • Darwin
    • Mac OSX
      • IOS
  • MS/SCO
    • MINIX OS
      • MS Windows

IBM PC : DOS

MS-DOS -> OS 2


리눅스는 어떻게 나왔을까

  • 1991년 핀란드 헬싱키 대학생이었던 리누스 토발즈가 취미로 개발하던 커널을 인터넷에 공개 하였다.(버전 0.1)

  • 타넨바움의 교육용 운영체제 미닉스(MINIX)커널을 기반으로 제작되었다.

  • 1994년에 안정적인 리눅스 커널 1.0이 발표

  • 1996년에 리눅스 커널 2.0이 발표

  • 2.0 부터는 IBM, 컴팩, 오라클 같은 서버와 데이터베이스 회사들의 전폭적인 지원 속에 급성장을 이루었다.

특징

  • 오픈 소스로 개발되는 운영체제이다.
  • GNU/Linux 라 불리만큼 GNU 도구를 사용해서 개발된다.
  • POSIX(Portable Operating System Interface)를 지원하기 때문에 유닉스와 100% 호환된다.
  • 따라서 유닉스의 명령어 뿐만 아니라 X 윈도우, BSD 소켓, IPC, POSIX Thread도 함께 지원하며 개발 환경과 방식도 UNIX와 별 차이가 없다.
  • 많은 아키텍처와 다양한 디바이스에 포팅 되고 있다.
  • 1990년 대 말까지는 서버 시장을 석권 하였는데(IMF), 유닉스(비쌈)와 윈도우 서버를 대체하는 서버 운영체제로 각광 받고 있다.
  • 2003년 출시된 리눅스 커널 2.6부터는 기본적으로 임베디드를 지원해서 임베디드 시장 뿐만 아니라 안드로이와 같은 모바일에서도 보다 폭넓게 채택되고 있다.
  • UNIX 운영체제의 특징을 모두 가지고 있다.(멀티 유저, 멀티 프로세스, 멀티 프로세서, 멀티 스레드)
  • 여러 사용자가 하나의 시스템을 사용하기 때문에 계정과 비밀번호 그리고 홈 디렉토리로 사용자를 구분 하며 계정별 권한과 제약을 두어 시스템 보안을 제공한다.

* GNU란?

“GNU’s Not Unux”

리눅스 커널이 포함된 GNU 패키지로 구성되어 동작하며 기능적인 유닉스 계열 시스템을 만들어준다.



리눅스 구조 –> file system

views
views

System call : 어떤 시스템을 실행시키기 위한 함수들의 모임

시스템 호출(system call)은 운영 체제커널이 제공하는 서비스에 대해, 응용 프로그램의 요청에 따라 커널에 접근하기 위한 인터페이스이다.

  • 주요 directory

    views
    주요 directory

파이썬 웹 표준 라이브러리 정리

|

views


웹 표준 라이브러리 구성

1) 파이썬 설치 시, 기본적으로 함께 설치되는 표준 라이브러리

2) 웹 클라이언트 프로그래밍 또는 웹 서버 프로그래밍에 따라 사용 모듈이 달라진다.

3) 2.x 와 3.x 에 따라 패키지명, 모듈명이 재구성되어 있는 차이가 있고 함수와 클래스등의 내용 자체는 거의 동일 

4) 웹표준 라이브러리의 구성

Django는 자유도가 떨어져서 Flask 사용이 더 편할 수도 있다.



python web library 공부

[ 웹 클라이언트 라이브러리 ? ]

1) 웹 서버에 요청을 보내는 모든 애플리케이션은 웹 클라이언트라 할 수 있다.

2) 웹브라우저, Open API를 사용하는 프로그램들

3) 웹 클라이언트와 웹 서버는 HTTP/HTTPS 프로토콜을 사용한다.



새로운 프로젝트 python_weblib에서 실습

[1] http.client모듈의 HTTPConnection Test

1) HTTP 프로토콜의 저수준의 요청을 보낼 수 있다.
2) urllib.request 요청과 동일한 요청을 보낼 수 있다.
3) GET 방식 요청

예제를 위해 예비된 2단계 도메인 네임인 ‘www.example.com’을 이용해 응답 확인하기

from http.client import HTTPConnection
conn = HTTPConnection('www.example.com')

성공 확인

# 성공
# GET / HTTP/1.1
# 200 OK
conn.request('GET', '/')
response = conn.getresponse()
print(response.status, response.reason)

if response.status == 200:
    body = response.read()
    print(body, type(body))
<출력> : 해당 홈페이지 출력
200 OK
b'<!doctype html>\n<html>\n<head>\n    <title>Example Domain</title>\n\n    <meta charset="utf-8" />\n    <meta http-
...

실패 확인 - 404 File Not Found

# 실패
# GET /hello.html HTTP/1.1
# 404 File Not Found
conn.request('GET', '/hello.html')
response = conn.getresponse()
print(response.status, response.reason)
<출력> 404 Not Found


[2] urllib.parse 모듈의 urlparse Test

from urllib.parse import urlparse

# full url 파싱
result = urlparse('http://www.python.org:80/guide/python.html:philosophy?overall=3#here')
print(result)
<출력>
ParseResult(scheme='http', netloc='www.python.org:80', path='/guide/python.html:philosophy', params='', query='overall=3', fragment='here')

ParseResult 속성 알아보기



[3] urllib.request 모둘의 urlopen Test

해당 url을 열어 데이터를 얻을 수 있는 기능을 제공한다.

urlopen(url) 리턴 타입 : <class 'http.client.HTTPResponse'>

urlopen(url [, data [, timeout]])

url : 열고자 하는 URL 문자열, request 클래스의 인스턴스가 포함된다.
data : POST 방식으로 전송 시에 서버로 업로드할 폼 데이터, URL 인코딩 되있는 문자열
timeout : 내부에서 사용하는 모든 블로킹 연산에 사용할 타임아웃 시간

지원 메소드

urlopen().read([nbytes]) : nbyte의 데이터를 바이트 문자열로 읽음 
urlopen().readline() : 한 줄의 텍스트를 바이트 문자열로 읽음
urlopen().info() : URL에 연관된 메타 정보를 담은 매핑 객체를 반환
urlopen().getcode() : HTTP 응답 코드를 정수로 반환( 200, 404 )
urlopen().close() : 연결을 닫는다

코드로 확인

from urllib.parse import urlencode
from urllib.request import urlopen, Request

1) get 방식

# get 방식
http_response = urlopen('http://www.example.com')
body = http_response.read()
print(body)

2) post 방식

# urlencode : 쿼리 스트링 파라미터를 Encoding 
data = {
    'email' : 'leeap1004@gmail.com',
    'password' : '1234',
    'name':'이정은'
}
data = urlencode(data)
print(data)
<출력> email=leeap1004%40gmail.com&password=1234&name=%EC%9D%B4%EC%A0%95%EC%9D%80
# post 방식
data = {
    'email' : 'leeap1004@gmail.com',
    'password' : '1234',
    'name':'이정은'
}
data = urlencode(data).encode('utf-8')
request = Request('http://www.example.com', data)
http_response = urlopen(request)
body = http_response.read()
print(body)

[ request에 header데이터 추가 기능 ]

cookie정보도 전송할 수 있다.

data = {
    'email' : 'leeap1004@gmail.com',
    'password' : '1234',
    'name':'이정은'
}
data = urlencode(data).encode('utf-8')
request = Request('http://www.example.com', data)

request.add_header('Content-Type', 'text/html')
request.add_header('cookies:jsessionid=3232dswsd2')

http_response = urlopen(request)
body = http_response.read()
print(body)