이미지 크롤러 - 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 주소를 이용한 중복 제거의 개선 방법