프로젝트 중 네이버 검색 결과 60개의 각 링크를 크롤링해야하는 기능이 있어 화면에서 스크롤을 내리며 크롤링을 진행했다.
네이버 View의 경우 한번에 30개씩 검색결과를 보여준다.
그리고 스크롤을 내리면 계속해서 30개씩 불러와 결과를 보여주는 방식이다.
셀레니움에는 자바스크립트를 수행할 수 있는 코드가 있는데 이것을 활용하고자 한다.
1. 검색 화면 띄우기
네이버 View 중 블로그 카테고리의 검색결과만을 가져오도록 url을 설정한다.
그리고 검색 결과가 나올 때까지 5초까지 대기한다.
해당 코드의 일부
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
URL = 'https://search.naver.com/search.naver?query=' + query + '&nso=&where=blog&sm=tab_opt'
try :
#검색 결과가 나올 때까지 대기
WebDriverWait(driver, 5).until(
EC.presence_of_element_located((By.CLASS_NAME, 'thumb_single'))
)
except Exception as e :
print(e)
Explicitly wait
말 그대로 명시적 대기이다. 조건을 작성하고 해당 조건을 충족할때까지 기다려주는 방식이다.
웹페이지가 완전히 불러와질때까지 5초까지 대기하는데 이때 explicitly wait 방식을 사용하였다.
WebDriverWait(driver, 5).until()
WebDriverWait의 파라미터로 첫번째는 webDriver, 두번째는 기다릴 시간(sec 단위)를 작성한다.
until 내부에 찾고자 하는 element를 탐색하는 함수를 전달한다. 만일 element를 찾는다면 5초까지 기다리지 않고 다음 코드로 넘어간다.
element를 찾지 못하고 5초가 넘어가면 TimeoutException이 발생한다.
EC.presence_of_element_located((By.CLASS_NAME, 'thumb_single'))
WebDriverWait의 조건으로 위 코드를 작성하였다.
어떤 element가 존재하는지 여부를 확인하는 함수를 until 함수에 전달하게 된다.
위 코드에 따르면, 찾고자하는 요소는 'thumb_single'이라는 클래스 이름을 가지고 있다.
2. 화면 스크롤
화면이 출력되었다면 크롤링을 할 준비가 되었다.
네이버는 한 번에 30개씩 출력하기 때문에 만약 60개의 결과를 크롤링하고 싶다면 스크롤을 내려 30개를 추가로 받아와야 한다.
스크롤을 화면 끝까지 내리는 코드
driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
WebDriverWait(driver, 2).until(
lambda driver: len(driver.find_elements(By.CLASS_NAME, 'thumb_single')) == 원하는 개수
)
excute_script는 자바스크립트 코드를 수행하는 함수이다.
도큐먼트의 높이만큼 스크롤을 내리면 화면의 가장 하단에 도달한다.
하단에 도달한 후 검색결과를 가져오는 시간을 다시 explicitly wait 방식으로 기다려준다.
lambda driver: len(driver.find_elements(By.CLASS_NAME, 'thumb_single')) == 원하는 개수
until 함수에는 메소드를 파라미터로 전달해야 한다.
전달된 메소드는 until 함수 내에서 반복적으로 수행되며, 메소드 반환값이 존재하면 WebDriverWait을 중지한다.
따라서 element가 특정 개수만큼 존재하는지를 확인하기 위해서 위와 같은 람다함수를 작성한다.
find_elements 함수를 통해 element 전부를 받아온 후 이 개수가 원하는 개수인지를 확인하는 방식이다.
3. 원하는 요소 크롤링
스크롤을 내려 원하는 만큼 검색결과가 나왔다면 이제 원하는 요소를 크롤링한다.
프로젝트에서는 각 결과의 링크들을 크롤링하기 때문에 간단히 다음 코드로 크롤링을 진행했다.
result = driver.find_elements(By.CLASS_NAME, 'thumb_single')
for idx in range(len(result)):
element = result[idx]
try:
links.append(element.get_attribute("href"))
except Exception as e:
print("exception During link crawling")
print(e)
'Python' 카테고리의 다른 글
[Scrapy] Scrapy 튜토리얼2 - 네이버 검색 결과 크롤링(크롤러 설정) (0) | 2022.03.17 |
---|---|
[Scrapy] Scrapy 튜토리얼1 - Scrapy를 선택한 이유 (0) | 2022.03.17 |
[Python] string to Json (Json.loads()) 파싱 문제 (0) | 2022.03.10 |
[pandas] Dataframe append 속도 저하 문제 (0) | 2021.12.08 |
[OpenCV C++] 웹캠 크롭하기 (0) | 2020.11.11 |