안녕하세요, 여러분! 드디어 웹 스크래핑 시리즈의 마지막 시간이 되었어요! 🎉 지난 시간까지 환경 설정과 기본적인 웹 스크래핑 방법을 배웠는데요, 오늘은 수집한 데이터를 저장하고 활용하는 방법과 더 심화된 기술을 알아볼 거예요! 어제는 스크래핑 코드로 날씨 정보를 가져왔더니 우산을 챙겨갔는데 정말 비가 왔어요! 웹 스크래핑의 실용성을 몸소 체험했답니다! 😄 이제 마지막 단계로 함께 나아가볼까요?
웹 스크래핑 데이터 저장하기 💾
수집한 데이터는 다양한 형식으로 저장할 수 있어요. 가장 많이 사용되는 형식들을 살펴볼게요!
1. CSV 파일로 저장하기 📋
CSV(Comma-Separated Values)는 데이터를 쉼표로 구분하여 저장하는 간단한 형식이에요. 엑셀에서도 쉽게 열 수 있어 널리 사용되죠!
import requests
from bs4 import BeautifulSoup
import csv
import datetime
def scrape_news_headlines():
"""뉴스 헤드라인을 스크래핑하는 함수"""
url = "https://news.ycombinator.com/"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
# 헤드라인과 링크 가져오기
headlines = []
for item in soup.select('span.titleline > a'):
headlines.append({
'title': item.text,
'link': item.get('href')
})
return headlines
def save_to_csv(data, filename):
"""데이터를 CSV 파일로 저장하는 함수"""
# 현재 날짜를 파일명에 추가
today = datetime.datetime.now().strftime("%Y-%m-%d")
full_filename = f"{filename}_{today}.csv"
# CSV 파일 생성 및 데이터 쓰기
with open(full_filename, 'w', newline='', encoding='utf-8') as csvfile:
# 필드 이름 정의
fieldnames = data[0].keys() if data else []
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
# 헤더 쓰기
writer.writeheader()
# 데이터 쓰기
for row in data:
writer.writerow(row)
print(f"데이터가 {full_filename}에 저장되었습니다!")
return full_filename
# 실행 예제
if __name__ == "__main__":
print("뉴스 헤드라인 스크래핑 중...")
headlines = scrape_news_headlines()
if headlines:
print(f"{len(headlines)}개의 헤드라인을 찾았습니다.")
filename = save_to_csv(headlines, "news_headlines")
# 저장된 데이터 미리보기
print("\n저장된 데이터 미리보기:")
for i, headline in enumerate(headlines[:5], 1):
print(f"{i}. {headline['title']}")
else:
print("헤드라인을 찾을 수 없습니다.")
2. JSON 파일로 저장하기 📊
JSON(JavaScript Object Notation)은 구조화된 데이터를 저장하기에 좋은 형식이에요. 웹 애플리케이션에서 많이 사용되죠!
import requests
from bs4 import BeautifulSoup
import json
import datetime
def scrape_product_info():
"""상품 정보를 스크래핑하는 예제 함수"""
# 이 예제에서는 실제 데이터 대신 샘플 데이터를 사용합니다
# 실제 스크래핑에서는 아래 코드를 사용하세요:
# url = "https://example-shop.com/products"
# response = requests.get(url)
# soup = BeautifulSoup(response.text, 'html.parser')
# products = []
# for item in soup.select('.product-item'):
# name = item.select_one('.product-name').text.strip()
# price = item.select_one('.product-price').text.strip()
# products.append({'name': name, 'price': price})
# 샘플 데이터
products = [
{'name': '스마트폰 케이스', 'price': '15,000원', 'rating': 4.5, 'reviews': 120},
{'name': '블루투스 이어폰', 'price': '89,000원', 'rating': 4.8, 'reviews': 342},
{'name': '노트북 파우치', 'price': '28,500원', 'rating': 4.2, 'reviews': 56},
{'name': '무선 충전기', 'price': '35,000원', 'rating': 3.9, 'reviews': 78}
]
return products
def save_to_json(data, filename):
"""데이터를 JSON 파일로 저장하는 함수"""
# 현재 날짜와 시간을 파일명에 추가
timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
full_filename = f"{filename}_{timestamp}.json"
# 메타데이터 추가
json_data = {
'timestamp': timestamp,
'source': 'Web Scraping Example',
'total_items': len(data),
'items': data
}
# JSON 파일에 데이터 쓰기
with open(full_filename, 'w', encoding='utf-8') as jsonfile:
json.dump(json_data, jsonfile, ensure_ascii=False, indent=4)
print(f"데이터가 {full_filename}에 저장되었습니다!")
return full_filename
# 실행 예제
if __name__ == "__main__":
print("상품 정보 스크래핑 중...")
products = scrape_product_info()
if products:
print(f"{len(products)}개의 상품 정보를 찾았습니다.")
filename = save_to_json(products, "product_data")
# 저장된 데이터 미리보기
print("\n저장된 데이터 미리보기:")
for i, product in enumerate(products, 1):
print(f"{i}. {product['name']} - {product['price']} (평점: {product['rating']})")
else:
print("상품 정보를 찾을 수 없습니다.")
3. 데이터베이스에 저장하기 🗄️
대용량 데이터나 구조화된 데이터는 SQLite 같은 데이터베이스에 저장하면 더 효율적으로 관리할 수 있어요!
import requests
from bs4 import BeautifulSoup
import sqlite3
import datetime
def scrape_book_info():
"""책 정보를 스크래핑하는 예제 함수"""
# 실제 사이트 스크래핑 대신 샘플 데이터 사용
books = [
{'title': '파이썬으로 배우는 웹 스크래핑', 'author': '김개발', 'price': '25,000원', 'publisher': '코딩출판사', 'year': 2023},
{'title': '처음 시작하는 데이터 분석', 'author': '이분석', 'price': '30,000원', 'publisher': '데이터북스', 'year': 2022},
{'title': 'PyCharm 마스터하기', 'author': '박코딩', 'price': '28,000원', 'publisher': 'IDE출판', 'year': 2023},
{'title': '웹 개발자를 위한 HTML/CSS', 'author': '최웹개발', 'price': '22,000원', 'publisher': '프론트엔드사', 'year': 2021}
]
return books
def save_to_database(books):
"""책 정보를 SQLite 데이터베이스에 저장하는 함수"""
# 현재 날짜로 DB 파일 이름 생성
today = datetime.datetime.now().strftime("%Y-%m-%d")
db_name = f"books_database_{today}.db"
# 데이터베이스 연결
conn = sqlite3.connect(db_name)
cursor = conn.cursor()
# 테이블 생성 (이미 존재하는 경우 무시)
cursor.execute('''
CREATE TABLE IF NOT EXISTS books (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
author TEXT NOT NULL,
price TEXT,
publisher TEXT,
year INTEGER,
date_added TEXT
)
''')
# 현재 시간 가져오기
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 데이터 추가
for book in books:
cursor.execute('''
INSERT INTO books (title, author, price, publisher, year, date_added)
VALUES (?, ?, ?, ?, ?, ?)
''', (
book['title'],
book['author'],
book['price'],
book['publisher'],
book['year'],
current_time
))
# 변경사항 저장
conn.commit()
# 데이터베이스에서 데이터 조회하여 확인
cursor.execute("SELECT * FROM books")
saved_books = cursor.fetchall()
# 연결 종료
conn.close()
print(f"데이터가 {db_name} 데이터베이스에 저장되었습니다!")
return db_name, saved_books
# 실행 예제
if __name__ == "__main__":
print("책 정보 스크래핑 중...")
books = scrape_book_info()
if books:
print(f"{len(books)}개의 책 정보를 찾았습니다.")
db_name, saved_books = save_to_database(books)
# 저장된 데이터 미리보기
print("\n데이터베이스에 저장된 책 정보:")
for i, book in enumerate(saved_books, 1):
# book 튜플 구조: (id, title, author, price, publisher, year, date_added)
print(f"{i}. {book[1]} - {book[2]} ({book[4]}, {book[5]})")
else:
print("책 정보를 찾을 수 없습니다.")
고급 스크래핑 기법 🔍
이제 더 복잡한 웹사이트를 스크래핑하는 고급 기법을 알아볼게요!
1. 동적 페이지 스크래핑 (Selenium 활용) 🌐
JavaScript로 동적으로 콘텐츠를 불러오는 웹사이트는 Selenium을 사용하여 스크래핑할 수 있어요. Selenium은 실제 브라우저를 제어하는 도구예요!
"""
Selenium을 이용한 동적 웹페이지 스크래핑 예제
사용 전 준비사항:
1. Selenium 설치: pip install selenium
2. 웹 드라이버 설치: ChromeDriver (https://sites.google.com/chromium.org/driver/)
"""
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
import csv
def setup_driver():
"""Selenium 웹 드라이버 설정"""
# 크롬 옵션 설정
chrome_options = Options()
chrome_options.add_argument("--headless") # 헤드리스 모드 (화면 표시 없음)
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--window-size=1920,1080")
# 크롬 드라이버 경로 설정 (자신의 ChromeDriver 경로로 변경하세요)
driver_path = "./chromedriver" # Windows: "chromedriver.exe"
service = Service(driver_path)
# 드라이버 생성
driver = webdriver.Chrome(service=service, options=chrome_options)
return driver
def scrape_infinite_scroll_page():
"""무한 스크롤 페이지 스크래핑 예제"""
driver = setup_driver()
try:
# 웹 페이지 로드 (예: 트위터 검색 결과)
driver.get("https://twitter.com/search?q=python&src=typed_query")
# 페이지가 로드될 때까지 대기
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "[data-testid='tweet']"))
)
# 스크롤 데이터를 담을 리스트
tweets = []
target_count = 20 # 스크래핑할 트윗 수
# 이미 처리한 트윗의 ID를 저장하는 집합
processed_tweets = set()
print(f"{target_count}개의 트윗을 수집합니다...")
# 원하는 개수의 트윗을 모을 때까지 스크롤 반복
while len(tweets) < target_count:
# 현재 보이는 모든 트윗 요소 가져오기
tweet_elements = driver.find_elements(By.CSS_SELECTOR, "[data-testid='tweet']")
# 각 트윗 정보 추출
for tweet in tweet_elements:
# 트윗 ID 또는 고유 식별자 추출 (여기서는 내부 텍스트로 대체)
tweet_text = tweet.text
tweet_id = hash(tweet_text) # 간단한 해시 기반 ID
# 이미 처리한 트윗인지 확인
if tweet_id in processed_tweets:
continue
try:
# 트윗 작성자
author = tweet.find_element(By.CSS_SELECTOR, "[data-testid='User-Name']").text
# 트윗 내용
content = tweet.find_element(By.CSS_SELECTOR, "[data-testid='tweetText']").text
# 수집한 정보 저장
tweets.append({
'author': author,
'content': content
})
# 처리한 트윗 ID 기록
processed_tweets.add(tweet_id)
print(f"트윗 수집: {len(tweets)}/{target_count}")
# 목표 달성 시 종료
if len(tweets) >= target_count:
break
except Exception as e:
print(f"트윗 정보 추출 중 오류: {e}")
# 페이지 아래로 스크롤
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# 새 콘텐츠 로드 대기
time.sleep(2)
# CSV 파일로 저장
with open('twitter_python_tweets.csv', 'w', newline='', encoding='utf-8') as csvfile:
fieldnames = ['author', 'content']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for tweet in tweets:
writer.writerow(tweet)
print(f"{len(tweets)}개의 트윗을 성공적으로 수집했습니다!")
print("데이터가 twitter_python_tweets.csv 파일에 저장되었습니다.")
except Exception as e:
print(f"스크래핑 중 오류 발생: {e}")
finally:
# 브라우저 종료
driver.quit()
# 실행 시 주의: Twitter의 구조는 자주 변경될 수 있으며,
# 실제 실행 시 로그인이 필요하거나 구조가 달라져 작동하지 않을 수 있습니다.
# 이 코드는 교육 목적으로만 제공됩니다.
if __name__ == "__main__":
print("⚠️ 주의: 이 예제는 실제 Twitter 사이트의 구조에 따라 작동하지 않을 수 있습니다.")
print("실행하기 전에 ChromeDriver가 설치되어 있는지 확인하세요.")
# scrape_infinite_scroll_page() # 실행 시 주석 해제
참고: Selenium을 사용하려면 먼저 pip install selenium으로 라이브러리를 설치하고, 브라우저 드라이버(예: ChromeDriver)를 다운로드해야 해요. 위 예제는 교육 목적으로만 제공되며, Twitter의 이용약관을 준수해야 함을 명심하세요!
2. 웹 스크래핑 자동화하기 ⏱️
일정 시간마다 자동으로 데이터를 수집하고 저장하는 스크립트를 만들 수 있어요. schedule 라이브러리를 사용하면 특정 시간에 자동으로 스크래핑을 수행할 수 있어요.
import requests
from bs4 import BeautifulSoup
import pandas as pd
import time
import schedule
import os
from datetime import datetime
class WeatherScraper:
"""날씨 정보를 주기적으로 스크래핑하는 클래스"""
def __init__(self, cities, output_folder="weather_data"):
self.cities = cities
self.output_folder = output_folder
# 출력 폴더가 없으면 생성
if not os.path.exists(output_folder):
os.makedirs(output_folder)
print(f"출력 폴더 '{output_folder}'를 생성했습니다.")
# 헤더 설정
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
# 수집한 데이터를 저장할 데이터프레임 초기화
self.all_data = pd.DataFrame()
def get_weather(self, city):
"""지정된 도시의 날씨 정보를 가져오는 함수"""
try:
# 실제 프로덕션에서는 적절한 날씨 사이트를 사용하세요
url = f"https://www.timeanddate.com/weather/{city}/ext"
response = requests.get(url, headers=self.headers)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
# 날씨 데이터 추출 (사이트 구조에 따라 선택자 조정 필요)
temp_element = soup.select_one('.h2')
temp = temp_element.text if temp_element else "N/A"
weather_element = soup.select_one('p.summary')
weather = weather_element.text if weather_element else "N/A"
# 현재 시간
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return {
'city': city,
'temperature': temp,
'condition': weather,
'timestamp': current_time
}
except Exception as e:
print(f"도시 '{city}' 날씨 스크래핑 중 오류: {e}")
return {
'city': city,
'temperature': "오류",
'condition': "오류",
'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
def scrape_all_cities(self):
"""모든 도시의 날씨 정보를 스크래핑하는 함수"""
print(f"\n====== 날씨 스크래핑 시작: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} ======")
# 각 도시의 날씨 정보 수집
data = []
for city in self.cities:
print(f"{city} 날씨 정보 스크래핑 중...")
weather_info = self.get_weather(city)
data.append(weather_info)
# 너무 빠른 요청으로 차단되지 않도록 대기
time.sleep(1)
# 데이터프레임으로 변환
df = pd.DataFrame(data)
print(f"{len(df)} 개의 도시 날씨 정보를 수집했습니다.")
# 모든 데이터에 추가
self.all_data = pd.concat([self.all_data, df])
# CSV 파일로 저장
today = datetime.now().strftime("%Y-%m-%d")
now = datetime.now().strftime("%H-%M-%S")
filename = f"{self.output_folder}/weather_{today}_{now}.csv"
df.to_csv(filename, index=False)
print(f"데이터가 {filename}에 저장되었습니다.")
# 전체 데이터 저장
all_data_filename = f"{self.output_folder}/all_weather_data.csv"
self.all_data.to_csv(all_data_filename, index=False)
print(f"누적 데이터가 {all_data_filename}에 저장되었습니다.")
def start_scheduled_scraping(self, interval_minutes=60):
"""스케줄링된 스크래핑 시작"""
print(f"날씨 스크래핑 자동화 시작: {interval_minutes}분마다 실행됩니다.")
# 먼저 한 번 실행
self.scrape_all_cities()
# 주기적으로 실행하도록 스케줄링
schedule.every(interval_minutes).minutes.do(self.scrape_all_cities)
try:
# 스케줄러 계속 실행
while True:
schedule.run_pending()
time.sleep(1)
except KeyboardInterrupt:
print("\n스크래핑 자동화가 중지되었습니다.")
# 사용 예제
if __name__ == "__main__":
# 스크래핑할 도시 리스트
cities_to_scrape = ["seoul", "tokyo", "london", "new-york"]
# 스크래퍼 초기화
scraper = WeatherScraper(cities_to_scrape)
# 15분마다 스크래핑 시작
scraper.start_scheduled_scraping(interval_minutes=15)
참고: 스크래핑 자동화 시 해당 웹사이트의 이용약관을 준수하고, 서버에 부담을 주지 않도록 적절한 시간 간격을 설정하는 것이 중요해요!
3. 스크래핑 데이터로 분석하기 📊
수집한 데이터를 분석하고 시각화하면 유용한 인사이트를 얻을 수 있어요. pandas와 matplotlib 같은 라이브러리를 활용하면 데이터를 더 쉽게 분석할 수 있어요!
import pandas as pd
import matplotlib.pyplot as plt
import os
import re
from datetime import datetime
def analyze_weather_data(data_folder="weather_data"):
"""날씨 데이터를 분석하고 시각화하는 함수"""
# 누적 데이터 파일 확인
all_data_file = f"{data_folder}/all_weather_data.csv"
if not os.path.exists(all_data_file):
print(f"누적 데이터 파일을 찾을 수 없습니다: {all_data_file}")
return
# 데이터 로드
df = pd.read_csv(all_data_file)
print(f"데이터 로드 완료: {len(df)}개의 레코드")
# 데이터 전처리
# 온도에서 숫자만 추출 (예: "25°C" -> 25)
df['temp_value'] = df['temperature'].apply(lambda x:
float(re.search(r'(-?\d+(\.\d+)?)', str(x)).group(1)) if isinstance(x, str) and re.search(r'(-?\d+(\.\d+)?)', str(x)) else None)
# 타임스탬프를 datetime 객체로 변환
df['timestamp'] = pd.to_datetime(df['timestamp'])
df['date'] = df['timestamp'].dt.date
# 기본 통계 분석
print("\n=== 도시별 평균 온도 ===")
city_avg_temp = df.groupby('city')['temp_value'].mean().reset_index()
print(city_avg_temp)
# 도시별 날씨 상태 빈도
print("\n=== 도시별 가장 흔한 날씨 상태 ===")
weather_counts = df.groupby(['city', 'condition']).size().reset_index(name='count')
for city in df['city'].unique():
city_weather = weather_counts[weather_counts['city'] == city].sort_values('count', ascending=False)
if not city_weather.empty:
print(f"{city}: {city_weather.iloc[0]['condition']} ({city_weather.iloc[0]['count']}회)")
# 그래프 생성을 위한 폴더 생성
graphs_folder = f"{data_folder}/graphs"
if not os.path.exists(graphs_folder):
os.makedirs(graphs_folder)
# 1. 도시별 평균 온도 바 차트
plt.figure(figsize=(10, 6))
plt.bar(city_avg_temp['city'], city_avg_temp['temp_value'], color='skyblue')
plt.title('도시별 평균 온도')
plt.xlabel('도시')
plt.ylabel('평균 온도 (°C)')
plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.savefig(f"{graphs_folder}/city_avg_temp.png")
plt.close()
# 2. 시간별 온도 변화 (라인 차트)
# 각 도시별로 별도의 선 그래프
plt.figure(figsize=(12, 7))
for city in df['city'].unique():
city_data = df[df['city'] == city].sort_values('timestamp')
plt.plot(city_data['timestamp'], city_data['temp_value'], label=city, marker='o')
plt.title('시간별 도시 온도 변화')
plt.xlabel('시간')
plt.ylabel('온도 (°C)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.xticks(rotation=45)
plt.tight_layout()
plt.savefig(f"{graphs_folder}/temp_over_time.png")
plt.close()
# 3. 도시별 온도 분포 (박스플롯)
plt.figure(figsize=(10, 6))
df.boxplot(column='temp_value', by='city', grid=False)
plt.title('도시별 온도 분포')
plt.suptitle('') # 상단 제목 제거
plt.xlabel('도시')
plt.ylabel('온도 (°C)')
plt.savefig(f"{graphs_folder}/temp_distribution.png")
plt.close()
print(f"\n분석 완료! 그래프가 {graphs_folder}에 저장되었습니다.")
return df
def create_weather_report(df, output_folder="weather_data"):
"""날씨 데이터를 기반으로 간단한 보고서 생성"""
if df is None or df.empty:
print("보고서를 생성할 데이터가 없습니다.")
return
# 보고서 파일명
report_file = f"{output_folder}/weather_report_{datetime.now().strftime('%Y-%m-%d')}.html"
# HTML 보고서 작성
html = f"""
<!DOCTYPE html>
<html>
<head>
<title>날씨 데이터 분석 보고서</title>
<style>
body {{ font-family: Arial, sans-serif; margin: 20px; }}
h1 {{ color: #2c3e50; }}
h2 {{ color: #3498db; }}
table {{ border-collapse: collapse; width: 100%; margin-bottom: 20px; }}
th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
th {{ background-color: #f2f2f2; }}
tr:nth-child(even) {{ background-color: #f9f9f9; }}
.graph {{ margin: 20px 0; max-width: 100%; }}
.summary {{ background-color: #e8f4f8; padding: 15px; border-radius: 5px; }}
</style>
</head>
<body>
<h1>날씨 데이터 분석 보고서</h1>
<p>생성 시간: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
<div class="summary">
<h2>요약</h2>
<p>분석된 데이터 수: {len(df)}개 레코드</p>
<p>분석 기간: {df['timestamp'].min().strftime('%Y-%m-%d')} ~ {df['timestamp'].max().strftime('%Y-%m-%d')}</p>
<p>분석 도시: {', '.join(df['city'].unique())}</p>
</div>
<h2>도시별 평균 온도</h2>
<table>
<tr>
<th>도시</th>
<th>평균 온도 (°C)</th>
<th>최저 온도 (°C)</th>
<th>최고 온도 (°C)</th>
</tr>
"""
# 도시별 통계 추가
for city in df['city'].unique():
city_data = df[df['city'] == city]
avg_temp = city_data['temp_value'].mean()
min_temp = city_data['temp_value'].min()
max_temp = city_data['temp_value'].max()
html += f"""
<tr>
<td>{city}</td>
<td>{avg_temp:.1f}</td>
<td>{min_temp:.1f}</td>
<td>{max_temp:.1f}</td>
</tr>
"""
html += """
</table>
<h2>그래프</h2>
<div class="graph">
<h3>도시별 평균 온도</h3>
<img src="graphs/city_avg_temp.png" alt="도시별 평균 온도" width="800">
</div>
<div class="graph">
<h3>시간별 온도 변화</h3>
<img src="graphs/temp_over_time.png" alt="시간별 온도 변화" width="800">
</div>
<div class="graph">
<h3>도시별 온도 분포</h3>
<img src="graphs/temp_distribution.png" alt="도시별 온도 분포" width="800">
</div>
<h2>결론</h2>
<p>이 보고서는 수집된 날씨 데이터를 기반으로 자동 생성되었습니다. 더 자세한 분석이 필요한 경우 원본 데이터를 참조하세요.</p>
</body>
</html>
"""
# HTML 파일로 저장
with open(report_file, 'w', encoding='utf-8') as f:
f.write(html)
print(f"보고서가 생성되었습니다: {report_file}")
# 실행 예제
if __name__ == "__main__":
print("날씨 데이터 분석 시작...")
df = analyze_weather_data()
if df is not None and not df.empty:
create_weather_report(df)
웹 스크래핑 프로젝트 아이디어 💡
이제 배운 내용을 응용할 수 있는 몇 가지 프로젝트 아이디어를 소개할게요:
- 가격 비교 도구: 여러 쇼핑몰에서 특정 제품의 가격을 수집하여 비교하는 도구
- 뉴스 요약기: 여러 뉴스 사이트에서 헤드라인을 수집하고 주요 키워드를 분석하는 도구
- 도서 추천 시스템: 도서 리뷰 사이트에서 데이터를 수집하여 사용자 취향에 맞는 책을 추천하는 시스템
- 채용 정보 모니터링: 구직 사이트에서 특정 키워드가 포함된 채용 공고를 수집하는 도구
- 소셜 미디어 트렌드 분석: 소셜 미디어 플랫폼에서 인기 주제나 해시태그를 분석하는 도구
웹 스크래핑의 윤리적 고려사항 🤔
웹 스크래핑은 강력한 도구이지만, 책임감 있게 사용해야 해요:
- 이용 약관 준수: 웹사이트의 이용 약관과 robots.txt 파일을 반드시 확인하세요
- 개인정보 보호: 개인정보가 포함된 데이터는 수집하지 마세요
- 서버 부하 고려: 짧은 시간에 너무 많은 요청을 보내지 마세요
- 저작권 존중: 수집한 데이터의 사용 시 저작권을 존중하세요
- 상업적 이용 제한: 일부 웹사이트는 상업적 목적의 스크래핑을 금지하고 있어요
웹 스크래핑 기술 향상을 위한 다음 단계 🚀
웹 스크래핑에 더 능숙해지고 싶다면, 다음 주제들을 더 깊이 공부해보세요:
- 정규표현식(Regex): 복잡한 패턴의 문자열을 추출하는데 유용해요
- API 활용: 많은 웹사이트는 공식 API를 제공하며, 이를 활용하면 더 안정적으로 데이터를 수집할 수 있어요
- 비동기 프로그래밍: 여러 페이지를 동시에 스크래핑하여 성능을 향상시킬 수 있어요
- 데이터베이스 연동: 대량의 데이터를 효율적으로 저장하고 관리하는 방법을 배우세요
- 머신러닝 적용: 수집한 데이터에 머신러닝을 적용하여 예측 모델을 만들어보세요
시리즈를 마치며 🌟
이렇게 3회에 걸친 웹 스크래핑 시리즈가 마무리되었어요! 여러분은 이제:
- PyCharm 환경 설정 방법
- 기본적인 웹 스크래핑 방법
- 다양한 데이터 저장 방식
- 고급 스크래핑 기법
- 데이터 분석 및 시각화 방법
을 배웠어요! 이 지식을 바탕으로 여러분만의 웹 스크래핑 프로젝트를 시작해보세요!
어제 웹 스크래핑으로 날씨 정보를 가져와서 비 소식을 미리 알게 된 것처럼, 웹 스크래핑은 우리 일상을 더 편리하게 만들어줄 수 있어요. 이제 여러분도 코딩의 마법으로 인터넷의 바다에서 원하는 정보를 쏙쏙 건져올릴 수 있게 되었네요! 😊
질문이나 피드백이 있으시면 언제든지 댓글로 남겨주세요! 여러분의 첫 웹 스크래핑 프로젝트가 무엇인지도 알려주시면 좋겠어요! 함께 성장하는 즐거움을 나눠요~ 💖
'개발' 카테고리의 다른 글
🌈 PyCharm으로 시작하는 FastAPI 개발 여정 (초보자를 위한 가이드) 2편 ✨ (0) | 2025.03.19 |
---|---|
🌈 PyCharm으로 시작하는 FastAPI 개발 여정 (초보자를 위한 가이드) 1편 ✨ (0) | 2025.03.18 |
🌈 초보자를 위한 PyCharm으로 웹 스크래핑 시작하기 (2/3) (0) | 2025.03.16 |
🌈 초보자를 위한 PyCharm으로 웹 스크래핑 시작하기 (1/3) (1) | 2025.03.15 |
앱 개발자의 필수 친구! JetBrains IDE 설치하고 함께 코딩해요 🌟 (0) | 2025.03.13 |