Growth Marketing/GM4

[TIL-260416] 멋쟁이사자처럼 그로스마케팅 4기 - 데이터분석 개론 day26 | 크롤링-xml, json

pamsyra 2026. 4. 16. 16:27
▼오늘 배운 사항들
1. 구글뉴스 크롤링(xml)
- beautifulsoup 사용
2. 네이버뉴스 크롤링(json)
- 딕셔너리 사용

Part 1. 크롤링 - 구글 뉴스 

[구글 뉴스 가져오기]

1. soup 변수에 beautifulsoup 만들고

2. 꺼내고 싶은 태그별로 변수지정해서 find("")로 꺼내기

3. search query로 꺼낼 키워드 설정

  • find() : 태그 꺼내오기
  • 변수.text : <>html 태그 없애고 싶으면 .text
  • 오답) soup.find로 새로할 필요없이 itme.find로 해야...
  • {search_query} : 키워드만 바꾸면 알아서 돌아갈 수 있게 만듬
  • quote _plus() : 한글 변

태그 꺼내보기
search query 변수 설정 - 키워드 대신 {}로 search querey 기입 - f"" 생성 후 quote plus로 한글 깨짐 방지

 

  • 반복문 활용해서 여러개 꺼내보기
#enumerate : 리스트 반복할 때 앞에 숫자를 만들어주는 명령, item의 [:10]번째까지 만들고, 시작은 1부터라는 함수
#idx는 숫자를 꺼내주는 함
for idx, item in enumerate(items[:10], start=1) :
  print(item)
  print(idx)
for item in items[:10] :
  print(item)
  # 타이틀, 링크, 발행일, 뉴스기사출처
  title = item.find("title").text
  link = item.find("link").text
  pub_date = item.find("pubDate").text
  source = item.find("source").text
  print(f"[{source}] : {title}, {pub_date}, {link}")

enumerate 사용 / 미사용

 

[처음부터 한 셀에 만들어보기]

#하나의 셀 안에 모든 코드 넣어보기
import requests
from bs4 import BeautifulSoup 
from urllib.parse import quote_plus #한글을 url에 넣을 수 있게

search_query = "축제" 

rss_url = f"https://news.google.com/rss/search?q={quote_plus(search_query)}&hl=ko&gl=KR&ceid=KR:ko"

#데이터 가져오기
response = requests.get(rss_url,headers= {"User-Agent" : "Mozila/5.0"} )

soup = BeautifulSoup(response.text, "xml")
items = soup.find_all("item")


for item in items[:100] :

  # 타이틀, 링크, 발행일, 뉴스기사출처
  title = item.find("title").text
  link = item.find("link").text
  pub_date = item.find("pubDate").text
  source = item.find("source").text
  print(f"[{source}] : {title}, {pub_date}, {link}")

 


CSV 파일로 저장하기

#CSV파일로 저장하기
import requests
from bs4 import BeautifulSoup 
from urllib.parse import quote_plus #한글을 url에 넣을 수 있게
import csv #csv에 담기 위한 함수
from google.colab import files #구글에서 파일 다운로드를 위한 함수
from datetime import datetime

search_query = "축제" 

rss_url = f"https://news.google.com/rss/search?q={quote_plus(search_query)}&hl=ko&gl=KR&ceid=KR:ko"

#데이터 가져오기
response = requests.get(rss_url,headers= {"User-Agent" : "Mozila/5.0"} )

soup = BeautifulSoup(response.text, "xml")
items = soup.find_all("item")

 

[CSV 파일 열어보기]

  1. 파일네임지정
  2. 파일 열기 with open
    - 파일명, 인코딩 
    - 첫번째 헤더 지정
  3. 파일 꺼내기
    - 열기 : for문 사용
    - 빈 값 처리 : if else 사용
    - 데이터 변환 : if , strptime / strftime
  4. 파일 열기
#csv 파일을 열어보자

file_name = f"news_{search_query}.csv"

#w는 파일 새로 만들어서 쓰는 코드, 기존에 있으면 덮어쓰기 
#newline은 줄바꿈 하지말기
with open(file_name, "w", newline="", encoding="utf-8-sig" ) as f: 
  writer = csv.writer(f) #request 심부름꾼 만든 것처럼 csv에 writer 만들어서 명령중 (f)은 file에 담는다
  writer.writerow(["제목", "언론사", "날짜", "링크"]) #시킬 행동 코드, 헤드 컬럼명
  
  for item in items[:10] :
    title = item.find("title").text if item.find("title") else "" #값이 없을 경우 빈칸으로 지정하는 코드
    link = item.find("link").text if item.find("link") else ""
    pub_date = item.find("pubDate").text if item.find("pubDate") else ""
    source = item.find("source").text if item.find("source") else ""

      #pubDate 날짜 변환하기
      #strptime : 문자열 -> 날짜
      #strftime : 날짜 -> 원하는 문자열로 재배치 
    if pub_date:
        pub_date = datetime.strptime(pub_date, "%a, %d %b %Y %H:%M:%S GMT" ) #(데이터, 어떤 형식인지 알려주기)
        pub_date = pub_date.strftime("%Y-%m-%d")       #재조합하기


      #csv 헤더 다음에 들어갈 내용 넣기
    writer.writerow([title, source, pub_date, link])
    print(f"{title}, {source}")

 

 

더보기

* search_query 변경해서 진행

import requests
from bs4 import BeautifulSoup 
from urllib.parse import quote_plus #한글을 url에 넣을 수 있게
import csv #csv에 담기 위한 함수
from google.colab import files #구글에서 파일 다운로드를 위한 함수
from datetime import datetime

search_query = "한국어교육" 

rss_url = f"https://news.google.com/rss/search?q={quote_plus(search_query)}&hl=ko&gl=KR&ceid=KR:ko"

#데이터 가져오기
response = requests.get(rss_url,headers= {"User-Agent" : "Mozila/5.0"} )

soup = BeautifulSoup(response.text, "xml")
items = soup.find_all("item")

#csv 파일을 열어보자
file_name = f"news_{search_query}.csv"

with open(file_name, "w", newline="", encoding="utf-8-sig" ) as f: 
  writer = csv.writer(f) #request 심부름꾼 만든 것처럼 csv에 writer 만들어서 명령중 (f)은 file에 담는다
  writer.writerow(["제목", "언론사", "날짜", "링크"]) #시킬 행동 코드, 헤드 컬럼명
  
  for item in items[:20] :
    title = item.find("title").text if item.find("title") else "" #값이 없을 경우 빈칸으로 지정하는 코드
    link = item.find("link").text if item.find("link") else ""
    pub_date = item.find("pubDate").text if item.find("pubDate") else ""
    source = item.find("source").text if item.find("source") else ""

      #pubDate 날짜 변환하기
      #strptime : 문자열 -> 날짜
      #strftime : 날짜 -> 원하는 문자열로 재배치 
    if pub_date:
        pub_date = datetime.strptime(pub_date, "%a, %d %b %Y %H:%M:%S GMT" ) #(데이터, 어떤 형식인지 알려주기)
        pub_date = pub_date.strftime("%Y-%m-%d")       #재조합하기


      #csv 헤더 다음에 들어갈 내용 넣기
    writer.writerow([title, source, pub_date, link])

files.download(file_name)

[데이터 프레임에 넣기]

- 방법 2가지 있음 : 리스트 / 딕셔너리

1. 리스트

더보기
#df 데이터프레임에 넣기 -리스트

import requests
from bs4 import BeautifulSoup 
from urllib.parse import quote_plus #한글을 url에 넣을 수 있게
from datetime import datetime
import pandas as pd

search_query = "한국어교육" 

rss_url = f"https://news.google.com/rss/search?q={quote_plus(search_query)}&hl=ko&gl=KR&ceid=KR:ko"

#데이터 가져오기

response = requests.get(rss_url,headers= {"User-Agent" : "Mozila/5.0"} )

soup = BeautifulSoup(response.text, "xml")
items = soup.find_all("item")

df_news = []

for item in items[:20] :
  title = item.find("title").text if item.find("title") else "" #값이 없을 경우 빈칸으로 지정하는 코드
  link = item.find("link").text if item.find("link") else ""
  pub_date = item.find("pubDate").text if item.find("pubDate") else ""
  source = item.find("source").text if item.find("source") else ""

    #pubDate 날짜 변환하기
  if pub_date:
      pub_date = datetime.strptime(pub_date, "%a, %d %b %Y %H:%M:%S GMT" ) #(데이터, 어떤 형식인지 알려주기)
      pub_date = pub_date.strftime("%Y-%m-%d")       #재조합하기
  
  df_news.append([title, source, pub_date, link])

print(df_news)

df_news_df = pd.DataFrame(df_news, columns=["제목", "언론사", "날짜", "링크"])
df_news_df 
#컬럼 순서만 잘 정해진다면 리스트로도 가능

2. 딕셔너리

더보기
#df 데이터프레임에 넣기 2번째 방법 - 딕셔너리

import requests
from bs4 import BeautifulSoup 
from urllib.parse import quote_plus #한글을 url에 넣을 수 있게
from datetime import datetime
import pandas as pd

search_query = "한국어교육" 

rss_url = f"https://news.google.com/rss/search?q={quote_plus(search_query)}&hl=ko&gl=KR&ceid=KR:ko"

#데이터 가져오기

response = requests.get(rss_url,headers= {"User-Agent" : "Mozila/5.0"} )

soup = BeautifulSoup(response.text, "xml")
items = soup.find_all("item")

df_news = []

for item in items[:20] :
  title = item.find("title").text if item.find("title") else "" #값이 없을 경우 빈칸으로 지정하는 코드
  link = item.find("link").text if item.find("link") else ""
  pub_date = item.find("pubDate").text if item.find("pubDate") else ""
  source = item.find("source").text if item.find("source") else ""

    #pubDate 날짜 변환하기
  if pub_date:
      pub_date = datetime.strptime(pub_date, "%a, %d %b %Y %H:%M:%S GMT" ) #(데이터, 어떤 형식인지 알려주기)
      pub_date = pub_date.strftime("%Y-%m-%d")       #재조합하기
  
  df_news.append({
      "title" : title,
      "source" : source,
      "pub_date" : pub_date,
      "link" : link
  })

df_news_df = pd.DataFrame(df_news)
df_news_df

df_nws.append([a,b,)df_news 리스트안에 한줄로 차례대로 담긴 거 확인 가능

 

 


Part 2. 네이버뉴스 가져오기

  • 키워드 포함된 뉴스 가져올 반복문 만들기
import requests
import pandas as pd

client_id =  #네이버 개발자센터
client_secret = #네이버 개발자 센터

url = "https://openapi.naver.com/v1/search/news.json"

headers = {
    "X-Naver-Client-Id" : client_id ,
    "X-Naver-Client-Secret" : client_secret }

params = {
    "query": "솔로프리너",
    "sort": "date", #정렬
    "display": 30 }  

response = requests.get(url, params=params , headers=headers )

data = response.json()
items = data['items']

news_list = [] #df만들기 전에 빈 리스트 값 하나 만들기

for item in items:
    news_list.append({
        "title" : item['title'],
        "link" : item['link'],
        "description" : item['description'],
        "pub_date" : item['pubDate']    
    })

df_news = pd.DataFrame(news_list)
df_news

 

  • 전처리하기
    1. 발행일 전처리  : pd.to_datetime / .dt.strftime
    #판다스를 쓰는 이유
    #-구글뉴스는 하나하나 날짜 지정했는데, 판다스는 지정하지 않아도 됨
    2. 정렬 
    3. 태그값 삭제
    4. 중복기사 삭제
    5. 결측치 처리
# 발행일 전처리
df_news['pub_date'] = pd.to_datetime(df_news['pub_date']) #날짜처럼생긴 문자열 → 날짜형식으로 변환
df_news['pub_date'] = df_news['pub_date'].dt.strftime("%Y-%m-%d")   #원하는 형식으로 변경

# 정렬
df_news.sort_values(by='pub_date', ascending=False)
#df_news.sort_values(by='pub_date', ascending=False).reset_index(drop=True)

# 태그값 삭제 - 정규표현식패턴 
df_news['title'] = df_news['title'].str.replace( r"<.*?>" , "", regex=True)
df_news['description'] = df_news['description'].str.replace( r"<.*?>" , "", regex=True)

#중복기사 삭제
df_news.shape #확인
df_news = df_news.drop_duplicates(subset=["title" , "link"])
#df_news = df_news.drop_duplicates(subset=["title"])
#df_news = df_news.drop_duplicates(subset=["link"])

#결측치 처리
df_news.isnull().sum() #결측치 확인
df_news['title'] = df_news['title'].fillna("제목 없음")
df_news['description'] = df_news['description'].fillna("내용 없음")
df_news['link'] = df_news['link'].fillna("링크 없음")

1. 발행일 전처리
2. 정렬
3. 정렬 후 태그값 삭제

 

4. 중복기사 제거 - 중복값없음
5. 결측치 처리

 

 

 

 

※ API 방식 차이 - 구글뉴스의 xml / 네이버뉴스의 json

 

더보기

구글뉴스에서 썼던 xml과 네이버뉴스에서 쓴 json의 구조 차이를 이해하고 python에서 beautifulsoup 사용 / 딕셔너리 사용에 대한 차이를 이해해라...