이미지 크롤링
네이버와 구글에서 검색어를 입력하고 검색해서 나온 이미지들을 컴퓨터에 저장해보자.
1. 네이버
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager
import time
import pyautogui
import os
import urllib.request
# 꺼짐 방지
chrome_options = Options()
chrome_options.add_experimental_option("detach", True)
# 불필요한 에러메세지 없애기
chrome_options.add_experimental_option("excludeSwitches", ["enable-logging"])
# 크롬드라이버 매너저를 통해 드라이버를 설치, 서비스를 만들어낸다
service = Service(executable_path=ChromeDriverManager().install())
driver = webdriver.Chrome(service = service, options=chrome_options)
keyword = pyautogui.prompt("이미지를 가져올 검색어를 입력하세요.")
if not os.path.exists(f"imagecrawling/{keyword}"):
os.mkdir(f"imagecrawling/{keyword}")
url = f"https://search.naver.com/search.naver?where=image&sm=tab_jum&query={keyword}"
driver.implicitly_wait(10)
driver.maximize_window()
driver.get(url)
before_h = driver.execute_script("return window.scrollY")
while True:
# 아래로 내리기
driver.find_element(By.CSS_SELECTOR, 'body').send_keys(Keys.END)
# 로딩 시간 주기
time.sleep(1)
# 스크롤 후 높이
after_h = driver.execute_script("return window.scrollY")
if(after_h == before_h):
break
before_h = after_h
# 이미지 태그
images = driver.find_elements(By.CSS_SELECTOR, "._image._listImage")
for i, image in enumerate(images, 1):
# 이미지 태그 주소 가져오기
img_src = image.get_attribute("src")
print(i,img_src)
urllib.request.urlretrieve(img_src, f'imagecrawling/{keyword}/{i}.png')
네이버 이미지는 동적 웹사이트라서 스크롤 시 HTML이 추가로 생성된다.
BeautifulSoup 라이브러리는 정적 웹사이트를 다룰 때 효과적이지만, 동적 웹사이트를 다루기는 힘들다.
Selenium 라이브러리를 사용해 동적 웹사이트를 크롤링하자.
몇 가지 설정을 진행하고 진행한다.
우선 웹사이트를 더 이상 HTML이 생성되지 않을 때 까지 쭉~ 내려주자.
다음으로, HTML에서 이미지 부분을 의미하는 태그를 찾아주고 find_element 메서드로 가져와준다.
저장은 urllib 라이브러리를 사용해서 처리한다.
각각의 라이브러리들이 어떻게 동작하는지 엄밀하게 이해하려 노력하기보다는 활용에 집중하자. (기본적인 이해는 필요하다)
2. 구글
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager
import time
import pyautogui
import os
import urllib.request
# 꺼짐 방지
chrome_options = Options()
chrome_options.add_experimental_option("detach", True)
# 불필요한 에러메세지 없애기
chrome_options.add_experimental_option("excludeSwitches", ["enable-logging"])
# 크롬드라이버 매너저를 통해 드라이버를 설치, 서비스를 만들어낸다
service = Service(executable_path=ChromeDriverManager().install())
driver = webdriver.Chrome(service = service, options=chrome_options)
#---- selenium 기본설정 끝----#
keyword = pyautogui.prompt("이미지를 가져올 검색어를 입력하세요.")
if not os.path.exists(f"imagecrawling/{keyword}"):
os.mkdir(f"imagecrawling/{keyword}")
url = f"https://www.google.com/search?q={keyword}&sxsrf=ALiCzsZoREwf1RYipnTo3vBUVmroeABBfg:1663652357625&source=lnms&tbm=isch&sa=X&ved=2ahUKEwjVgbn-06L6AhUNO3AKHRtcAKIQ_AUoAXoECAIQAw&biw=1280&bih=569&dpr=1.5"
driver.implicitly_wait(10)
driver.maximize_window()
driver.get(url)
before_h = driver.execute_script("return window.scrollY")
while True:
# 아래로 내리기
driver.find_element(By.CSS_SELECTOR, 'body').send_keys(Keys.END)
# 로딩 시간 주기
time.sleep(1)
# 스크롤 후 높이
after_h = driver.execute_script("return window.scrollY")
if(after_h == before_h):
break
before_h = after_h
# 썸네일 이미지 태그
images = driver.find_elements(By.CSS_SELECTOR, ".rg_i.Q4LuWd")
for i, image in enumerate(images, 1):
# 썸네일 클릭해서 저장
# 클릭 시 셀레니움 대신 자바스크립트 활용
driver.execute_script("arguments[0].click()", image)
time.sleep(1)
# 큰 이미지 사용하기 base64 사용 x
if i == 1:
target = driver.find_elements(By.CSS_SELECTOR, "img.n3VNCb")[0]
else:
target = driver.find_elements(By.CSS_SELECTOR, "img.n3VNCb")[1]
img_src = target.get_attribute("src")
# Forbidden 에러 해결 (사람이 하는거로 인식하도록)
opener = urllib.request.build_opener()
opener.addheaders = [('User-Agent', 'Mozila/5.0')]
urllib.request.install_opener(opener)
print(i,img_src)
# urllib.error.URLError: <urlopen error [SSL: WRONG_SIGNATURE_TYPE] wrong signature type (_ssl.c:997)
# 위의 오류는 크롤링 방지 문구이다. try - except로 처리해주자.
try:
urllib.request.urlretrieve(img_src, f'imagecrawling/{keyword}/{i}.png')
except:
pass
구글도 네이버와 비슷하게 진행하면 되지만, HTML구조 말고도 조금 다른 부분이 있다.
구글 이미지에서는 썸네일을 누르면 동적으로 HTML이 생성돼 상세 화면이 추가된다.
상세 화면에서 볼 수 있는 큰 이미지를 가져와야한다.
즉, 셀레니움으로 썸네일을 클릭한 후 상세 화면에서 확인할 수 있는 이미지를 저장하면 된다.
구글의 이미지 HTML을 살펴보면 base64 인코딩 방식을 사용하는걸 확인할 수 있다.
이미지의 크기를 일관적으로 가져가려면 base64를 사용하지 않는 이미지로 가져와야 하고, 이 부분이 첫 번째 요소와 다른 요소와 다름에 주의하자.
네이버 뉴스를 크롤링 할 때 했던 것처럼 봇으로 인식되는걸 방지하기 위해 이미지 저장 메서드에 헤더를 추가해준다.
클릭도 셀레니움이 지원하는 클릭 대신 자바스크립트의 클릭을 사용하도록 한다.
마지막으로 사이트에서 크롤링을 막아놓은 경우 오류를 뱉는 대신 해당 이미지는 패스하도록 설정하면 끝이다.
동적 웹 페이지를 다룰 때는 셀레니움을 자주 사용하지만, 셀레니움은 BeautifulSoup보다 느리다.
작업의 속도가 중요할 때는 셀레니움으로 HTML을 모두 로딩한 후 HTML을 BeautifulSoup로 보내는 방식으로 사용해보자.
'Web > Web Scraping' 카테고리의 다른 글
크롤링에서 POST 요청이 필요한 경우 (0) | 2022.09.24 |
---|---|
네이버 금융 크롤링 (1) | 2022.09.24 |
쿠팡 상품 크롤링 (0) | 2022.09.20 |
네이버 뉴스 크롤링 (0) | 2022.09.18 |
HTTP 통신과 라이브러리 (0) | 2022.04.05 |
댓글
이 글 공유하기
다른 글
-
크롤링에서 POST 요청이 필요한 경우
크롤링에서 POST 요청이 필요한 경우
2022.09.24 -
네이버 금융 크롤링
네이버 금융 크롤링
2022.09.24 -
쿠팡 상품 크롤링
쿠팡 상품 크롤링
2022.09.20 -
네이버 뉴스 크롤링
네이버 뉴스 크롤링
2022.09.18