진행 중인 프로젝트에서 음식 이미지를 사용할 일이 있어서 이미지 크롤링에 대해 찾아보기 시작했다.
여러 사이트를 뒤져봤는데, 그 중 네이버 이미지에는 CCL 상업적 이용 가능 옵션이 있어서 보다 안전하게 프로젝트에 사용할 수 있지 않을까 싶어서 네이버에서 크롤링을 하기로 했다.
구글링을 열심히 해서 여러 크롤링 코드들을 참고했지만, 실제로 잘 동작하지 않아서.... 직접 참고한 몇몇 코드를 따와서 재구성해보았다.
일단 beatifulsoup으로 크롤링을 시도했을 때는 특정 태그부터는 parser가 접근을 하지 못해서 (해당 태그에 dataGroupKey 같은 인증 관련된 부분이 있었는데 이 문제인듯 싶다...) selenium을 통해 구현하기로 했다.
selenium 설치
우선 selenium 사용을 위해 터미널에 다음 명령어를 입력해준다.
pip install selenium
chrome driver 설치
다음은 google Chrome Driver를 설치해 주어야 한다.
https://sites.google.com/a/chromium.org/chromedriver/downloads
이 사이트에 들어가서 자신의 chrome과 맞는 버전을 다운받아야 한다.
+) chrome 버전은 chrome 브라우저 오른쪽 끝에 더보기 -> 도움말 -> Chrome 정보를 통해 확인할 수 있다.
설치를 완료했으면 자신의 PATH 디렉토리 하위에 chromedriver을 위치시킨다. 이렇게 하면 이후 다양한 프로젝트에서 드라이버를 호출할 때 유용하기에 권장하는 방법이다.
나의 경우는 python, pip 등의 명령어가 모여있는 /usr/local/bin 디렉토리로 chromedriver를 이동시켰다.
sudo mv {.../chromdriver} /usr/local/bin # 설치한 chromedriver 경로 -> /usr/local/bin
여기까지 진행했으면 기본 세팅은 끝났다.
코드
<전체 코드>
from selenium import webdriver
from urllib.parse import quote_plus
from urllib.request import urlopen
import os
def save_images(images, save_path):
for index, image in enumerate(images[:10]): # images[:크롤링하고 싶은 사진 개수]
src = image.get_attribute('src')
t = urlopen(src).read()
file = open(os.path.join(save_path, str(index + 1) + ".jpg"), "wb")
file.write(t)
print("img save " + save_path + str(index + 1) + ".jpg")
def create_folder_if_not_exists(directory):
try:
if not os.path.exists(directory):
os.makedirs(directory)
except OSError:
print('Error: Creating directory. ' + directory)
def make_url(search_term):
# 네이버 이미지 검색
base_url = 'https://search.naver.com/search.naver?where=image§ion=image&query='
# CCL 상업적 이용 가능 옵션
end_url = '&res_fr=0&res_to=0&sm=tab_opt&color=&ccl=2' \
'&nso=so%3Ar%2Ca%3Aall%2Cp%3Aall&recent=0&datetype=0&startdate=0&enddate=0&gif=0&optStr=&nso_open=1'
return base_url + quote_plus(search_term) + end_url
def crawl_images(search_term):
# URL 생성
url = make_url(search_term)
# chrome 브라우저 열기
browser = webdriver.Chrome('chromedriver')
browser.implicitly_wait(3) # 브라우저를 오픈할 때 시간간격을 준다.
browser.get(url)
# 이미지 긁어오기
images = browser.find_elements_by_class_name("_image")
# 저장 경로 설정
save_path = "/Users/danuri/Desktop/images/" + search_term + "/"
create_folder_if_not_exists(save_path)
# 이미지 저장
save_images(images, save_path)
# 마무리
print(search_term + " 저장 성공")
browser.close()
if __name__ == '__main__':
crawl_images(input('원하는 검색어: '))
함수로 분리해서 그렇지 복잡한 코드는 아니다. 아래서부터 위로 올라가면서 알아보자.
<main>
if __name__ == '__main__':
crawl_images(input('원하는 검색어: '))
프로그램 시작 시 원하는 검색어를 입력해서 이미지 크롤링을 시작한다.
<이미지 크롤링>
def crawl_images(search_term):
# URL 생성
url = make_url(search_term)
# chrome 브라우저 열기
browser = webdriver.Chrome('chromedriver')
browser.implicitly_wait(3) # 브라우저를 오픈할 때 시간간격을 준다.
browser.get(url)
# 이미지 긁어오기
images = browser.find_elements_by_class_name("_image")
# 저장 경로 설정
save_path = "/Users/danuri/Desktop/images/" + search_term + "/"
create_folder_if_not_exists(save_path)
# 이미지 저장
save_images(images, save_path)
# 마무리
print(search_term + " 저장 성공")
browser.close()
이미지를 크롤링하는 중심 함수다. 위에서부터 알아보자.
1. URL 생성
url = make_url(search_term)
def make_url(search_term):
# 네이버 이미지 검색
base_url = 'https://search.naver.com/search.naver?where=image§ion=image&query='
# CCL 상업적 이용 가능 옵션
end_url = '&res_fr=0&res_to=0&sm=tab_opt&color=&ccl=2' \
'&nso=so%3Ar%2Ca%3Aall%2Cp%3Aall&recent=0&datetype=0&startdate=0&enddate=0&gif=0&optStr=&nso_open=1'
return base_url + quote_plus(search_term) + end_url
네이버 이미지 검색 URL + 검색어(search_term) + CCL 상업적 이용 가능 옵션을 이어서 크롤링하고자 하는 URL로서 사용한다.
2. chrome 브라우저 열기
browser = webdriver.Chrome('chromedriver')
browser.implicitly_wait(3) # 브라우저를 오픈할 때 시간간격을 준다.
browser.get(url)
- webdriver.Chrome('chromedriver'): 아까 설치한 chromedriver를 사용해 크롬 페이지를 연다.
- implicitly_wait(3): 브라우저를 오픈할 때 약간의 시간간격을 줘야 이미지가 크롤링된다. 실제로 해당 부분 코드를 지우면 브라우저가 열리자마자 닫힌다.
- get(url): chrome에서 해당 url로 접속한다.
3. 이미지 긁어오기
images = browser.find_elements_by_class_name("_image")
네이버 이미지 검색 페이지 HTML을 분석해보면 각 이미지들이 '_image' 클래스를 갖고 있다. 이를 전부 긁어온다.
4. 저장 경로 설정
save_path = "/Users/danuri/Desktop/images/" + search_term + "/"
create_folder_if_not_exists(save_path)
def create_folder_if_not_exists(directory):
try:
if not os.path.exists(directory):
os.makedirs(directory)
except OSError:
print('Error: Creating directory. ' + directory)
각자 원하는 저장 경로를 설정한다. 나는 '바탕화면/images/김치찌개' 로 검색어마다 'images/[검색어]' 디렉토리에 저장되도록 설정했다.
create_folder_if_not_exists는 해당 저장경로가 존재하지 않으면 생성해주는 함수다.
5. 이미지 저장
save_images(images, save_path)
def save_images(images, save_path):
for index, image in enumerate(images[:10]): # images[:크롤링하고 싶은 사진 개수]
src = image.get_attribute('src')
t = urlopen(src).read()
file = open(os.path.join(save_path, str(index + 1) + ".jpg"), "wb")
file.write(t)
print("img save " + save_path + str(index + 1) + ".jpg")
설정한 저장 경로(save_path)에 긁어온 이미지들(images)을 저장한다.
나는 검색어당 10장이면 충분해서 10장만 저장하도록 했다. (1.jpg ~ 10.jpg)
6. 마무리
print(search_term + " 저장 성공")
browser.close()
마지막으로 chrome 브라우저를 닫아준다.
<실행 결과>
원하는 검색어: 김치찌개
img save /Users/danuri/Desktop/images/김치찌개/1.jpg
img save /Users/danuri/Desktop/images/김치찌개/2.jpg
img save /Users/danuri/Desktop/images/김치찌개/3.jpg
img save /Users/danuri/Desktop/images/김치찌개/4.jpg
img save /Users/danuri/Desktop/images/김치찌개/5.jpg
img save /Users/danuri/Desktop/images/김치찌개/6.jpg
img save /Users/danuri/Desktop/images/김치찌개/7.jpg
img save /Users/danuri/Desktop/images/김치찌개/8.jpg
img save /Users/danuri/Desktop/images/김치찌개/9.jpg
img save /Users/danuri/Desktop/images/김치찌개/10.jpg
김치찌개 저장 성공
크롤링 성공!