본문 바로가기

코딩/자연어 처리 프로젝트

[자연어 처리] 웹페이지 크롤링(1)

텍스트 마이닝 프로젝트를 위한 첫 단계인 데이터 수집 단계에서 python으로 크롤링을 진행했습니다.

 

beautifulsoup과 request 조합으로 크롤링을 할 수 있지만

약 3-4만개의 리뷰를 여러 페이지에서 크롤링 할 수 있도록 자동화하기 위해서

selenium 모듈을 사용했어요 !

 

*) selenium: 웹페이지 테스트 자동화용 모듈로, 개발/테스트용 드라이버(웹브라우저)를 사용하여 실제 사용자가 사용하는 것처럼 동작시킬 수 있음 (id, password 입력과 같이 검색창에 검색 키 전달, 버튼 클릭 etc..)

 

*) 실습전 확인사항

    1. selenium 모듈 설치 (아나콘다 navigator - environments - selenium 검색)

    2. 크롬 드라이버 다운로드 ( https://chromedriver.chromium.org/downloads )

 

 


 

- 필요한 모듈 및 패키지 라이브러리 import

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

from bs4 import BeautifulSoup

 

 

- 제품명 크롤링

selenium에서는 driver 객체에 특정 element를 가져오기 위한 함수들을 제공하고 있습니다.

 

  • find_element_by_tag_name
  • find_element_by_class_name
  • find_element_by_id
  • find_element_by_xpath
  • find_element_by_css_selector

위와 같은 함수에 찾고싶은 element의 tag나 class, id, xpath, css selector을 전달하면

해당되는 element를 반환하는데요,

element의 xpath, selector같은 것들은 개발자 도구를 들어가서 확인하실 수 있습니다.

 

  1. 개발자 도구의 좌측 상단 커서모양 버튼을 누르고 긁어오고자 하는 element를 클릭
  2. html에서 표시되는 element 위에서 우클릭 - Copy - 원하는 Copy 내용 선택
  3. 함수 입력값으로 사용 (ex: Copy XPath를 선택 - find_element_by_xpath() 의 입력값으로 전달)

 

#크롬 드라이버 설치 경로
chrome_driver = '설치 디렉토리 경로 입력'

#드라이버 객체 생성
driver = webdriver.Chrome(chrome_driver)

#get함수에 이동하고자 할 사이트 전달
url = 'https://www.oliveyoung.co.kr/store/goods/getGoodsDetail.do?goodsNo=A000000161782&dispCatNo=100000100010008&trackingCd=Cat100000100010008_MID#'
driver.get(url) 

prod_name = driver.find_element_by_xpath('//*[@id="Contents"]/div[2]/div[2]/div/p[2]')
print(prod_name.text)

driver.close()

 

element의 앞뒤 태그가 제거되고 안에 있는 text, 즉 제품명이 출력되는 것을 볼 수 있습니다.

 

 

- 리뷰 텍스트 크롤링

리뷰는 url 변수에 저장된 주소로 이동한 뒤, [리뷰]라는 버튼을 클릭해야 볼 수 있습니다.

따라서 driver로 브라우저를 연 후에 버튼을 클릭하는 이벤트를 수행하도록 해줍니다.

클릭도 마찬가지로 클릭할 element의 xpath를 복사해서 review_box 변수에 저장해놓고

review_box에서 .click() 메소드를 호출해줍니다.

 

driver = webdriver.Chrome(chrome_driver)

driver.get('https://www.oliveyoung.co.kr/store/goods/getGoodsDetail.do?goodsNo=A000000161782&dispCatNo=100000100010008&trackingCd=Cat100000100010008_MID#') 

review_box = driver.find_element_by_xpath('//*[@id="reviewInfo"]/a')
review_box.click()

 

그런데 앞선 제품명을 크롤링 했을 때와는 달리, 리뷰 텍스트에 해당하는 줄글을 크롤링하려고 하면

None으로 아무것도 크롤링 되지 않습니다.

왜냐하면 브라우저를 이용하면 요청이 한 번에 오는 게 아니기 때문에

원하는 element가 아직 로딩되지 않은 것일 수도 있기 때문입니다 !

따라서 WebDriverWait 객체를 이용해 해당 element가 로딩되기까지 대기하고

페이지에 담긴 소스를 그대로 사용해봅시다.

 

 

WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#gdasList > li:nth-child(1) > div.review_cont > div.txt_inner')))
  • WebDriverWait(드라이버 객체인 driver, 최대 10초간 대기)
  • .until(EC.presence_of_element_located): element가 로딩될 때까지 대기
  • By.CSS_SELECTOR: css selector를 이용해서 element 찾을 것
  • 어떤 element를 찾을지: 개발자 도구의 해당 element에서 우클릭-Copy-Copy selector

 

최대 10초동안 우리가 원하는 element가 로딩될 때까지 기다렸으므로

페이지의 html 소스를 src 변수에 저장하고 BeautifulSoup 객체를 만들어줍니다.

 

src = driver.page_source
soup2 = BeautifulSoup(src)

driver.close()

 

 

그런 다음 soup 객체에서 리뷰 텍스트에 해당하는 element를 가져와야 하는데,

이 때는 CSS를 이용해서 tag를 찾기 위해 .select_one() 함수를 사용합니다.

개발자 도구의 element에 우클릭 - Copy - Copy selector 을 함수의 입력값으로 전달합니다.

 

review = soup2.select_one('#gdasList > li:nth-child(1) > div.review_cont > div.txt_inner')
review.get_text()

 

select_one으로 가져온 값에서 앞뒤를 감싸는 태그는 제거하고

가운데의 value, 즉 text에 해당하는 부분만 가져오기 위해 .get_text() 함수를 사용합니다.

 

 

driver = webdriver.Chrome(chrome_driver)

driver.get(url) 

review_box = driver.find_element_by_xpath('//*[@id="reviewInfo"]/a')
review_box.click()

WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#gdasList > li:nth-child(1) > div.review_cont > div.txt_inner')))

src = driver.page_source
soup2 = BeautifulSoup(src)

driver.close()

review = soup2.select_one('#gdasList > li:nth-child(1) > div.review_cont > div.txt_inner')
review.get_text()

 

 

(전체코드)

반응형