먼저 해당 포스팅은 앞전의 크롤링 개념 포스팅을 먼저 보고 오는 것을 추천한다.
2024.03.11 - [python] - [크롤링] 웹 크롤링에 대한 기초 지식을 알아보자!
크롤링에 대한 개념이 제대로 확립되지 않은 채로 진행하면 파이널 프로젝트를 진행할 때의 나처럼 방향성을 잡기가 매우 어려울 것이다.
2023.11.06 - [프로젝트] - [selenium] 웹 크롤링으로 장소와 주소 긁어서 엑셀로 저장하기 (url 안변할때 쓰는 방법)
이번 포스팅도 마찬가지로 해당 앞전 포스팅에서 참고한 강의를 따라 실습을 진행했음을 알린다.
메타코드의 웹 크롤링 기초 강의로 오늘까지 무료로 수강가능하니 늦기전에 들어보길 바란다!
뉴스 기사 크롤링하기
HTML 소스 따는 방법
먼저 전체 카테고리의 오늘 날짜의 제일 상단 뉴스를 눌러서 같이 진행해보고자 한다.
캡쳐본을 보면 크롤링을 경험해보거나, HTML 코드를 통해 이미지를 수집했던 사람들이라면 모두 아는 내용일거라 생각한다.
페이지 검사를 눌러 HTML 소스들을 확인할 수 있고, 위와 같은 것을 처음 따라해보는 사람들을 위해 제목 부분에 코드가 함께 뜨면서 블록 처리된 것을 설명해보자면 페이지 검사에서 뜨는 Elements 옆의 화살표 부분을 누르고 원하는 글자나 이미지를 클릭하면 다음과 같이 되니 한번 해보길 바란다.
시작 코드
먼저 뉴스를 크롤링하기 위해 새로운 ipynb을 생성해준다.
그리고 requests와 BeautifulSoup 라이브러리를 import 해준다.
라이브러리까지 세팅이 완료되었다면, 원하는 뉴스 기사를 클릭해 해당 주소를 복사해오고, 이를 url에 담아준다.
그리고 이 url의 text를 html_doc에 담아주겠다고 설정하면 기본 세팅은 끝났다!
다음으로 해야할 부분은 우리가 수집하고자 하는 부분이 어떤 태그에 담겨있는지를 파악해야한다.
그전에 미리 해두어야 할 부분이 하나 있는데, 현재는 html_doc에 html 코드가 모두 담겨있지만, 위의 사진처럼 정렬이 된 상태가 아니다.
그렇기 때문에 이 부분을 우리가 쉽게 알아보고자 BeautifulSoup을 사용해서 정렬된 상태로 볼 수 있도록 코드를 작성해주자.
soup = BeautifulSoup(html_doc, 'html.parser')
soup
추출해서 저장하기
title1 = soup.find('h4', class_ = 'headline-title')
body1 = soup.find('div', class_ = 'detail-body font-size')
# 딕셔너리 데이터 구조에 저희가 원하는 데이터를 담습니다.
data = {'뉴스 url' : [url], '제목' : [title1.text], '내용' : [body1.text]}
# 저희가 만든 데이터를 데이터프레임 구조로 만듭니다.
df = pd.DataFrame(data)
# CSV 파일로 저장합니다.
df.to_csv('news1_kbs_index_False.csv', index = False)
df.to_csv('news1_kbs_index_True.csv', index = True)
위의 코드와 같이 뉴스 제목을 추출하고, 기사 내용을 따로 추출해서 객체에 담아준다.
그리고 해당 뉴스의 url과 제목 부분의 text와 기사 내용 부분의 text를 딕셔너리 구조로 묶어주고, 이를 pandas 데이터 프레임으로 생성해서 표 형식으로 보기 쉽게 만들어 준다.
여기서 index를 T/F로 따로 한 이유는 저장이 어떻게 되는지를 보기 위한 예시이다.
2개 이상의 기사 크롤링
이제 앞전엔 하나의 기사를 csv 파일로 담아오는 것을 해봤으니, 이제는 다수의 기사를 크롤링해올 차례이다.
먼저 url, 타이틀, 내용별로 각각 리스트를 생성해주고, 앞전에 작업한 코드에는 1번째 기사라는 의미고 1을 붙여주자.
그리고 다음 기사를 눌러서 같은 과정을 반복해주는데, 이 때 title이나 body의 class가 동일한 것을 알 수 있다.
여러개를 담기 위해서는 아까 만들었던 리스트에 append를 붙여서 하나씩 넣어 확장시켜줘야 한다.
저장한 csv 파일을 확인해보면 위의 사진과 같이 나온다.
이 때, 내용에 원하는 기사 내용만 나오지 않고 코드가 나왔는데 우리가 위에서 원하는 코드에 text를 붙이지 않았기 때문이다.
따라서 위의 코드를 아래와 같이 수정해서 한다면 타이틀과 내용이 텍스트로 추출되어 우리가 원하는 결과 형식으로 반환될 것이다.
url_list = []
title_list = []
body_list = []
url1 = 'https://news.kbs.co.kr/news/pc/view/view.do?ncd=7910449'
html_doc1 = requests.get(url1).text
soup1 = BeautifulSoup(html_doc1, 'html.parser')
title1 = soup1.find('h4', class_ = 'headline-title').text
body1 = soup1.find('div', class_ = 'detail-body font-size').text
url_list.append(url1)
title_list.append(title1)
body_list.append(body1)
url2 = 'https://news.kbs.co.kr/news/pc/view/view.do?ncd=7910446'
html_doc2 = requests.get(url2).text
soup2 = BeautifulSoup(html_doc2, 'html.parser')
title2 = soup2.find('h4', class_ = 'headline-title').text
body2 = soup2.find('div', class_ = 'detail-body font-size').text
url_list.append(url2)
title_list.append(title2)
body_list.append(body2)
data12 = {'뉴스 url' : url_list, '제목' : title_list, '내용' : body_list}
df12 = pd.DataFrame(data12)
df12.to_csv('news12_kbs.csv', index = False)
코드 자동화
위처럼 2개면 크게 상관없겠지만, 다수의 url을 가지고 하게되면 일일이 코드를 치는 것은 시간낭비일 것이다.
이를 위해 링크만 주어지면 같은 형식을 띄고 있기에 자동으로 돌릴 수 있는 코드를 작성해서 하면 훨씬 효율적이게 된다.
위의 사진과 같이 for 반복문을 통해서 한번의 코드로 짠다면, 훨씬 간편하고 헷갈리지 않게 처리할 수 있다.
url_list = []
title_list = []
body_list = []
urls = ['https://news.kbs.co.kr/news/pc/view/view.do?ncd=7910449'
,'https://news.kbs.co.kr/news/pc/view/view.do?ncd=7910446'
]
for url in urls:
html_doc = requests.get(url).text
soup = BeautifulSoup(html_doc, 'html.parser')
title = soup.find('h4', class_ = 'headline-title').text
body = soup.find('div', class_ = 'detail-body font-size').text
url_list.append(url)
title_list.append(title)
body_list.append(body)
data = {'뉴스 url' : url_list, '제목' : title_list, '내용' : body_list}
df = pd.DataFrame(data)
df.to_csv('news12_kbs_same.csv', index=False)
날짜 인기 뉴스들 크롤링하기
데이터가 담기지 않을 때
데이터가 담기지 않은 상황 이전의 코드는 앞서 계속해온 기본코드뿐이라 설명없이 아래에 코드블록을 통해 남겨두겠다.
import requests
from bs4 import BeautifulSoup
import pandas as pd
url = 'https://news.kbs.co.kr/news/pc/category/category.do?ref=pSiteMap#20240311&1'
html_doc = requests.get(url).text
soup = BeautifulSoup(html_doc, 'html.parser')
box_contents = soup.find_all('a', class_ = 'box-content flex-style')
box_contents
코드는 다음과 같은 상황인데 box_contents 라는 리스트에 아무것도 담기지 않은 상황이 나왔다.
데이터가 담겨있지 않을 때는 먼저 태그명과 클래스 명이 같은지를 먼저 확인해봐야하는데 우리는 같은 상황이다.
이럴 때, 동적 뷰를 통한 페이지 로드가 이루어지는 자바스크립트를 통해 페이지가 생성된 것인지를 파악해야한다.
JS를 통해 만들어진 페이지일 경우 우리가 크롤링을 하는 것이 페이지가 로드되는 것보다 빠르게 접근되기 때문에 이런 상황이 초래되기도 한다.
알아보기 쉽게 따로 아래에 작성해두겠다.
Selenium 활용하기
셀레니움의 경우 앞전의 상황과 같이 동적인 페이지에서도 사용이 가능하다는 장점이 있기 때문에 자주 사용된다.
셀레니움은 주로 크롬의 웹드라이버와 함께 사용하며, 웹드라이버는 자동업데이트가 안되서 업데이트가 될 때마다 다운을 다시 받아야 하는 단점을 웹드라이버 매니저가 보완해준다.
위에서는 계속 Beautifulsoup을 사용했었던 예시를 다뤘기에 셀레니움은 크롬 드라이버와 함께 다운에 대해서만 살짝 언급하고 다음 포스팅에서 계속해서 작성해보겠다.
'데이터' 카테고리의 다른 글
[크롤링] 웹 크롤링 kbs 뉴스 데이터로 직접 해보자! (Selenium 활용) + 다음페이지 이동기능 및 RSS (0) | 2024.03.11 |
---|---|
[크롤링] 웹 크롤링 kbs 뉴스 데이터로 직접 해보자! (Selenium 활용) + Trouble Shooting (1) | 2024.03.11 |
[크롤링] 웹 크롤링에 대한 기초 지식을 알아보자! (0) | 2024.03.11 |
[NLP] 딥러닝 자연어 처리 입문 개별 스터디 - 상편 (5) | 2024.01.27 |
[데이터 분석] 딥러닝 합성곱에 대해 알아보자 (0) | 2023.08.28 |