골방잡담

Selenium+Telegram+APScheduler+EC2 로 필요한 정보 알림 받기 본문

PC방에서/개인프로젝트

Selenium+Telegram+APScheduler+EC2 로 필요한 정보 알림 받기

sisu_ 2020. 4. 1. 00:01

오늘은 2월 초부터 시작해서 개인적으로 진행한 프로젝트에 대해서 공유를 해보려고 한다.
꾸준히 정보를 가져와야하는 사이트가 있어서, 방법을 찾다가 크롤링을 이용해 보기로 했다.
엄청 간단하게 할 수 있을 줄 알았는데...결론적으로 매일매일 안정적으로 돌 때까지 수많은 troubleshooting 과정을 거쳐서

결국 3월 말쯤에나 원하는 것을 얻을 수 있었다.


그래도 처음으로 제대로된 프로젝트를 혼자서 완수하니 정말 보람차다 ٩( ᐛ )و
이 참에 파이썬 공부, EC2 활용 공부까지 얻은 것이 많아 그 내용을 정리도 할 겸 글을 작성해본다.

 

Goal : 특정 웹사이트에서 현황을 가져와서, telegram으로 주기적으로 해당 내용 보내주기
Tasks :

  1. 웹사이트 로그인해서 원하는 정보 크롤링
  2. 텔레그램 봇으로 정보 전송
  3. 배치로 돌리기
  4. Amazon EC2에 올리기

 

[웹사이트 로그인해서 원하는 정보 크롤링]
처음에는 beautiful soup만 이용했다. (내가 들은 인강은 beautiful soup까지만 소개해줘서.. )

로그인까지는 잘 되었는데, 문제는 자꾸 첫 화면의 html(로그인 창)을 가져왔다. ( Ĭ ^ Ĭ )

찾아보니 동적으로 DOM이 변화한 후의 HTML을 활용하려면, Selenium을 써야 한다고 하여 Selenium에 대해서 알아보기 시작했다.

Selenium은 실제 웹 브라우저가 동작하기 때문에 JS로 렌더링이 완료된 후의 DOM 결과물에 접근하는 것이 가능하다고 한다.

Selenium 설치 후에는 chromedriver도 설치했다.

개인적으로 이 포스팅이 매우 도움이 되었다:
출처: [https://comdoc.tistory.com/entry/6-selenium-과-BeautifulSoup으로-daum-카페를-크롤링-해보자]

 

[텔레그램 봇으로 정보 전송]

  1. 봇을 하나 만든다 (텔레그램 모바일 앱에서 가능) : 토큰을 얻을 수 있음

  2. 봇을 내 친구로 추가해서, 내 ID를 알아낸다

  3. 내 계정으로 메시지 보내본다

    import telegram
    
    bot = telegram.Bot(token='{토큰값}')
    
    #봇한테 사람들이 보낸 메세지 보기  
    for i in bot.getUpdates():  
    print(i.message)
    
    bot.sendMessage(chat\_id = {내chat\_id}, text = '안늉')
  4. 크롤링 결과를 텔레그램 봇으로 보내기!

    import telegram
    
    bot = telegram.Bot(token='953516940:AAFaKsVIQY\_GlNZGG2aqlDwDBWjyuQu0TyU')  
    (생략)  
    receiver = {내chat\_id}  
    bot.sendMessage(chat\_id = receiver, text = msg)

[APScheduler 사용하기]
개인적으로 좀 어려웠다. 일단 걸어놓고 기다리는 시간이 답답하기도 했고,

스케줄러가 문젠지 아니면 다른 부분이 문젠지 헷갈려 troubleshooting이 어려웠다.

최종 코드는 아래와 같다. 테스트는 interval 모드로 했지만, 실제 돌릴 때는 특정 시간에 가게 하고 싶어서 CronTrigger을 이용했다 :

from apscheduler.schedulers.blocking import BlockingScheduler  
from apscheduler.triggers.cron import CronTrigger

def job\_function():  
    {크롤링을 위한 코드}  

sched = BlockingScheduler()  
#매일 오전 9시, 11시, 15시, 18시, 20시   
#sched.add\_job(job\_function, CronTrigger.from\_crontab('0 0,2,6,9,11 \* \* \*'), timezone='UTC')  
sched.add\_job(job\_function, 'interval', minutes=5)  
sched.start()  

[백그라운드로 실행하기]
backgroup에서 돌게 하기

nohup {command} &

kill 할 때는 :
ps -ef 한 후

kill -9 {프로세스 번호}

 

[ubuntu 환경에 맞게 수정하기]

 

OS

* ubuntu 18.04 사용

 

Python3 세팅

* ubuntu에 Python 2가 이미 설치되어 있지만, Python 2에서는 지원 안 되는 것들이 있다고 하여 Python3로 다시 세팅했다.

* pip 설치 https://linuxize.com/post/how-to-install-pip-on-ubuntu-18.04/

sudo apt-get install python3-pip  
pip3 install requests bs4 python-telegram-bot apscheduler python3-bs4

 

크롬/크롬 드라이버 설치 ( https://ducj.tistory.com/38에 매우 잘 정리돼있음)
* 크롬 다운로드 : https://linuxize.com/post/how-to-install-google-chrome-web-browser-on-ubuntu-18-04/

* 버전 체크 : google-chrome --version

* 사용한 버전 : Google Chrome 80.0.3987.149

* wget -N http://chromedriver.storage.googleapis.com/80.0.3987.106/chromedriver_linux64.zip

* sudo apt install unzip

* 한 후 unzip chromedriver_linux64.zip

* 원하는 폴더로 chromedriver위치 조정 (기존 코드에 있던 경로로 똑같이 옮겨두었음)

 

깃헙에서 가져오기 : FTP로 가져올 수도 있고, 솔직히 코드가 워낙 간단해서 그냥 복사해도 되지만 작업하면서 계속 github에 올렸던걸 그대로 가져와봤다. 결국엔 troubleshooting을 한참 해서 이게 도움이 많이 되었다;;ㅎㅎ..
* git clone {repository url}
* (참고 : https://ryan-han.com/post/aws/deployonec2/))
* 서버에서 바로 vi로 바꾼 내용을 add -> commit -> push까지 함. 하기 링크 참고 : https://codevkr.tistory.com/46
* 서버에서 git pull 하면 가져와짐.

 

[TroubleShooting History]

 

  1. 인코딩 오류

    ubuntu@ip-172-31-33-158:~$ python messaging.py  
    File "messaging.py", line 15  
    SyntaxError: Non-ASCII character '\\xec' in file messaging.py on line 15, but no encoding declared; see [http://python.org/dev/peps/pep-0263/](http://python.org/dev/peps/pep-0263/) for details  

    ==> https://pante.blog/371 이거 보고 해결됨
    이걸 첫 줄에 넣어주면 됨::::
    # -*- coding: utf-8 -*-

  2. headless로 바꿨는데도 ubuntu에서만 안 돌아가는 현상
    * 아래 답변 보고, /home/ubuntu 밑에 exe와 python 파일이 있던 것을 /home/ubuntu/wconcept 디렉터리 만들고, 그 밑에 python과 exe 넣었더니 잘 됨 🙂

구글링 만세  ʅʕ´•ﻌ•`ʔʃ 

 

  1. headless로 설정하기

    * 아래와 같이 옵션 추가해주고, stackoverflow에서 chrome_options 대신 options=options로 바꾸니 해결되었다는 글을 보고 똑같이 해보니 잘 되었음 🙂

    * options = webdriver.ChromeOptions()

    * options.add_argument('headless')

    * # driver = webdriver.Chrome('/chromedriver_win32_80.0.3987.16/chromedriver', options=options)

    * driver = webdriver.Chrome('/usr/lib/chromium-browser/chromedriver', options=options)

  2. 메모리 릭(memory leak) 현상
    - 자꾸 메시지가 3일 정도 오다가 (일 2회 오게 해놨었음) 중간에 메세지가 안 오고, 그 떄 서버에 들어가려고 하면 Network 이슈로 들어갈 수가 없다는 메세지가 떠서 서버를 재시작해야만 했다.

 

선배에게 물어보니 메모리 이슈일 수도 있다고 해서.. 결국에는 매 시간 메모리를 비우게끔 세팅을 했다.

- 캐시/메모리 비우기

* ubuntu로 하려니 권한이 없어서 아래와 같이 루트로 로그인한 후 설정했다.

* 루트로 로그인하기 :

Last login: Sun Mar 22 02:31:10 2020 from 211.200.73.148  
ubuntu@ip-172-31-43-2:

~~$ sudo passwd root  
Enter new UNIX password:  
Retype new UNIX password:  
passwd: password updated successfully  
ubuntu@ip-172-31-43-2:~~

~$ sudo vi /etc/ssh/sshd\_config~  
~ubuntu@ip-172-31-43-2:~

~~$ sudo vi /etc/ssh/sshd\_config  
ubuntu@ip-172-31-43-2:~~

$ sudo sync && echo 3 > /proc/sys/vm/drop\_caches  
\-bash: /proc/sys/vm/drop\_caches: Permission denied  
ubuntu@ip-172-31-43-2:~$ su root  
Password:  
root@ip-172-31-43-2:/home/ubuntu# sudo sync && echo 3 > /proc/sys/vm/drop\_cachesroot@ip-172-31-43-2:/home/ubuntu# vi /proc/sys/vm/drop\_caches

- 문제는... 이걸 설정한 후에도 메모리 확보가 안 됐다. 결론은, driver.close() 하던 것을 대신 driver.quit()으로 바꾸니... 잘 돌기 시작했다 (허무....)

 

 

+ 티스토리...줄맞추는거 왜 이렇게 힘든가요..? 흑흑흑흑 markdown으로 편집했는데....줄이 전혀 안 맞아서.. 기본모드로 편집하는데 편집할때 화면이랑 미리보기 화면은 또 다르네요.... ;;;;; 

Comments