ㅁ 개요
O 프로그램 소개
- 이번 글은 이전글((실습)파이썬 네이버에서 강아지로 검색 후 강아지 이미지를 자동으로 크롤링 하는 프로그램 만들기 - 11.이미지 저장을 위한 별도 폴더 생성)에 이은 13번째 마지막 글로 많은 수의 이미지(예: 강아지 100장 등)를 내려 받으려면 셀레니움을 이용하여 동적으로 페이지 다운 후 다운로드 해야 하는데, 이러한 동적 페이지 다운 방법에 대해 알아 보겠습니다.
O 완성된 프로그램 실행 화면
1.이전 소스코드( 11.crawing_naver.py )에서 다운로드할 이미지 수를 50개로 지정(j=50)하고 실행하면 다음과 같습니다.
즉, 50개를 지정해도 최대 이미지 20장만 다운로드 된 것을 볼 수 있습니다.
코드를 수정 후 다시 실행하면 아래와 같이 이미지 50장이 모두 다운로드 되는 것을 확인 할 수 있으며, 그 이상으로 숫자를 늘려도 모두 다운로드 받을 수 있습니다.
50장 모두 다운로드 된 것을 보여주고 있습니다.
ㅁ 세부 내용
O 완성된 소스
소스 : 13.crawing_naver.py
# -*- coding utf-8 -*-
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
import time
from bs4 import BeautifulSoup
from datetime import datetime
import requests
import os
from datetime import datetime
import re
# 개선사항(숙제) 모두 해결한 소스임
# 9.인코딩된 이미지를 어떻게 다운로드하여 저장할 것인지
# 10.파일로 저장시 파일이름에 특수문자가 포함된 경우의 처리를 어떻게 할 것인지
# 11.이미지 저장시 현재폴더가 아닌 별도 폴더 생성 후 해당 폴더에 어떻게 저장할 것인지
# 12.폴더 이름을 현재시간을 사용해서 만들려면 어떻게 하면 되는지
# >예: img_20240301_113242
# 13.많은 이미지를 받을 경우 페이지를 내린 후 받아야 하는데 이를 어떻게 해결할 것인가?
##########################################
# 1.셀레니움을 이용한 크롬브라우저 자동 띄우기
##########################################
s = Service("C:/download/chromedriver.exe") # Replace with the actual path
options = webdriver.ChromeOptions()
browser = webdriver.Chrome(service=s, options=options)
##########################################
# 12.폴더 이름을 현재시간을 사용해서 만들기
##########################################
# 현재 날짜를 가져오기
current_date = datetime.now().strftime("%Y%m%d_%H%M%S")
# 폴더 이름 생성
folder_name = f"img_{current_date}"
##########################################
# 11.이미지 저장을 위한 별도 폴더 생성
##########################################
folder_path = os.path.join(os.getcwd(), folder_name)
try:
os.mkdir(folder_path)
print(f"폴더 '{folder_name}'가 생성되었습니다.")
except FileExistsError:
print(f"폴더 '{folder_name}'는 이미 존재합니다.")
except Exception as e:
print(f"폴더 생성 중 오류가 발생했습니다: {e}")
# 검색어
plusUrl = "강아지"
##########################################
# 2.네이버 검색 페이지 로딩하기
##########################################
baseUrl = 'https://search.naver.com/search.naver?where=image&sm=tab_jum&query='
url = baseUrl + plusUrl
print(url)
browser.get(url)
time.sleep(2)
##########################################
# 13.셀레니움을 이용해서 페이지 내리기
##########################################
j = 50 # 이미지 수
k = round(j/15) # 스크롤 내리는 횟수
# if k == 0:
# k = 0
# 스크롤을 여러 번 내리려면 반복문을 사용
for i in range(k): # 3번 스크롤을 내릴 예시
# 자바스크립트를 사용하여 페이지를 스크롤
browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# 스크롤 후 로딩을 위해 충분한 시간을 기다릴 수 있도록 설정 (필요에 따라 조절)
time.sleep(2)
# # 브라우저 종료
# browser.quit()
print("페이지 스크롤이 완료되었습니다.")
##########################################
# 3.네이버 검색 페이지에서 모든 소스 가져오기
##########################################
html_source = browser.page_source
# print(html_source,"\n\n\n\n++++++++++++++++++++++++++++++++++++++++++++++")
soup = BeautifulSoup(html_source, 'html.parser')
# print(soup)
##########################################
# 4.가져온 소스 필터링 테스트 하기
##########################################
# 가져온 소스에서 이미지 태크의 클래스 속성이 '_fe_image_tab_content_thumbnail_image' 인것을 가져와 보기
img = soup.find('img', {'class': '_fe_image_tab_content_thumbnail_image'})
# print(img)
# https://search.pstatic.net/common/?src=http%3A%2F%2Fblogfiles.naver.net%2FMjAyNDAxMDhfOTEg%2FMDAxNzA0NjgzOTQwMTAx.JKnvEIv6ST9A9IW6iTtTtAR2MtkkBaRPlF_--TLfUfIg.KAh-qQql-eBqUuP2Kkb2yGj2pdSMNRVM3KosTAiTVdQg.JPEG.rkddl2001tmf%2Fth_%252817%2529.jpg&type=a340
############################################################
# 5.가져온 소스에서 이미지 링크와 설명만 뽑아서 리스트에 담아두기
############################################################
image_links = []
image_alts = []
for img in soup.find_all('img', {'class': '_fe_image_tab_content_thumbnail_image'}):
image_links.append(img['src'])
image_alts.append(img['alt'])
# print(image_links,"\n\n")
# print(image_alts)
############################################################
# 6.이미지 링크와 설명 가공하기(원하는대로 만들기)
############################################################
# j = 2 # 가져올 이미지 수
# result = list(zip(image_links[:j], image_alts[:j]))
# print(result,"\n")
# print(result[0],"\n")
############################################################
# 7.이미지를 다운로드하고, 이미지 파일이름 만들기
############################################################
for i, (link, alt) in enumerate(zip(image_links[:j], image_alts[:j]), start=1):
# print(link)
# link = link.split(':')[0]
############################################################
# 9.인코딩된 이미지 제외하기
############################################################
if link.split(':')[0] == 'https':
img_data = requests.get(link).content
filename = f'{i}_image_{str(alt)}.jpg'
############################################################
# 10.파일이름에 특수문자 포함 시 처리하기
############################################################
filename = re.sub(r'[^\w\s.]', '', filename)
# 폴더변경(새로 생성한 이미지 폴더로 이동)
os.chdir(folder_path)
############################################################
# 8.PC에 다운로드한 이미지를 저장하기
############################################################
try:
with open(filename, 'wb') as f:
f.write(img_data)
print(plusUrl, "이미지가 내PC에 잘 저장되었습니다.")
except:
print(plusUrl, "이미지가 내PC에 잘 저장되지 않았습니다. 에러가 발생하였습니다.")
O 소스 실행
O 주요 내용
아래 소스에 대해 간략히 설명하면 다음과 같습니다.
line 72~83: 셀레니움에서 최초 브라우저를 띄우고 로딩(약 2초 이상)한 후 동적 페이지를 아래로 스크롤 해야만 다수의 이미지를 받을 수 있습니다. 여기서는 이미지의 수에 따라 페이지 다운의 횟수를 지정하였습니다.
예를 들어 다운로드 받을 이미지 수가 50개이면 50/15 = 3.3xx 인데, round()함수를 사용하면 3이됩니다. 따라서 이미지 50장 설정 시 페이지 다운은 3번 하게 됩니다.
line 80 : 페이지 다운은 아래 코드로 실행합니다.
line 83 : 페이지 다운 후 이미지가 제대로 로딩 될 수 있도록 반드시 여유 시간(time.sleep(2))을 주어야 합니다.
ㅁ 정리
O 우리가 배운 내용
- 오늘 우리가 배운 내용 중 가장 중요한 부분을 꼽으라면 아래와 같습니다.
아래 주석 참조
-이것으로 '(실습)파이썬 네이버에서 강아지로 검색 후 강아지 이미지를 자동으로 크롤링 하는 프로그램 만들기'의 모든 강의를 마칩니다.
오늘은 여기까지이며, 댓글과 하트는 제가 이글을 지속할 수 있게 해주는 힘이 됩니다.
감사합니다.