3단계
"3단계 진행해 보자."
Intro
좋습니다! 이제 3단계: Selenium + Headless 브라우저 환경 구성으로 넘어가겠습니다. 이 단계에서는 실제 웹 브라우저를 Docker 컨테이너 안에서 Headless 모드로 실행하여, JavaScript까지 렌더링되는 웹페이지를 제어하는 환경을 구성할 거예요.
✅ 3단계 목표 요약
목표 | 내용 |
---|---|
Selenium 환경 구성 | selenium/standalone-chrome Docker 이미지 사용 |
NAS Python 코드에서 원격으로 Selenium 제어 | RemoteWebDriver 로 연결 |
JavaScript 렌더링되는 웹페이지 크롤링 테스트 | Google, YouTube, 동적 페이지 등 실습 가능 |
🧱 구성 아키텍처
NAS (Python 코드)
⇅ (HTTP:4444)
Docker 컨테이너 (Selenium + Chrome Headless)
✅ Step-by-Step 실행
📥 1. Selenium Docker 이미지 다운로드
sudo docker pull selenium/standalone-chrome
이 이미지는 Chrome + WebDriver + VNC 서버가 모두 포함된 풀 패키지입니다.
🚀 2. Selenium 컨테이너 실행
sudo docker run -d --name selenium-chrome \
-p 4444:4444 \
selenium/standalone-chrome
- 4444 포트는 WebDriver와 통신하는 포트입니다.
- 컨테이너가 실행되면 Selenium Grid 서버가 열립니다.
상태 확인:
http://<NAS_IP>:4444/status
🧪 3. NAS에서 Python 스크립트 작성 (selenium-test.py
)
# selenium-test.py
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
options = Options()
options.add_argument("--headless") # 창 없이 실행
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
driver = webdriver.Remote(
command_executor="http://<NAS_IP>:4444/wd/hub",
options=options
)
driver.get("https://example.com")
print("Page title:", driver.title)
driver.quit()
반드시
<NAS_IP>
를 실제 IP 주소로 바꿔주세요 (예:192.168.0.201
)
▶ 4. Python 실행 환경에서 테스트
sudo docker run -it --rm \
-v /volume1/docker-scripts:/app \
python:3.10 bash
컨테이너 내부에서:
cd /app
pip install selenium
python selenium-test.py
✅ 결과 기대 출력
Page title: Example Domain
→ 브라우저가 실제로 열리진 않지만 Headless Chrome이 해당 페이지를 받아서 제목을 출력한 것입니다. => 저자의 DNS에서는 example.com이 resolve되지 않았지만, chrome browser에서는 DNS over HTTPS (DoH) 또는 DNS over TLS (DoT) 사용 혹은 로컬 OS DNS 설정 무시하고 자체적으로 구글/클라우드플레어 등의 DNS를 사용할 수 있다고 한다.
📌 다음 가능 실습
- 특정 요소 추출:
driver.find_element(By.ID, "some-id")
- 스크린샷 저장:
driver.save_screenshot("page.png")
- YouTube 같은 SPA(Single Page App) 페이지 분석
지금 실행해보시고, 잘 되면 4단계로 자동화 및 로그 저장으로 넘어가볼게요!
진행 중 오류가 있으면 어떤 메시지 나왔는지 공유해주시면 바로 도와드릴게요.
4 단계
"4단계 진행해 보자."
Intro
좋습니다! 이제 4단계: NAS 내부에서 Python 코드와 Selenium 컨테이너 연동 자동화로 넘어가겠습니다.
이 단계는 지금까지 구성한 환경을 실제 자동화 스크립트 형태로 정리하고,
- NAS 공유 폴더에 코드/결과를 저장하고
- 여러 번 실행해도 안정적으로 동작하도록 구성하는 것을 목표로 합니다.
✅ 4단계 목표 요약
항목 | 설명 |
---|---|
Python 코드 자동 실행 | 크론탭이나 수동 실행이 가능한 형태로 구성 |
컨테이너 상태 자동 체크 | Selenium 서버가 떠 있는지 확인 |
결과 저장 | 크롤링 결과 또는 스크린샷을 NAS에 저장 |
에러 시 재시도 또는 로그 저장 | 나중에 디버깅을 위해 남겨두기 |
✅ Step-by-Step
📁 1. NAS 공유 폴더 구조 설정 (예: /volume1/docker-scripts
)
/volume1/docker-scripts/ -> 내환경은 /volume2/backups/scripts/
├── selenium-test.py
├── output/
│ ├── last_result.txt
│ └── page_screenshot.png
└── logs/
└── run.log
필요한 하위 디렉토리를 미리 만들어주세요.
🐍 2. selenium-test.py
업데이트 (자동화 + 저장)
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
import time
import os
from datetime import datetime
# 설정
NAS_OUTPUT_DIR = "/app/output"
NAS_LOG_DIR = "/app/logs"
URL = "https://example.com"
# 로그 기록
def log(message):
timestamp = datetime.now().strftime("[%Y-%m-%d %H:%M:%S]")
with open(os.path.join(NAS_LOG_DIR, "run.log"), "a") as f:
f.write(f"{timestamp} {message}\n")
print(f"{timestamp} {message}")
try:
log("Starting browser...")
options = Options()
options.add_argument("--headless")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
driver = webdriver.Remote(
command_executor="http://<NAS_IP>:4444/wd/hub", # 실제 NAS IP 입력
options=options
)
driver.get(URL)
log(f"Accessed: {URL}")
# 저장: 제목과 스크린샷
title = driver.title
with open(os.path.join(NAS_OUTPUT_DIR, "last_result.txt"), "w") as f:
f.write(f"Page Title: {title}\n")
screenshot_path = os.path.join(NAS_OUTPUT_DIR, "page_screenshot.png")
driver.save_screenshot(screenshot_path)
log(f"Saved screenshot to: {screenshot_path}")
driver.quit()
log("Browser closed.")
except Exception as e:
log(f"ERROR: {e}")
🔁
<NAS_IP>
는 반드시 실제 IP로 대체해주세요.
📁/app/output
,/app/logs
는 Docker에서 마운트할 NAS 공유 폴더입니다.
🐳 3. Python 컨테이너에서 실행
sudo docker run -it --rm \
-v /volume1/docker-scripts:/app \
python:3.10 bash
컨테이너 내부에서:
cd /app
pip install selenium
python selenium-test.py
✅ 결과 확인
output/last_result.txt
: 페이지 제목output/page_screenshot.png
: 렌더링된 스크린샷logs/run.log
: 실행 로그 기록
🔄 자동 실행 팁 (선택)
추후 cron
또는 Synology의 작업 스케줄러(Task Scheduler) 를 이용해서 아래 명령을 정기적으로 실행 가능:
sudo docker run --rm \
-v /volume1/docker-scripts:/app \
python:3.10 python /app/selenium-test.py
셸 스크립트로 저장해두면 더 편리합니다
✅ 다음 단계로 준비되셨다면…
- Selenium 대신 Playwright, Pyppeteer 등 대안 브라우저 사용
- Selenium 컨테이너에서 Python까지 통합 실행
- Docker Compose로 Selenium + Python 함께 구성 (5단계)
지금 자동화된 스크립트 실행해보시고, output
과 logs
에 결과 잘 남는지 확인해 보세요!
오류나 디테일 조정 원하시면 언제든지 도와드릴게요.
추가 단계
"자동 실행의 예에서는 selenium package 설치가 안되어 있어서 실패 할 것 같은데. 어떻게 생각해?"
이를 기반으로 Dockfile을 통해서 docker image를 만드는 방법을 알게 되었다.
"selenium beautifulsoup4 requests openai 까지 포함하는 docker image를 만드는 Dockerfile을 제안해줘. python-webscrap이라는 이름의 이미지로 만들었으면해. 추후에 이 이미지를 이용해서 news website를 bs4 혹은 selenium으로 scrapping하고 openai로 요약하는 작업을 해보려해."
Intro
멋진 계획입니다! 요청하신 대로 다음과 같은 Python 패키지들이 포함된 Docker 이미지를 만들기 위한 Dockerfile
을 아래에 제안드립니다:
selenium
beautifulsoup4
requests
openai
이미지 이름은 python-webscrap
으로 빌드할 수 있도록 구성하겠습니다.
✅ Dockerfile: python-webscrap
# 1. Python 3.10 베이스 이미지 사용
FROM python:3.10
# 2. 필수 패키지 설치
RUN pip install --no-cache-dir \
selenium \
beautifulsoup4 \
requests \
openai
# 3. 작업 디렉토리 설정 (선택 사항)
WORKDIR /app
📄 파일 이름 예시:
/volume1/docker-scripts/Dockerfile-webscrap
✅ 이미지 빌드 방법
cd /volume1/docker-scripts -> 내 환경에서는 /volume2/backups/scripts
sudo docker build -t python-webscrap -f Dockerfile-webscrap .
-f
옵션은 Dockerfile 파일명이 기본값(Dockerfile
)이 아닌 경우에 사용
✅ 이미지 실행 예시
sudo docker run -it --rm \
-v /volume2/backups/scripts:/app \
python-webscrap bash
이 실행 파일은 내 환경에 맞추고 interactive한 환경에서 python 명령어들을 테스트할 수 있게 하였다. 이 때, selenium-test.py와 openai-test.py를 테스트 해볼 수 있다.
from openai import OpenAI
import os
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY") or "YOUR KEY")
prompt = f"한국어로 3 문장 생성해줘."
try:
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": prompt}]
)
print(response.choices[0].message.content.strip())
except Exception as e:
print(f"(생성 실패: {e})")
'Vibe Coding' 카테고리의 다른 글
GUI 없는 NAS에서 Selenium Docker로 단계별 도전기: 1, 2단계 (2) | 2025.07.16 |
---|---|
GUI 없는 NAS에서 Selenium? Docker로 단계별 도전기 (4) | 2025.07.09 |
앱 사용 이력을 정확히 추적하는 법: Android에서 UsageEvents 분석기 만들기 (3) | 2025.06.25 |
AI 시대의 학습: 자비스와 간달프 사이에서 (5) | 2025.06.24 |
기술 덕후의 아침 루틴 만들기: Synology, Python, Obsidian 연동기 (3) | 2025.06.18 |