#elixirlang 언어로 만든 네이버 검색 랭킹 알림 #telegram 봇을 #heroku 플랫폼으로 배포하기
본격적인 사이드 프로젝트 시작에 앞서 몸풀기로 만들었다. 재미있는 주제가 안 떠올랐다. 조금 시간을 들여 뭘 만들지 고민하다가 만만한 검색 랭킹을 골랐다. 동작은 간단하다. 텔레그램 봇에 /start
명령을 입력하면 1분마다 네이버 검색 랭킹 알림이 온다. 그만 받아보려면 /end
명령을 입력하면 된다.
elixir 언어로 만들었다. 현업에서 쓰고 있고 계속 공부하는 언어라 다른 언어를 사용할 생각조차 안 했다. chrome driver를 사용해 chrome 브라우저가 렌더링하는 html에서 정보를 추출한다. 네이버 검색 랭킹 추출이 필요하다면 그냥 index.html 파일을 다운로드해서 추출하면 된다. 이후에 다이나믹 컨텐츠에서 추출할 걸 대비해 chrome driver를 사용했다. 배포는 heroku로 했다. 편해서 좋아라하는 서비스다.
elixir
defmodule SearchRankingTelegram.Telegram do
defp process_message(state, message) do
# ..
case String.trim(text) do
"/start" ->
put_in(
state.chat_id_list,
Enum.uniq(state.chat_id_list ++ [chat_id])
)
"/end" ->
put_in(
state.chat_id_list,
List.delete(state.chat_id_list, chat_id)
)
_ ->
state
end
telegram 모듈은 한번 만들어봐서 쉽게 짰다. /start
, /end
명령으로 chat_id
관리를 한다.
defmodule SearchRankingTelegram.Telegram do
def handle_cast({:broadcast, msg}, state) do
state.chat_id_list
|> Enum.each(fn chat_id ->
Nadia.send_message(chat_id, msg)
end)
{:noreply, state}
end
chat_id
값은 네이버 검색 랭킹을 가져와서 브로드캐스팅을 할 때, 사용한다.
defmodule SearchRankingTelegram.Scraper do
defp scraping() do
Logger.info("scraping")
navigate_to("https://www.naver.com/")
find_all_elements(:class, "ah_item")
|> Enum.filter(fn e -> attribute_value(e, "data-order") end)
|> Enum.map(fn e ->
{find_within_element(e, :class, "ah_r") |> inner_text(),
find_within_element(e, :class, "ah_k") |> inner_text()}
end)
스크레이핑(scraping)엔 hound 라이브러리를 사용했다. hound 세션은 elixir 프로세스당 하나만 만들 수 있다. 괜찮은 디자인 결정. 프로세스를 잘게 만들어서 디자인하는 elixir랑 잘 어울린다. 이런 디자인을 한 덕에 세션에 관련된 함수를 session id 없이 그냥 호출할 수 있어 편하다.
config :hound, driver: "chrome_driver", browser: "chrome_headless"
hound는 다양한 driver를 지원한다. 웹브라우저로 chrome을 주로 사용해서 chrome driver를 선택했다.
heroku
heroku에서 앱을 만들고 cli를 설치한다.
$ heroku buildpacks:add "https://github.com/HashNuke/heroku-buildpack-elixir.git"
$ heroku buildpacks:add "https://github.com/heroku/heroku-buildpack-google-chrome.git"
$ heroku buildpacks:add "https://github.com/heroku/heroku-buildpack-chromedriver.git"
그 후 elixir, chrome, chrome driver 빌드팩을 설치한다.
$ cat elixir_buildpack.config
elixir_version=1.7.3
디폴트 elixir 버전이 낮아서 최신 버전으로 설정한다.
$ cat Procfile
worker: mix run --no-halt
$ heroku ps:scale web=0
$ heroku ps:scale worker=1
worker dyno로 실행한다. 디폴트 세팅은 web dyno 하나가 켜져 있기 때문에 web dyno를 끄고 worker dyno를 켜는 작업을 해야한다.
$ heroku config:set TELEGRAM_TOKEN=xxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
$ heroku config:set CHROME_DRIVER_PATH=/app/.chromedriver/bin/chromedriver
실행에 필요한 환경변수를 세팅한다.
$ git push heroku master
발사!
프로젝트 홈페이지 - ohyecloudy/search-ranking-telegram - github.com