이번 시간은 지난 포스팅 beautifulsoup을 활용하지 못했던 것을 이어 selenium으로 해보는 것을 이어서 작성하겠다.
2024.03.11 - [python] - [크롤링] 웹 크롤링 kbs 뉴스 데이터로 직접 해보자! (Beautifulsoup 활용)
마찬가지로 메타코드의 웹 크롤링 기초 강의를 활용해서 수강하고 있는 중이다.
JavaScript 페이지 크롤링 대응법
Selenium 활용하기
이전 포스팅을 참고하지 않은 분들을 위해 앞부분을 다시 가져와봤다.
셀레니움의 경우 앞전의 상황과 같이 동적인 페이지에서도 사용이 가능하다는 장점이 있기 때문에 자주 사용된다.
셀레니움은 주로 크롬의 웹드라이버와 함께 사용하며, 웹드라이버는 자동업데이트가 안되서 업데이트가 될 때마다 다운을 다시 받아야 하는 단점을 웹드라이버 매니저가 보완해준다.
웹드라이버로 url 열기
여기는 셀레니움의 라이브러리와 웹드라이버 매니저 라이브러리를 활용해 불러오는 것을 한 뒤,
우리가 열고자 하는 url 링크를 추가해서 웹 드라이버에서 해당 링크를 열리는지 확인하는 방법이다.
나는 왜인지 모르겠지만 셀레니움과 웹드라이버 매니저 모두 다운을 받았음에도 라이브러리를 불러오지 못해 한참을 헤맸다.
혹시라도 라이브러리를 불러오지 못한다는 오류가 뜨는 사람들은 vs code만 끄고 켜봐도 다시 작동될 것이다.
강의에서는 저 코드로 분명이 크롬 드라이버가 열린다.
근데 질문을 남긴 사람들은 모두 열리지 않았고, 나 역시 이 코드에서 오류가 났었다.
그래서 열심히 gpt 서칭해서 찾아낸 오류는 다음과 같다.
1. 서비스를 생성한 후 excutable_path를 사용해야한다. (즉, 한 코드에 작성할 수 없다.)
2. Service 객체는 크롬 드라이버를 설치하고 실행하기 위해서만 사용한다. (즉, 드라이버 설치 경로를 먼저 설정후 해야한다.)
3. excutable_path에 드라이버 설치 경로를 연결하는 방식이 되어야 한다. (= 1번과 같은말)
수정한 코드는 다음과 같다.
# Selenium으로 웹 드라이버 실행
driver_path = ChromeDriverManager().install()
service = Service(driver_path)
driver = webdriver.Chrome(executable_path=driver_path)
# url 전달
url = 'https://news.kbs.co.kr/news/pc/category/category.do?ref=pSiteMap#20240311&1'
driver.get(url)
# 기다려달라는 값 전달
wait = WebDriverWait(driver, 10)
# 드라이버 접근 > 페이지 소스 가져오기
html = driver.page_source
# 드라이버 종료
driver.quit()
Beautifulsoup과 연계해서 사용
위의 코드를 먼저 작성해서 웹드라이버가 정상적으로 열리는지를 확인해준다.
그리고 앞전에는 자바스크립트로 인해 페이지를 먼저 탐색해서 beautifulsoup을 사용할 수 없었는데,
다시 한번 사용해보면 이제는 우리가 원하는 a 태그를 모두 찾아낸 것을 알 수 있었다.
soup = BeautifulSoup(html, 'html.parser')
box_contents = soup.find_all('a', class_ = 'box-content flex-style')
box_contents
추출한 부분 확인
위의 결과를 통해 box_contents의 길이를 확인해서 몇개가 담겼는지 확인해보고, 두어개 확인을 해본다.
확인을 하는 이유는 태그와 클래스 명이 동일한지를 알아보기 위함이다.
우리는 태그명과 클래스명이 모두 동일한 것을 확인했고, 이를 통해 title은 기사 제목으로, news-text는 기사 내용으로, span 클래스명이 date인 곳은 날짜로 모두 모아보려 한다.
a 태그로 url 확인
box_contents에 담겨있는 a태그의 주소를 이용해서 url을 변경할 수 있도록 코드를 만들어 본다.
이 코드의 경우 각각의 url이 다르지만, 'http://news.kbs.co.kr' 이라는 앞부분은 동일하기 때문에 이 부분을 활용해서 url이라는 변수에 앞부분은 제시하고 뒷부분은 box_contents에 몇번째, 어떤 태그를 가져오라는 코드를 입력한다.
url = 'http://news.kbs.co.kr' + box_contents[0]['href']
url
나머지도 추출하기
위에서 url을 추출해왔으니, 이제는 남은 기사 제목, 내용, 날짜를 각각 추출해볼 시간이다.
위의 3가지를 각각 추출하는 방법은 동일하게 box_contents에서 원하는 순번을 입력하고,
찾아내야하니 find를 사용해서 해당하는 태그명을 먼저 입력하고, 뒤에 클래스 명을 입력해준다.
이때 우리는 코드를 얻고자 하는 것이 아니니 .text도 해주어야 한다.
title = box_contents[0].find('p', class_ = 'title').text
body = box_contents[0].find('p', class_ = 'news-text').text
date = box_contents[0].find('span', class_ = 'date').text
자동화로 리스트로 담기
이제 이전 포스팅에서 했던 것처럼 코드가 헷갈리지 않고 효율적으로 사용하기 위해 자동화를 시켜줄 것이다.
for 반복문을 사용해서 box_content라는 변수를 새로 만들어 box_contents에 담겨있는 것들을 순차적으로 각각 url, title, body, date에 담아주고, 이를 append 함수를 사용해서 리스트에 담아줘야 한다.
# 원하는 부분들만 찾아서, 리스트에 담고, 데이터 프레임으로 만들기
# 빈 리스트 만들기
url_list = []
title_list = []
body_list = []
date_list = []
for box_content in box_contents:
url = 'http://news.kbs.co.kr' + box_content['href']
title = box_content.find('p', class_ = 'title').text
body = box_content.find('p', class_ = 'news-text').text
date = box_content.find('span', class_ = 'date').text
url_list.append(url)
title_list.append(title)
body_list.append(body)
date_list.append(date)
데이터 저장하기
각 리스트에 담은 url, 기사 제목, 내용, 날짜를 하나의 데이터 프레임 형식으로 만들고자 한다.
데이터 프레임 형식으로 만드는 이유는 우리는 추출해낸 데이터를 활용해야하기 때문에 알아보기 쉽도록 표현할 필요가 있다.
그래서 크롤링을 할 때는 항상 pandas를 같이 import 해주는 것이 좋다.
# 데이터 저장
data = {'뉴스 url' : url_list, '제목' : title_list, '내용' : body_list, '날짜' : date_list}
df = pd.DataFrame(data)
df
csv 파일로 저장하기
다음과 같이 인덱스 없이 데이터를 csv 파일로 생성해보고자 한다.
앞에서 데이터 프레임으로 생성한 df를 활용해서 pandas 기능으로 csv로 변경할 것이다.
df.to_csv('news_kbs_box.csv', index=False)
나는 뭐가 문제인지 vs code를 활용해서는 한글로 잘 보이고 vs code에서 csv 파일을 열어도 한글로 보이는데, 엑셀로만 열면 파일 인코딩이 깨진 상태로 보인다.
이 부분은 따로 확인해봐야할 필요가 있을 듯 하다.
'데이터' 카테고리의 다른 글
[딥러닝] Tensorflow와 Pytorch 간단하게 비교해보기 (1) | 2024.09.05 |
---|---|
[크롤링] 웹 크롤링 kbs 뉴스 데이터로 직접 해보자! (Selenium 활용) + 다음페이지 이동기능 및 RSS (0) | 2024.03.11 |
[크롤링] 웹 크롤링 kbs 뉴스 데이터로 직접 해보자! (Beautifulsoup 활용) (0) | 2024.03.11 |
[크롤링] 웹 크롤링에 대한 기초 지식을 알아보자! (0) | 2024.03.11 |
[NLP] 딥러닝 자연어 처리 입문 개별 스터디 - 상편 (5) | 2024.01.27 |