python/data crawling
8. selenium (3) - webdriverWait
Abokadoh
2023. 2. 15. 15:17
selenium
을 활용하여 특정 element
의 로딩을 기다리고 데이터를 크롤링해보자
element
의 로딩을 기다린다는 말은 예를 들어 페이지가 완전히 Load되고 나서 정보를 긁어오고 싶을 때를 말한다.
ex) 뉴스의 댓글 수는 처음 페이지 요청시에 곧바로 불러지지 않는다. 이런 경우 로딩을 완전히 기다리고 데이터를 크롤링하는 방법을 사용해야 할 수 있다.
네이버 기사의 댓글 수를 추출해보겠다.
우선 네이버 기사의 html 문서를 크롤링해보자
chorme_drvier = '/Users/choehyeogjae/Desktop/chromedriver'
driver = webdriver.Chrome(chrome_drvier)
url = 'https://n.news.naver.com/mnews/article/081/0003018031?sid=105'
driver.get(url)
scr = driver.page_source # scr은 string 타입의 html문서임
코드를 실행하면 scr
객체에 str type
의 html 문서가 들어간다.
이것을 BeautifulSoup
을 사용하여 분석에 용이하게 만들어주자.
from bs4 import BeautifulSoup
soup = BeautifulSoup(scr)
개발자도구에서 확인한 댓글수는 span tag, class = u_cbox_count에 있므로 select_one
함수를 사용해보자
soup.select_one('span.u_cbox_count')
내가 원하는 텍스트값이 추출되지 않았다.
왜지?
그 이유는 댓글의 숫자 같은경우 우리가 처음에 url을 요청했을 때 바로 응답되는 데이터가 아닌 일정 시간(0.x초)후에 돌아오는 데이터이기 때문이다..
이런 경우 webdriverWait
를 사용하면 해결할 수 있다.
chrome_driver = '/Users/choehyeogjae/Desktop/chromedriver'
driver = webdriver.Chrome(chrome_driver)
url = 'https://news.naver.com/main/read.nhn?mode=LSD&mid=shm&sid1=105&oid=081&aid=0003018031'
driver.get(url)
myElem = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '.u_cbox_count')))
scr = driver.page_source
soup = BeautifulSoup(scr)
comment_area = soup.select_one('.u_cbox_count')
driver.close()
comment_area.get_text()
WebDriver(driver, 10)
WebDriverWait
을 통해driver
를 ‘최대’ 10초동안 기다린다.- 이 때 10초가 넘어가면 NoSuchElementException, ElementNotVisibleException 에러가 뜰 것이다.
until(EC.presence_of_element_located((By.CSS_SELECTOR, ‘.u_cbox_count’)))
- 언제까지? ; u_cbox_count를 css selector로 찾을 때까지~
- 이때 해당 element가 나오면
EC
가TRUE
를 리턴하는 것이다.
실습 ; 댓글 끌어오기
import requests
def get_daum_news_comments(news_id):
headers = {
'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJncmFudF90eXBlIjoiYWxleF9jcmVkZW50aWFscyIsInNjb3BlIjpbXSwiZXhwIjoxNTY0Njc4NjQ1LCJhdXRob3JpdGllcyI6WyJST0xFX0NMSUVOVCJdLCJqdGkiOiJlZGUxNzM0MS1hNWNjLTRmYmQtODJkMy0zZTMwOGMwMGViZTEiLCJjbGllbnRfaWQiOiIyNkJYQXZLbnk1V0Y1WjA5bHI1azc3WTgifQ.Cxs2g1hUUAjyuSrUDAhaKGol8vvyW-_mwPtV0X0DvEU',
'Origin': 'https://news.v.daum.net',
'Referer': 'https://news.v.daum.net/v/20190728165812603',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}
url_template = 'https://comment.daum.net/apis/v1/posts/@{}/comments?parentId=0&offset={}&limit=10&sort=RECOMMEND&isInitial=false'
offset = 0
comments = []
while True:
url = url_template.format(news_id, offset)
resp = requests.get(url, headers=headers)
data = resp.json()
if not data:
break
comments.extend(data)
offset += 10
return comments
len(get_daum_news_comments('20190728165812603'))