Naver 이미지 크롤러

minsoo jeong·2021년 1월 27일
0

이미지 크롤러 - Naver

  • 공식적인 방법으로 어플리케이션을 등록을 통해 API를 사용할 수 있다.
import urllib.request
import json

client_id = "XXXXXX"
client_secret = "XXXXXX"
encText = urllib.parse.quote("아이유")

url = "https://openapi.naver.com/v1/search/image?query=" + encText + "&sort=sim&display=100"
request = urllib.request.Request(url)
request.add_header("X-Naver-Client-Id", client_id)
request.add_header("X-Naver-Client-Secret", client_secret)
response = urllib.request.urlopen(request)
rescode = response.getcode()
if (rescode == 200):
    response_body = response.read()
    response_json = json.loads(response_body.decode('utf-8'))
else:
    print("Error Code:" + rescode)
  • 웹드라이버를 이용한 방법에 비해 옛날 이미지가 많이 포함되어 있다.
  • 매우 빠른 검색 속도
  • 하루 25,000 쿼리 제한
  • 쿼리당 최대 1000개의 이미지 획득가능

Selenium을 이용한 웹페이지 파싱

  • Selenium 은 브라우저의 웹드라이버를 이용하여 웹사이트의 동작을 테스트한다. 따라서 현재 사용중인 브라우저 버전과 호환가능한 웹드라이버를 다운로드 받아야한다. 크롬 브라우저의 웹 드라이버는 link에서 다운로드할 수 있다.
  • Naver 검색창의 웹페이지 동작을 분석하고 아래의 웹드라이버의 동작을 구현하여 이미지 url을 가져올 수 있다.
1. 키워드 검색
2. 스크롤
3. img 태그에서 src 속성값 획득
4. url 중복 제거
  • 네이버 이미지 검색에서 더 이상 스크롤 할수 없는 경우 로딩창의 style 속성에 display가 'none'으로 설정된다.
  • <div class="photo_loading _spinner ._listSpinner" style="display: none;">

from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By

def infinite_scroll_down(driver, wait=.5):
    body = driver.find_element_by_tag_name('body')
    while True:
        body.send_keys(Keys.END)
        if driver.find_elements(By.XPATH, '//div[contains(@class,"photo_loading")]')[0].get_attribute('style') == '':
            time.sleep(wait)
        else:
            break
  • 2021.1.26 기준으로 네이버 이미지 검색에서는 스크롤 위치에 따라 썸네일이 로드되며 이전에는 src 속성에 empty 값(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)이 할당된다. 따라서 스크롤을 강제로 움직여 썸네일 이미지를 로드한 후 이미지의 url을 크롤링해야한다.
  • (수정) 이미지의 src가 empty인 경우 data-lazy-src 속성에 썸네일 url이 있기 때문에 굳이 강제로 스크롤 하지 않아도 된다. 하지만 get_attrubute()를 호출하는 시점에 따라 element의 상태가 다를 수 있기 때문에 반복검사를 수행하도록 구현하였다.
def get_thumbnail_urls(driver, wait=.1, retry=3):
    empty_src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
    urls = []
    imgs = driver.find_elements(By.XPATH, '//img[@class="_image _listImage"]')
    for img in imgs:
        count = retry
        while count:
            src = img.get_attribute('src')
            if src == empty_src:
                src = img.get_attribute('data-lazy-src')
            if src is not None and src != empty_src:
                urls += [src]
                break
            count -= 1
            time.sleep(wait)

    print(f'{len(urls)}/{len(imgs)} images are loaded')
    return urls
  • 2021.1.26 기준으로 네이버 이미지 검색은 질의어에 대한 검색 결과들의 썸네일을 리스트업하고 썸네일 클릭시 우측에 원본 이미지와 유사 이미지를 제공한다.
  • 원본과 썸네일 이미지는 사실 동일한 리소스임을 확인할 수 있다. 원본의 경우 https://search.pstatic.net/common/?src=xxxx%yyyy.jpg&type=sc960_832 와 같은 형식의 url을 얻을 수 있으며 썸네일은 https://search.pstatic.net/common/?src=xxxx%yyyy.jpg&&type=a340 와 같은 형식으로 썸네일 이미지가 따로 저장되어 있는 것이 아니라 호스팅 서버에서 동일한 이미지를 요청데이터에 따라 이미지 프로세싱하고 있음을 알 수 있다. 따라서 이전과 같은 방법으로 썸네일 주소를 획득하여 문자열 치환을 통해 원본을 얻을 수 있지만 직접 클릭을 통해 원본의 url을 얻는 방법으로 구현하였다.
  • 원본이미지가 완전히 로드되기 전까지는 썸네일 url을 제공한다.
def get_image_urls(driver, wait=.1, retry=3):
    
	def check_loaded(img):
        return False if img.get_attribute('src').endswith('type=a340') else True

    body = driver.find_element_by_tag_name('body')
    body.send_keys(Keys.HOME)
    imgs = driver.find_elements(By.XPATH, '//img[@class="_image _listImage"]')
    urls = []
    for n, img in enumerate(imgs):
        if n == 0:
            img.click()
        count = retry
        origin_img=driver.find_element(By.XPATH, '//div[@class="image _imageBox"]//img')
        while count and not check_loaded(origin_img):
            time.sleep(wait)
            count -= 1

        if check_loaded(origin_img):
            urls.append(origin_img.get_attribute('src'))

        body.send_keys(Keys.RIGHT)
    print(f'{len(urls)}/{len(imgs)} images are loaded')
    return urls
  • 썸네일 & 원본 모두 질의어에 대한 결과만 가져오고 있으며 최대 500개의 이미지를 얻을 수 있다. 클릭시 나타나는 우측의 유사 이미지 검색결과를 이용하여 더 많은 관련 이미지를 얻을 수 있다.
  • URL 주소를 이용한 중복 제거의 개선 방법

0개의 댓글