- 수업 내용 리마인드 및 아카이빙 목적의 업로드

Q. 네이버 블로그에서 '특정 키워드(청년취업사관학교)'와 '날짜 범위(20240101~20240731)'에 해당하는 게시물들을 자동으로 수집하고, 각 게시물의 "제목", "작성자 닉네임", "작성일", "본문 내용", "URL"을 추출하여 CSV 파일로 저장하는 코드를 작성하세요.
청년취업사관학교 : 네이버 블로그검색
'청년취업사관학교'의 네이버 블로그검색 결과입니다.
search.naver.com
A. 네이버 블로그 데이터 수집 스크립트
전체 코드
import requests
from bs4 import BeautifulSoup
import pandas as pd
import json
def clean_text(text):
return text.replace("\n", "").replace("\u200b", "").replace("\xa0", "").replace("\t", "").replace("\r", "")
def get_blog_item(url):
tmp = url.split("/")
url = f'https://blog.naver.com/PostView.naver?blogId={tmp[-2]}&logNo={tmp[-1]}'
try:
res = requests.get(url)
res.raise_for_status()
except requests.exceptions.RequestException as e:
print(f"Failed to retrieve blog post: {url}, error: {e}")
return None
nick = tmp[-2]
soup = BeautifulSoup(res.text, "html.parser")
try:
if soup.select_one(".se-title-text"):
title = soup.select_one(".se-title-text").text
date = soup.select_one(".se_publishDate").text
content = soup.select_one(".se-main-container").text
else:
title = soup.select_one(".se_title h3").text
date = soup.select_one(".se_publishDate").text
content = soup.select(".se_component_wrap")[1].text
title = clean_text(title)
content = clean_text(content)
return title, nick, date, content, url
except AttributeError as e:
print(f"Failed to parse blog post: {url}, error: {e}")
return None
def get_naver_blog(keyword, startdate, enddate, to_csv=False):
url = f'https://s.search.naver.com/p/review/48/search.naver?ssc=tab.blog.all&api_type=8&query={keyword}&start=1&nx_search_query=&nx_and_query=&nx_sub_query=&ac=1&aq=0&spq=0&sm=tab_opt&nso=so%3Add%2Cp%3Afrom{startdate}to{enddate}&prank=30&ngn_country=KR&lgl_rcode=09170128&fgn_region=&fgn_city=&lgl_lat=37.5278&lgl_long=126.9602&enlu_query=IggCADqCULhpAAAAj0RP67RmqTWRq3DkdYxhcV7F5RKpJAPG1d9ZSyMVgoc%3D&abt=&retry_count=0'
ret = []
while url:
try:
res = requests.get(url)
res.raise_for_status()
res_dic = json.loads(res.text)
except requests.exceptions.RequestException as e:
print(f"Failed to retrieve search results: {url}, error: {e}")
break
except json.JSONDecodeError as e:
print(f"Failed to parse JSON: {url}, error: {e}")
break
soup = BeautifulSoup(res_dic.get('contents', ''), 'html.parser')
url = res_dic.get('nextUrl')
for item in soup.select('.title_area > a'):
try:
blog_data = get_blog_item(item['href'])
if blog_data:
ret.append(blog_data)
except Exception as e:
print(f"Failed to process blog item: {item['href']}, error: {e}")
if not url:
break
df = pd.DataFrame(ret, columns=['title', 'nick', 'date', 'content', 'url'])
if to_csv:
df.to_csv(f'blog_{keyword}_{startdate}_{enddate}.csv', index=False)
get_naver_blog('청년취업사관학교', '20240101', '20240731', to_csv=True)
코드 설명
1. 필요한 모듈 임포트
import requests
from bs4 import BeautifulSoup
import pandas as pd
import json
- requests: 웹 페이지의 내용을 가져오기 위해 사용됩니다.
- BeautifulSoup: HTML 파싱을 위해 사용되는 라이브러리입니다.
- pandas: 데이터를 구조화된 형태(예: DataFrame)로 관리하고, CSV 파일로 저장하기 위해 사용됩니다.
- json: JSON 형식의 데이터를 다루기 위해 사용됩니다.
2. 텍스트 정리 함수 (clean_text)
def clean_text(text):
return text.replace("\n", "").replace("\u200b", "").replace("\xa0", "").replace("\t", "").replace("\r", "")
- 이 함수는 텍스트에서 불필요한 공백 문자나 특수 문자를 제거하여 텍스트를 깔끔하게 정리합니다.
3. 블로그 게시물 정보 추출 함수 (get_blog_item)
def get_blog_item(url):
tmp = url.split("/")
url = f'https://blog.naver.com/PostView.naver?blogId={tmp[-2]}&logNo={tmp[-1]}'
try:
res = requests.get(url)
res.raise_for_status()
except requests.exceptions.RequestException as e:
print(f"Failed to retrieve blog post: {url}, error: {e}")
return None
- url.split("/"): 블로그 URL을 슬래시(/)를 기준으로 나눕니다.
- f'https://blog.naver.com/PostView.naver?blogId={tmp[-2]}&logNo={tmp[-1]}': 네이버 블로그의 포스트 뷰 URL 형식에 맞게 새로운 URL을 생성합니다.
- requests.get(url): 블로그 게시물의 HTML 페이지를 요청합니다.
- res.raise_for_status(): 요청이 성공적이지 않으면 예외를 발생시킵니다.
nick = tmp[-2]
soup = BeautifulSoup(res.text, "html.parser")
- nick = tmp[-2]: 블로그 작성자의 닉네임을 추출합니다.
- BeautifulSoup(res.text, "html.parser"): HTML 문서를 파싱하여 soup 객체로 만듭니다.
try:
if soup.select_one(".se-title-text"):
title = soup.select_one(".se-title-text").text
date = soup.select_one(".se_publishDate").text
content = soup.select_one(".se-main-container").text
else:
title = soup.select_one(".se_title h3").text
date = soup.select_one(".se_publishDate").text
content = soup.select(".se_component_wrap")[1].text
- 블로그 게시물의 제목, 작성일자, 내용이 위치하는 HTML 태그를 선택합니다. 두 가지 형식이 존재할 수 있어 조건문으로 분기 처리합니다.
title = clean_text(title)
content = clean_text(content)
return title, nick, date, content, url
except AttributeError as e:
print(f"Failed to parse blog post: {url}, error: {e}")
return None
- clean_text 함수를 사용해 텍스트를 정리한 후, 제목, 작성자, 작성일, 내용, URL을 반환합니다.
- 만약 필요한 정보를 찾지 못하면 AttributeError 예외를 처리하고 None을 반환합니다.
4. 네이버 블로그 검색 결과 가져오기 (get_naver_blog)
def get_naver_blog(keyword, startdate, enddate, to_csv=False):
url = f'https://s.search.naver.com/p/review/48/search.naver?ssc=tab.blog.all&api_type=8&query={keyword}&start=1&nx_search_query=&nx_and_query=&nx_sub_query=&ac=1&aq=0&spq=0&sm=tab_opt&nso=so%3Add%2Cp%3Afrom{startdate}to{enddate}&prank=30&ngn_country=KR&lgl_rcode=09170128&fgn_region=&fgn_city=&lgl_lat=37.5278&lgl_long=126.9602&enlu_query=IggCADqCULhpAAAAj0RP67RmqTWRq3DkdYxhcV7F5RKpJAPG1d9ZSyMVgoc%3D&abt=&retry_count=0'
- 네이버 블로그 검색 URL을 생성합니다. 검색어와 시작일, 종료일을 포함한 URL을 만듭니다.
ret = []
while url:
try:
res = requests.get(url)
res.raise_for_status()
res_dic = json.loads(res.text)
except requests.exceptions.RequestException as e:
print(f"Failed to retrieve search results: {url}, error: {e}")
break
except json.JSONDecodeError as e:
print(f"Failed to parse JSON: {url}, error: {e}")
break
- 블로그 검색 결과를 가져와 JSON으로 파싱합니다. 요청에 실패하거나 JSON 파싱에 실패하면 반복을 중단합니다.
soup = BeautifulSoup(res_dic.get('contents', ''), 'html.parser')
url = res_dic.get('nextUrl')
- 검색 결과에서 블로그 게시물 링크를 추출할 수 있도록 HTML을 파싱합니다. 다음 페이지가 있으면 nextUrl을 업데이트합니다.
for item in soup.select('.title_area > a'):
try:
blog_data = get_blog_item(item['href'])
if blog_data:
ret.append(blog_data)
except Exception as e:
print(f"Failed to process blog item: {item['href']}, error: {e}")
- 각 블로그 게시물의 링크를 순회하며 get_blog_item 함수를 사용해 게시물 정보를 가져옵니다. 가져온 정보는 ret 리스트에 추가됩니다.
if not url:
break
- 더 이상 검색 결과가 없으면 반복을 종료합니다.
5. 데이터프레임 생성 및 CSV 저장
df = pd.DataFrame(ret, columns=['title', 'nick', 'date', 'content', 'url'])
if to_csv:
df.to_csv(f'blog_{keyword}_{startdate}_{enddate}.csv', index=False)
- 수집한 블로그 데이터를 pandas.DataFrame으로 구조화합니다.
- to_csv가 True로 설정되면, 데이터프레임을 CSV 파일로 저장합니다.
6. 함수 호출
get_naver_blog('청년취업사관학교', '20240101', '20240731', to_csv=True)
- 키워드 "청년취업사관학교"에 대해 2024년 1월 1일부터 2024년 7월 31일까지의 블로그 게시물을 수집하고, 결과를 CSV 파일로 저장합니다.
'+ 개발' 카테고리의 다른 글
뉴스 크롤링(#네이버 뉴스)_코드 설명 (0) | 2024.08.31 |
---|---|
논문 리뷰(#텍스트 마이닝 #금통위 의사록 분석)_Gen.AI (3) | 2024.08.30 |
Pandas로 데이터 분석하기 (0) | 2024.08.29 |
Numpy로 데이터 처리하기 (1) | 2024.08.28 |
데이터 시각화 기초 (1) | 2024.08.26 |