https://link.coupang.com/a/cqO1aS
Apple 2024 맥북 프로 14 M4 - 노트북 | 쿠팡
현재 별점 4.9점, 리뷰 425개를 가진 Apple 2024 맥북 프로 14 M4! 지금 쿠팡에서 더 저렴하고 다양한 노트북 제품들을 확인해보세요.
www.coupang.com

카카오의 티스토리말고
브런치라는 서비스도 있어요.
개인적인 경험으로 일반인이 운영하는 블로그보다
훨씬 글의 퀄리티가 높습니다.
작가들의 블로그라고 할 수 있어요.
그런데 불편한 점은
좋은 내용이라 참고하고 싶은데
저작권 보호를 위해서
작가 본인만 글을 복사할 수 있도록 되어있더라구요.

브런치 사이트의 복사/붙여넣기 방지를 우회하여
Python으로 크롤링하는 방법으로 해결가능합니다.
어떤 원리로 이게 가능할까요?
주로 이런 사이트들은 JavaScript 이벤트 핸들러나
CSS를 사용해 복사를 방지하지만,
서버에서 HTML을 받아오면
이러한 제한을 우회할 수 있습니다.

코드 사용법:
1) 단일 글을 크롤링하려면 article_url 변수에
원하는 브런치 글 URL을 입력하고 실행합니다.
2) 매거진 전체를 크롤링하려면
하단의 주석 처리된 부분을 해제하고
magazine_url에 매거진 URL을 입력합니다.
3) 이 코드는 다음과 같은 방식으로 작동합니다:
- HTTP 요청을 통해 브런치 페이지의
HTML을 직접 가져옵니다
- BeautifulSoup으로 HTML을 파싱하여
필요한 콘텐츠를 추출합니다
- 사용자 에이전트 헤더를 설정하여
일반 브라우저처럼 동작합니다
- 추출한 콘텐츠는 텍스트 파일로 저장됩니다
실제 사이트 구조에 따라 일부 선택자(selector)를
수정해야 할 수도 있습니다.
또한 브런치에서 크롤링 방지 정책이 변경될 경우
코드를 업데이트해야 할 수 있습니다.

import requests
from bs4 import BeautifulSoup
import time
import random
import re
import os
def get_article_content(article_url):
"""
브런치 글 URL을 받아 콘텐츠를 추출하는 함수
"""
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',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7',
'Referer': 'https://brunch.co.kr/'
}
try:
response = requests.get(article_url, headers=headers)
response.raise_for_status() # 요청이 성공했는지 확인
soup = BeautifulSoup(response.text, 'html.parser')
# 제목 추출
title = soup.select_one('h1.cover_title')
title_text = title.text.strip() if title else "제목 없음"
# 작성자 추출
author = soup.select_one('span.author_name')
author_text = author.text.strip() if author else "작성자 미상"
# 본문 내용 추출 (브런치의 경우 article 태그 내부에 있는 경우가 많음)
content_divs = soup.select('div.item_view article p, div.item_view article h1, div.item_view article h2, div.item_view article h3')
if not content_divs:
content_divs = soup.select('div.wrap_body p, div.wrap_body h1, div.wrap_body h2, div.wrap_body h3')
content = []
for div in content_divs:
text = div.get_text(strip=True)
if text:
content.append(text)
# 만약 위 선택자로 내용을 찾지 못했다면 다른 방법 시도
if not content:
article_content = soup.select_one('.wrap_body')
if article_content:
content = [p.text.strip() for p in article_content.find_all(['p', 'h1', 'h2', 'h3']) if p.text.strip()]
return {
'title': title_text,
'author': author_text,
'content': '\n\n'.join(content),
'url': article_url
}
except requests.exceptions.RequestException as e:
print(f"요청 중 오류 발생: {e}")
return None
except Exception as e:
print(f"처리 중 오류 발생: {e}")
return None
def save_article(article_data, folder='brunch_articles'):
"""
추출한 글을 파일로 저장하는 함수
"""
if not article_data:
return False
# 폴더가 없으면 생성
if not os.path.exists(folder):
os.makedirs(folder)
# 파일명 생성 (특수문자 제거)
filename = re.sub(r'[\\/*?:"<>|]', "", article_data['title'])
filename = f"{filename}_{article_data['author']}.txt"
filepath = os.path.join(folder, filename)
try:
with open(filepath, 'w', encoding='utf-8') as f:
f.write(f"제목: {article_data['title']}\n")
f.write(f"작성자: {article_data['author']}\n")
f.write(f"원본 URL: {article_data['url']}\n\n")
f.write("=" * 50 + "\n\n")
f.write(article_data['content'])
print(f"파일 저장 완료: {filepath}")
return True
except Exception as e:
print(f"파일 저장 중 오류 발생: {e}")
return False
def crawl_brunch_magazine(magazine_url):
"""
브런치 매거진의 모든 글을 크롤링하는 함수
"""
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',
}
try:
response = requests.get(magazine_url, headers=headers)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
# 글 링크 추출 (이 부분은 브런치 사이트 구조에 따라 조정 필요)
article_links = soup.select('a.link_post')
article_urls = []
for link in article_links:
if 'href' in link.attrs:
url = link['href']
if not url.startswith('http'):
url = f"https://brunch.co.kr{url}"
article_urls.append(url)
print(f"총 {len(article_urls)}개의 글을 발견했습니다.")
# 각 글 처리
for i, url in enumerate(article_urls):
print(f"[{i+1}/{len(article_urls)}] 처리 중: {url}")
article_data = get_article_content(url)
if article_data:
save_article(article_data)
# 서버 부하를 줄이기 위해 요청 간 간격 두기
time.sleep(random.uniform(1.5, 3.0))
except Exception as e:
print(f"매거진 크롤링 중 오류 발생: {e}")
# 사용 예시
if __name__ == "__main__":
# 단일 글 크롤링
article_url = "https://brunch.co.kr/@글주소" # 실제 브런치 글 URL로 변경
article_data = get_article_content(article_url)
if article_data:
save_article(article_data)
# 매거진 전체 크롤링
# magazine_url = "https://brunch.co.kr/@매거진주소" # 실제 브런치 매거진 URL로 변경
# crawl_brunch_magazine(magazine_url)

이런 식으로 텍스트 파일로
저장되어있는 걸 볼 수 있구요.
메모장 열어서 활용할 수 있어요.

사실 더 쉬운 방법은
코딩하지 않고 웹크롤링 없이
아래와 같이 브라우저 개발자 도구들어가서
디버거에 자바스크립트 작동하지 않도록
체크하는 것으로 해결할 수 있어요.
그냥 파이썬 코드 연습해보자는 겁니다^^;;

'파이썬' 카테고리의 다른 글
파이썬 클래스와 객체, 진짜 쉽게 이해하기! (0) | 2025.04.29 |
---|---|
파이썬 딕셔너리, value 기준 내림차순 정렬하는 방법 (0) | 2025.04.29 |
[파이썬] 튜플 vs 리스트, 뭐가 다를까? (1) | 2025.04.18 |
파이썬 변수: 객체와 이름의 연결고리 (1) | 2025.04.10 |
파이썬 수업을 위한 교육용 드론 추천 (0) | 2025.03.05 |