2024. 2. 12. 10:52ㆍ[Way to PM] 사이드 프로젝트
0. 레퍼런스
1. 우선 순위 설정
1) Chat GPT 이용해서 python으로 이미지 크롤러 만들기
2) 클로링한 이미지를 이용해 Google Teachable Machine으로 ML모델 만들기
3) HTML과 ML 연동해 간단한 축구 유니폼 추천 사이트 구축
*(CSS로 기본적인 정리)
**참고영상(https://www.youtube.com/watch?v=1b7pXC1-IbE)
2. WHY - 해당 과제를 통해 얻고자 하는 목표
1) Chat GPT라는 기술을 이용해 python에 대한 지식이 없어도 크롤링 시스템 구축하여 신기술을 직접 이용해보고 적용하는 경험 쌓기
2) 이미지 데이터 수집해서 ML모델 만들어보는 경험 쌓기
3) 구축한 ML모델을 이용할 수 있는 웹사이트 구축
3. HOW - 구현한 코드
전체 코드
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver import ChromeOptions
import requests
from PIL import Image
import io
import os
# from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
def download_image(image_url, folder_name):
if not os.path.isdir(folder_name):
os.makedirs(folder_name)
try:
response = requests.get(image_url, stream=True)
if response.status_code == 200:
# Open the image and convert it to JPG
image = Image.open(io.BytesIO(response.content)).convert('RGB')
# Create a filename based on the number of images in the folder
safe_image_name = f"{len(os.listdir(folder_name)) + 1}.jpg"
image_file_path = os.path.join(folder_name, safe_image_name)
# Save the image as JPG
image.save(image_file_path, 'JPEG')
except Exception as e:
print(f"Could not download or convert {image_url}. Error: {e}")
def fetch_image_urls(driver, base_url, max_images):
image_urls = set()
current_page = 1
while len(image_urls) < max_images:
if current_page == 1:
driver.get(base_url) # URL for the first page
else:
driver.get(f"{base_url}/page/{current_page}/") # URL for subsequent pages
try:
# Use WebDriverWait to wait for the image elements to be present
WebDriverWait(driver, 10).until(
EC.presence_of_all_elements_located((By.CSS_SELECTOR, "img.render"))
)
except TimeoutException:
print(f"Timeout while waiting for images on page {current_page}")
thumbnails = driver.find_elements(By.CSS_SELECTOR, "img.render")
# ... rest of your code
if not thumbnails: # If no elements found, try with 'img.renderMeta'
thumbnails = driver.find_elements(By.CSS_SELECTOR, "img.renderMeta")
for img in thumbnails:
src = img.get_attribute('src')
if src and src not in image_urls:
image_urls.add(src)
if len(image_urls) >= max_images:
return list(image_urls)
current_page += 1
return list(image_urls)
# Set up the Selenium WebDriver
options = ChromeOptions()
options.add_experimental_option("detach", True)
driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()), options=options)
# Define base URL and number of images to download
base_url = "https://www.footyrenders.com/premier-league/wolverhampton-wanderers"
max_images = 400 # Set your desired number of images
# Fetch image URLs
urls = fetch_image_urls(driver, base_url, max_images)
# Download images and convert them to JPG
for url in urls:
download_image(url, 'wolverhampton-wanderers')
# Close the WebDriver
driver.quit()
문제해결 과정 2.
1) 문제 상황 발생:
-시스템으로 이미지를 긁어오다가 계속해서 멈추는 문제(특별한 오류는 나타나지 않고 IDE에서도 run 중인 상황인데 멈추는 현상 발생)
2) 문제 원인 탐색:
-Chat GPT로 오류 원인을 알아보고 구글링으로 다시 크로스체크
-페이지가 아직 완전히 로드되지 않았는데 이미지를 가져오려는 작업이 진행되서 비동기 처리 과정에서 오류 발생인줄 알았으나
-진짜 문제는 서버를 랜더링하고 즉각적으로 이미지를 가져오는 요청을 수행하면서 cpu와 메모리 사용량을 증가시켜 스크립트가 진행이 안됐던 것이다.
*스크래핑 과정에서 발생할 수 있는 오류 두 가지는 앞서 말한대고 비동기 처리 과정에서 오류가 발생하거나, img요소의 class명을 잘못적었을 경우이다. 이 경우 NoSuchElementException을 반환하고 스크립트가 종료되어야 한다.
하지만 내 경우엔 IDE의 run이 계속 실행중이었고, webdriver가 종료되지 않았으며 어떠한 오류도 반환하지 않았다.
당시 cpu와 메모리가 미친듯이 치솟았던 걸 고려했을 때 리소스 부담으로 인해 과정 자체가 중단되었던 것으로 생각하는게 합리적이다. (실제로 코드가 '멈춘것처럼'(실제로 멈추는 경우는 없음) 보이는 이유는 명시적인 타임셋을 설정하거나 랜더링 과정에서의 대기시간 정도인데, 이번 케이스의 경우엔 10분이상 아무 동작하지 않는 상태가 지속되었다.)
3) 문제 해결
while len(image_urls) < max_images:
if current_page == 1:
driver.get(base_url) # URL for the first page
else:
driver.get(f"{base_url}/page/{current_page}/") # URL for subsequent pages
try:
# Use WebDriverWait to wait for the image elements to be present
WebDriverWait(driver, 10).until(
EC.presence_of_all_elements_located((By.CSS_SELECTOR, "img.render"))
)
except TimeoutException:
print(f"Timeout while waiting for images on page {current_page}")
thumbnails = driver.find_elements(By.CSS_SELECTOR, "img.render")
# ... rest of your code
if not thumbnails: # If no elements found, try with 'img.renderMeta'
thumbnails = driver.find_elements(By.CSS_SELECTOR, "img.renderMeta")
for img in thumbnails:
src = img.get_attribute('src')
if src and src not in image_urls:
image_urls.add(src)
if len(image_urls) >= max_images:
return list(image_urls)
current_page += 1
return list(image_urls)
if문에서 driver로 URL을 가져와 접속하고 요소들이 DOM에 추가되기까지 대기하는 시간을 부여한 다음 이미지 url을 가져오는 작업을 수행하도록 코드를 수정하였다. 이를 통해 랜더링이 완료된 후 이미지 url을 요청하는 과정이 일어나기 때문에 리소스 부담이 줄었고 스크래핑 과정이 잘 수행되었다.
*웹 페이지 렌더링 과정
웹 페이지가 브라우저에 로드되고 사용자에게 보여지는 과정은 대략 다음과 같습니다:
- HTML 다운로드: 브라우저가 서버로부터 HTML 파일을 요청하고 다운로드합니다.
- DOM 생성: 다운로드된 HTML을 분석하여 DOM 트리를 생성합니다. DOM 트리는 웹 페이지의 구조를 나타내는 객체의 계층적 모델입니다.
- CSSOM 생성: CSS(스타일 시트) 파일도 다운로드하고 분석하여 CSSOM(CSS Object Model) 트리를 생성합니다. CSSOM은 페이지의 스타일 정보를 포함합니다.
- 렌더 트리 생성: DOM과 CSSOM을 결합하여 렌더 트리를 생성합니다. 렌더 트리는 실제로 화면에 그려질 요소들만 포함합니다.
- 레이아웃: 렌더 트리의 각 요소에 대한 위치와 크기를 계산합니다.
- 페인트: 계산된 위치에 요소들을 화면에 그립니다.
4. WHAT - HOW에 있는 완성 코드
5. 배운점 및 자기평가
배운점
1) 웹페이지 랜더링 과정에서 DOM에 비동기적으로 문서와 요소들이 추가된다는 점 복습
2) 코드는 '멈추지' 않는다. 명시적인 대기시간으로 인해 '멈춘 것처럼' 보일 뿐, 그외엔 예외를 반환하여 스크립트가 종료되는게 정상이다. 코드가 '멈춘' 것처럼 보인다면 다른 곳에서 이유를 찾는다.
자기평가
1. 이전이었다면 비동기 처리 과정에서의 문제라고 단언한 후 거기에 집착하였을텐데, 예외처리 과정을 배운 후라서 내 생각이 틀렸음을 빨리 인지하고 문제를 다시 바라본 후 원인을 다시 인식해 명확히 할 수 있었다.
2. 1의 과정에서 소요되는 시간을 더 줄일 것
'[Way to PM] 사이드 프로젝트' 카테고리의 다른 글
[Way to PM] 사이드 프로젝트 1. 구글 TM 머신 웹페이지에 커스텀하기 1장 (1) | 2024.02.12 |
---|---|
[Way to PM] 사이드 프로젝트 1. python 몰라도 웹스크래핑 시스템 코드 구축하기 1장 (1) | 2024.02.10 |