상황
- Google에서 이미지를 크롤링하는 파이썬 스크립트를 쿠버네티스 클러스터에 pod로 띄우려고 했다
- Script → Docker container 과정으로 테스트 후 정상 동작하는 걸 확인 후 Pod로 띄웠는데 실패…
- 그동안 Docker container 에서 동작 → Pod에서 동작으로 이해하고 있었다.
- 결론: 실행환경을 고려할 때 CPU 아키텍쳐도 고려를 해야한다!
과정
1. Google에서 이미지 크롤링하는 파이썬 스크립트 (크롬사용)
Selenium은 웹 테스트를 할 때 사용하는 프레임워크인데 BeautifulSoup과 더불어 크롤링할 때 많이 사용되는 도구들 중 하나다.
실제로 우리가 구글에서 검색할때처럼 검색창에 키워드를 입력하고 기다린 후 스크롤을 내리는 과정들을 코드로 작성한다. 코드를 보면 어릴적 게임할 때(라스트킹덤 광물캘때) 사용하던 매크로같은 느낌이 든다.
위 그림처럼 Selenium 패키지를 통해 파이썬 코드로 Browser driver를 통해 실제 browser로 명령/요청을 전달하고 응답을 받는다. 이 과정을 위해 아래의 3가지가 갖춰진 환경이 필요하다.
- 크롭 웹 브라우저
- 크롬 드라이버
- 파이썬 Selenium 패키지
이 때 중요한건 크롬 웹브라우저와 크롬 드라이버의 버전의 호환성이다. 웹 브라우저는 자주 업데이트가 되는데 크롬 드라이버의 버전이 업데이트가 되지 않으면 어느 순간 크롤링이 안되는 문제가 발생한다. 본 글에서는 특정한 버전으로 맞춰서 진행한다.
진행했던 환경은 아래와 같다.
- x86_64, Ubuntu 20.04.6 LTS,1CPU, 1GB
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.4 LTS
Release: 20.04
Codename: focal
$ uname -a
Linux ubuntu-s-1vcpu-512mb-10gb-sfo3-01 5.4.0-122-generic #138-Ubuntu SMP Wed Jun 22 15:00:31 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
1) 크롭 웹 브라우저 설치
현재 날짜 기준(2023.12.25) Chrome 웹 브라우저의 stable 버전은 120.0.6099.109
(https://googlechromelabs.github.io/chrome-for-testing/#stable
# 크롬 웹브라우저 다운로드 및 설치 (working directory: /root/crawling)
$ wget https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/120.0.6099.109/linux64/chrome-linux64.zip
$ unzip chrome-linux64.zip
2) 크롬 드라이버 설치
위 버전에 맞춰서 크롬 드라이버도 설치
# 크롬 드라이버 다운로드 및 설치 (working directory: /root/crawling)
$ wget https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/120.0.6099.109/linux64/chromedriver-linux64.zip
$ unzip chromedriver-linux64.zip
3) Python selenium 패키지 설치
pip install "selenium == 4.15.1"
크롤링하는 코드는 본 유투브 링크를 참고했고, apple이라는 키워드로 검색했을 때 나오는 이미지들을 저장하는 코드이다.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys # 엔터처리용
import time
import urllib.request
import os
options = webdriver.ChromeOptions()
options.add_argument("--headless") # '창이 없는’: 서버에서는 웹브라우저 창을 못띄우니 필요
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage") # 공유메모리 사용하지 않음
options.add_argument("--single-process")
options.binary_location = '/root/crawling/chrome-linux64/chrome'
service = webdriver.ChromeService(executable_path='/root/crawling/chromedriver-linux64/chromedriver')
driver = webdriver.Chrome(service=service, options=options)
URL = "<https://www.google.co.kr/imghp>"
KEYWORD = "apple"
driver.get(url=URL)
# time.sleep은 fixed, implicity는 flexible로 time_to_wait이 maximum time
driver.implicitly_wait(time_to_wait=10)
keyElement = driver.find_element(By.NAME, "q")
keyElement.send_keys(KEYWORD)
keyElement.send_keys(Keys.RETURN) # 키보드 엔터
bodyElement = driver.find_element(By.TAG_NAME, "body")
time.sleep(5) # 엔터치고 이미지 나오는 시간 기다림
image_candidates = []
print("Crawling Images Start!")
for i in range(1):
bodyElement.send_keys(Keys.PAGE_DOWN)
time.sleep(0.2)
images = driver.find_elements(
By.XPATH, '//*[@id="islrg"]/div[1]/div/a[1]'
) # XPATH는 변경될 수 있고 web browser의 개발자도구 이용해서 확인필요
image_candidates.append(images)
for images in image_candidates:
for idx, image in enumerate(images):
image.send_keys(Keys.ENTER)
time.sleep(0.5)
high_images = driver.find_elements(
By.XPATH,
'//*[@id="Sva75c"]/div[2]/div[2]/div[2]/div[2]/c-wiz/div/div/div/div/div[3]/div[1]/a/img[1]', # XPATH는 변경될 수 있고 web browser의 개발자도구 이용해서 확인필요
)
try:
real_image = high_images[0].get_attribute("src")
except Exception as e:
print(f"Exception: {e}")
continue
try:
urllib.request.urlretrieve(
real_image,
os.path.join(os.getcwd(), str(idx)) + ".jpg",
)
except Exception as e:
print(e)
정상적으로 동작하는걸 확인했고 Docker 이미지로 만들어서 쿠버네티스 파드로 띄우려고 했는데 아래와 같은 에러가 발생했다.
OSError: [Errno 8] Exec format error: '~~/chromedriver-linux64/chromedriver’
에러메세지가 분명하진 않다.
이것저것 시도 후 파악한 결과는 CPU 아키텍처에 맞는 chrome 웹브라우저와 드라이버를 다운받아야했다. 알아보니 쿠버네티스 pod는 AWS graviton 기반의 인스턴스에 뜨게 되는데 이는 arm64기반의 cpu였다!
결국 arm64 기반의 크롬 웹브라우저와 드라이버를 다운로드 후 해결했다.
ARM은 intel이나 amd와 호환되지 않는 cpu 아키텍쳐로 저전력 고효율을 목적으로 하는 곳(ex) 스마트폰)에 많이 사용되었는데 많이 발전해서 이제 PC용으로도 사용하는 시도가 많아지고 있다고 한다. 앞서 이야기한 AWS의 Graviton이나 Apple의 M1, M2칩이 그 예이다. Cloud환경에서 작업할 때 CPU 아키텍쳐도 고려해야한다는 걸 알 수 있는 경험이었다.
참고
- [python] selenium 이용한 구글 이미지 크롤링 및 이미지 저장 (https://code-code.tistory.com/165)
- https://velog.io/@480/이제는-개발자도-CPU-아키텍처를-구분해야-합니다
- https://www.browserstack.com/guide/selenium-webdriver-tutorial
'Python' 카테고리의 다른 글
super() (0) | 2024.09.15 |
---|---|
The Walrus Operator: Python's Assignment Expressions (바다코끼리 연산자) (0) | 2024.08.31 |
URL 다루기 위한 python의 built-in 패키지: urllib (0) | 2024.08.25 |
Pillow로 Image를 열 때 자동회전되는 현상 (0) | 2024.01.15 |
[Python] annotation 과 forward reference (0) | 2022.06.06 |