Google 이미지 크롤러

minsoo jeong·2021년 1월 27일
1

이미지 크롤러 - Google

Selenium을 이용한 웹페이지 파싱

  • Naver와 동일한 방법으로 크롤링을 구현하였다. Naver와 달리 element의 naming이 식별 불가능하다.
[Google] 스크롤
  • 구글의 이미지 검색 결과는 스크롤 중간에 결과 더보기 버튼이 있으며 모든 검색결과가 디스플레이되면 하단에 '더 이상 표시할 콘텐츠가 없습니다.' 라는 안내 메세지가 나타난다. 이를 이용하여 스크롤을 구현하였다.

fdef infinite_scroll_down(driver, wait=.5):
    body = driver.find_element_by_tag_name('body')
    # more result btn
    while driver.find_element(By.XPATH, '//input[@class="mye4qd"]').is_displayed() is False:
        body.send_keys(Keys.END)
        time.sleep(wait)
    driver.find_element(By.XPATH, '//input[@class="mye4qd"]').click()
    while driver.find_element(By.XPATH, '//div[@class="OuJzKb Bqq24e"]').text != '더 이상 표시할 콘텐츠가 없습니다.':
        body.send_keys(Keys.END)
        time.sleep(wait)
    body.send_keys(Keys.END)
[Google] 썸네일 이미지 가져오기
  • 2021.1.26 기준으로 구글 이미지 검색에서는 상위 20개의 검색결과는 base64 인코딩이미지를 제공하며 이후에는 자체 서버의 이미지 url 형식으로 썸네일이미지를 제공한다.
  • 이미지 element의 src 가 없는 경우에는 data-src에 썸네일 URL이 있으며 스크롤에 따라 src에 URL이 복사되는 것을 확인하였다. 크롤러는 굳이 이 과정을 기다릴 필요가 없기 때문에 src 혹은 data-src를 확인하여 썸네일의 URL을 얻을 수 있다. 하지만 get_attrubute()를 호출하는 시점에 따라 element의 상태가 다를 수 있기 때문에 반복검사를 수행하도록 구현하였다.
def get_thumbnail_urls(driver, wait=.1, retry=3):
    imgs = driver.find_elements(By.XPATH, '//img[@class="rg_i Q4LuWd"]')
    urls = []
    for img in imgs:
        count = retry
        while count:
            src = img.get_attribute('src')
            if src is None:
                src = img.get_attribute('data-src')
            if src is not None:
                urls += [src]
                break
            count -= 1
            time.sleep(wait)

    print(f'{len(urls)}/{len(imgs)} images are loaded')
    return urls
[Google] 원본 이미지 가져오기
  • 2021.1.26 기준으로 구글 이미지 검색은 질의어에 대한 검색 결과들의 썸네일을 리스트업하고 썸네일 클릭시 우측에 원본 이미지와 유사 이미지를 제공한다.
  • 원본과 썸네일 이미지는 다른 리소스이기 때문에 썸네일을 각각 클릭하여 원본의 url을 얻어야한다.
  • 원본이미지의 로드가 완료되기 전까지는 원본의 url을 얻을 수 없고 동작이 완료되면 progress 바의 style 속성에 display: none이 설정된다.

def get_image_urls(driver, wait=.1, retry=3):
    def check_loaded():
       loading_bar = driver.find_element(By.XPATH,
                                         '//div[@class="tvh9oe BIB1wf"]//div[@class="k7O2sd"]')       
       return loading_bar.get_attribute('style') == 'display: none;'

    body = driver.find_element_by_tag_name('body')
    body.send_keys(Keys.HOME)

    imgs = driver.find_elements_by_xpath('//img[@class="rg_i Q4LuWd"]')

    urls = []
    for n, img in enumerate(imgs):
        if n == 0:
            img.click()

        count = retry
        while count and not check_loaded():
            time.sleep(wait)
            count -= 1

        if check_loaded():
            xpath = '//div[@class="tvh9oe BIB1wf"]//img[@class="n3VNCb"]'
            urls.append(driver.find_element_by_xpath(xpath).get_attribute('src'))
        driver.find_element_by_xpath('//div[@class="tvh9oe BIB1wf"]//a[@class="gvi3cf"]').click()
    print(f'{len(urls)}/{len(imgs)} images are loaded')
    return urls
[Google] ToDo
  • 클릭시 나타나는 우측의 유사 이미지 검색결과를 이용하여 더 많은 관련 이미지를 얻을 수 있다.
  • URL 주소를 이용한 중복 제거의 개선 방법

0개의 댓글