소개
라즈베리파이 4 에서 Firefox 브라우저를 Selenium 으로 실행한 내용에 대해 정리하는 글입니다.
깃헙 주소:
- https://github.com/ankylos/ankylos-crawler
도커 허브 주소
- https://hub.docker.com/repository/docker/lambrosopos/ankylos-scraper/general
물론, 이미지를 실질적으로는 ArgoCD 를 통해서 띄우기 위한 별도 차트 레포는 비공개로 되어 있지만, 추후에 정리되면 해당 레포에 관한 부분도 정리해보도록 하겠습니다.
들어가기 전에...
실제 글을 시작하기 전에 더 명확한 이해를 위한 맥락을 조금 더 공유해보도록 하겠습니다.
크롤링과 스크레이핑
일단, 크롤링 서버라고 부르고 있지만, 실질적으로는 스크레이핑 용도의 서버로, 네이버 음식점의 url 이 주어지면 해당 주소를 통해 메뉴를 데이터베이스에 저장하는 기능 하나를 가지고 있습니다. 그 이유는 크롤링 서버와 스크레이핑 서버를 별도로 분리할 예정이라 그렇습니다.
- 크롤링 서버는 말 그대로 네이버 음식점들의 주소와 요청에 대한 응답들을 저장하고 계속해서 새로운 음식점 주소들을 저장합니다.
- 스크레이핑 서버는 크롤링 서버에서 수집한 정보들을 바탕으로 내용들을 파싱하고 추출해서 데이터베이스에 저장합니다.
- 크롤링 서버와 스크레이핑 서버가 소통할 수 있게 메세지 큐가 클러스터 내에서 어느 주소들을 처리해야 할지 관리합니다.
클러스터
Raspberry Pi 4 에는 Debian GNU/Linux 11 (bullseye) 64 bit 이 설치되어 있습니다 (`cat /etc/*release`). 이 위에 k3s 가 실행되고 있고 CD 를 위한 ArgoCD 가 argocd 네임스페이스에 실행되고 있습니다. 사용할 때에는 보통 port-forwarding 으로만 잠깐 연결해서 사용합니다.
아쉽게도 Raspberry Pi 4 의 메모리가 적어서 (4GB) 최소한의 리소스를 사용하는 것을 목표로 하고 있습니다. Selenium 과 같은 프로세스를 실행하기에는 살짝 버겁기도 해서 조만간 다른 흐름으로 바꿀 예정입니다.
CI/CD
Github Actions 가 무료로 제공되어서 이를 주로 사용하고 있습니다. Test 하는 것과 배포하는 것 다 여기서 진행을 하고 있습니다.
Github 레포에서 Github Action 을 통해서 Release 가 되는 경우 도커 허브에 이미지를 배포하는 방식으로 이미지를 관리하고 있습니다. 이렇게 배포된 이미지는 2 개의 태그가 붙습니다.
- latest
- github commit sha
그리고 k3s 에 배포하기 위한 별도 차트 레포가 있어서 해당 레포의 태그만 업데이트 해주면 ArgoCD 에서 자동으로 이를 클러스터에 최종적으로 배포해주고 있습니다.
다만 지금 구조에서는 한 레포에 크롤링, 스크레이핑 다 넣을려고 했는데 Release 는 카테고리를 주기 힘들어서 별도의 레포로 관리를 할까 고민중에 있습니다. 어차피 크롤링 서버는 Go 로 제작할 예정이라 코드가 다르긴 하지만 레포가 많아지는 것에 대한 불편함이 있어서 하나로 생각하고 있었는데, microservice 구조에 좀 더 자연스럽게 별도로 진행할 것 같습니다.
Firefox 설치하기
이 글에서 설치하는 버전은 Firefox ESR (Extended Support Release) 입니다. 간단하게는 데이터 보호에 조금 더 신경 썼으며 기업에서 사용하는 목적으로 배포되는 버전으로 안정성을 높였습니다.
먼저 다음과 같이 패키지 목록을 업데이트 합니다.
$ sudo apt update
그리고 `firefox-esr` 을 설치해줍니다.
$ sudo apt install -y firefox-esr
설치가 완료되면 다음과 같이 `Firefox` 를 찾을 수 있는지 확인해줍니다.
$ which firefox
그러면 다음과 같이 뜨면 설치가 잘 된 것으로 볼 수 있습니다.
/usr/bin/firefox
Geckodriver
다음은 geckodriver 설치입니다. Geckodriver 는 쉽게 말해서 selenium 이 상호작용할 수 있도록 도와주는 역할을 하고 있습니다. Selenium 에서 Firefox 와 바로 소통하지 않고 해당 브라우저 드라이버를 통해서 상호작용하는 것이죠. 보통은 코드를 통해서 웹 브라우저에 접근을 하지 않기 때문에 해당 드라이버는 설치가 안되어 있는 경우가 많습니다.
Geckodriver 는 Github 릴리즈에서 원하는 릴리즈 버전을 다운로드 받을 수 있습니다.
- https://github.com/mozilla/geckodriver/releases
Releases · mozilla/geckodriver
WebDriver for Firefox. Contribute to mozilla/geckodriver development by creating an account on GitHub.
github.com
라즈베리파이는 ARM 기반 아키텍쳐이고 설치된 운영체제는 64비트라서 다음과 같이 `linux` 와 `aarch64` (ARM64) 가 들어있는 `tar.gz` 을 선택하시면 됩니다.
CLI 에서 다운로드 하려면 해당 링크를 복사해 `wget` 을 이용해 다음과 같이 받아줍니다.
$ wget "https://github.com/mozilla/geckodriver/releases/download/v0.33.0/geckodriver-v0.33.0-linux-aarch64.tar.gz"
위에서는 `v0.33.0` 을 다운로드 하지만 필요한 다른 버전을 하셔도 괜찮습니다.
다운로드가 되었다면 `tar.gz` 으로 압축되어 있는 부분을 해제해줘야 합니다.
$ tar -xvf geckodriver-v0.33.0-linux-aarch64.tar.gz
`tar` 명령어가 궁금하시다면 `man tar` 로 확인해보셔도 좋습니다. 위에서는 간단하게 `-xvf` 를 사용했는데 의미는 다음과 같습니다.
- v: Verbose 로 로그를 다 보고 싶을 때 추가합니다.
- f: Archive File 을 사용한다는 뜻으로 파일을 전달해준다는 뜻입니다. 파일을 넘겨준다는 신호를 보냅니다.
- x: Extract 로 압축된 파일에서 압축 해제하라는 뜻입니다.
압축 해제를 하게 되면 `geckodriver` 라는 실행가능한 파일이 생깁니다. 해당 파일을 어디에 놓아도 상관이 없긴 한데, PATH 를 통해서 찾을 수 있는 경로에 포함해 줍니다.
PATH 가 궁금하다면 `echo $PATH` 를 통해서 확인하고 출력된 디렉토리 중에 넣어주시면 됩니다.
저는 `/usr/local/bin` 에 추가해주겠습니다.
먼저 옮겨줍니다. `/etc/` 디렉토리는 root 에 있어서 sudo 가 필요합니다.
$ sudo mv ./geckodriver /usr/local/bin/geckodriver
이제 geckodriver 가 실행 가능하도록 모드를 추가해주겠습니다.
$ sudo chmod +x /usr/local/bin/geckodriver
Selenium
Selenium 설치
자 이제, Selenium 을 설치해보겠습니다.
파이썬으로 설치를 해보겠습니다. Pip 을 사용하면 다음과 같이 설치할 수 있습니다.
$ python3 -m pip install selenium
Selenium Firefox 사용하기
이제 드디어 selenium 을 통해 Firefox 브라우저를 실행해보겠습니다.
from selenium import webdriver
options = webdriver.FirefoxOptions()
options.add_argument("--headless")
service = webdriver.FirefoxService(executable_path="/usr/local/bin/geckodriver")
driver = webdriver.Firefox(options=options, service=service)
driver.get("https://www.google.com")
options
위에서 `options` 를 통해서 Firefox 옵션을 설정할 수 있습니다. 여기에서는 `-headless` 를 통해서 브라우저의 GUI 를 실행하지 않는 옵션입니다. 옵션을 추가하지 않게 되면 실제로 웹 브라우저를 실행하는 것과 동일하게 새로운 브라우저 창이 열리게 됩니다.
service
`FirefoxService` 를 통해서 geckodriver 경로를 정할 수 있습니다. 별도로 정해지지 않는다면 `geckodriver` 를 사용하게 됩니다. 따라서 PATH 에 포함되어서 실행될 수 있는 상태로 추가해놓고 실행가능한 상태여야 합니다.
driver
브라우저를 실행하는 부분인 `Firefox` 입니다. 앞서 만든 options 와 service 인스턴스들을 인자로 넘겨주면 Firefox 브라우저를 실행하게 됩니다.
Selenium 브라우징
Selenium 드라이버를 실행한 뒤에는 다음과 같이 사용할 수 있습니다.
# 웹페이지 방문
driver.get("https://www.google.com")
# HTML 소스 읽기
driver.page_source
# Javascript 실행하기
driver.execute_script("return window")
가져온 정보들로 이제 필요한 작업을 실행하면 됩니다.
정리
이번 글을 통해서 ARM 64 기반 Raspberry Pi 4 에서 Firefox 브라우저를 selenium 을 통해서 실행하게 되는 과정을 살펴보았습니다. 특히 크롤링, 스크레이핑을 위해서 자바스크립트를 실행해야하는 웹페이지 (SPA 기반) 을 탐색해야 할 때 제일 편한 방법인 것 같습니다.
물론, 성능적인 측면에서는 느려서, 가능하다면 병렬처리로 비동기 HTTP 요청들을 사용하는 것을 최대한 사용하는 것도 중요하다고 생각합니다. 특히 자바스크립트를 포함해 여러 리소스 등을 다 받게 된다면 몇 초는 필요하게 되어서 최대한 자제하는 것을 추천드립니다.
'Tools' 카테고리의 다른 글
k3s 라즈베리파이 클러스터 ArgoCD 설치 (0) | 2023.10.12 |
---|---|
유용한 Vim Plugins (0) | 2022.06.01 |
Intro to Scrapy (0) | 2022.06.01 |
iTerm과의 고군분투쓰 (0) | 2022.05.31 |
Atom text-editor (0) | 2022.05.30 |