selenium으로 스크롤 페이지 이미지 크롤링

코변·2022년 6월 7일
0

개발일지

목록 보기
28/41

오늘은 셀레니움으로 동적페이지에 접근해 이미지 크롤링을 했다. 그 이 후에는 이미지 벡터화 및 이미지 코사인유사도 검사를 통해서 추천 모델을 만들었다.

코드만 짜놓고 오류는 나지 않는지 잘 되어가고 있는지 중간에 확인만 해주면 되기때문에 오늘은 개인적으로 개념정리를 할 수 있는 시간이 있었다. 물론 블로그에 아직 올릴 정도는 아니지만 조만간 django ORM에 대해서 한 번 정리해볼 생각이다.

우선 selenium은 대표적 크롤링 라이브러리인 BeautifulSoup과는 달리 web-driver를 통해 클릭, 스크롤등을 통해 동적으로 화면을 제어할 수 있게 해준다.

내 작업환경은 코랩이므로 아래의 코드로 크롬 드라이버를 다운받아주고 pip 명령어를 통해 selenium을 다운받아준다.

!apt-get update 
!apt install chromium-chromedriver
!pip install --upgrade pip
!pip install selenium

그리고 나는 제어되고 있는 크롬의 화면을 볼 것도 아니고(--headless) 코랩은 GUI를 제공하지 않는 linux서버로 돌아가기 때문에 (--no-sandbox) 또 자세하게는 잘 모르겠지만 공유 메모리 사용을 막아(캐싱, dev/shm 폴더를 조회하는일) process가 느려지는 일을 방지하기 위해(--disable-dev-shm-usage) 다음과 같은 옵션을 추가해 웹드라이버를 불러와준다.

options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome('chromedriver',options=options)

내가 크롤링할 페이지는 스크롤을 하면 자동으로 다음 이미지가 계속해서 추가가 되는 사이트인데 이를 위해서 원하는 수준까지 스크롤해서 내려가 주는 함수를 구현했다.

driver.get('웹페이지 주소')
def scroll_to_bottom():
  last_height = driver.execute_script('return document.body.scrollHeight')

  while True:
    driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')

    time.sleep(0.6)

    new_height = driver.execute_script('return document.body.scrollHeight')

    if new_height >200000:
      break
    print(f'last_height = {last_height}')
    print(f'new_height = {new_height}')

    last_height = new_height

원래는 조건절에 if new_height == last_height라는 구문을 통해서 마지막 스크롤까지 내려가는 함수였지만 화면이 내 생각보다 어어어엄청나게 긴 탓에 위와 같은 조건으로 낮추어 크롤링을 진행했다.

base_dir = '/content/drive/MyDrive/images'
dict= {}
n = 0
for i in range(1, 1001):
  try:
    img = driver.find_element(By.XPATH,f'//*[@id="__layout"]/div/div[2]/div[5]/div/div[3]/div[1]/div[{str(i)}]/a/div[1]/picture/img')
    title = img.get_attribute('alt')
    src = img.get_attribute('src')
    image_path = os.path.join(base_dir,f'{n}.png')
    image = urllib.request.urlopen(src)
    image = Image.open(image)
    image.save(image_path)
    dict[n] = [title, src]
    n+=1
  except:
    print('fail')
    continue
driver.quit()

이미지가 어떤 확장자로 넘어올지 확신할 수 없는 상황이라(사실 그냥 urllib.request.urlretrieve에 screenshot을 활용해 저장을 한 번 했다가 image파일이 안열려서 다시 함) pillow를 통해 이미지를 열고 png파일로 다시 저장을 했다.

이렇게 1000장의 이미지를 크롤링을 통해 얻어냈고 이를 통해 추천시스템을 만들었지만 그건 페이지 및 시간관계상 내일 마무리 짓도록 하겠다.

profile
내 것인 줄 알았으나 받은 모든 것이 선물이었다.

0개의 댓글