티스토리 뷰
반응형
📡 1. 크롤링 (Crawling)
1-1. 개요
🕸️ 1-1-1. 크롤링이란?
**크롤링(Crawling)**은 웹 페이지나 API로부터 원하는 정보를 자동으로 수집하는 기술이다.
자동화된 프로그램인 크롤러(Crawler) 또는 **스파이더(Spider)**가 웹 페이지를 탐색하며 데이터를 추출한다.
머신러닝 학습, 데이터 분석, 시장 조사 등 대량의 데이터 수집에 효과적이다.
🔍 1-1-2. 크롤링 vs 스크래핑
구분 | 웹 크롤링 | 웹 스크래핑 |
---|---|---|
목적 | 웹 전체 탐색 및 페이지 수집 | 특정 데이터 추출 |
범위 | 광범위 (다수 사이트) | 제한적 (특정 페이지) |
방식 | 링크를 따라 페이지 순회 | HTML 구조 분석 및 파싱 |
활용 예시 | 검색 엔진 인덱싱 | 가격 비교, 트렌드 분석 |
윤리/법 | robots.txt 준수 |
저작권·이용약관 준수 |
💡
robots.txt
: 크롤링 허용 여부 및 범위를 명시한 파일.
예시:https://example.com/robots.txt
🎯 1-1-3. 크롤링의 필요성
- ✅ 자동화된 데이터 수집
- 🔄 실시간 정보 갱신 가능
- 📊 빅데이터 확보 → ML 학습/분석 활용
- 🏁 경쟁 분석 및 전략 수립
1-2. 크롤링 시 주의 사항
⚖️ 1-2-1. 법적 고려사항
- 저작권: 무단 수집 및 재사용 금지
- 이용약관 준수: 크롤링 허용 범위 확인
- robots.txt 정책 준수: 접근 제한 경로 확인
🧩 1-2-2. 서버 부하 방지
- 크롤링 속도 조절 (예:
time.sleep
) - 병렬 요청 제한 (동시 요청 제한)
- User-Agent 설정 → 신뢰성 확보
🔐 1-2-3. 개인정보 및 윤리 고려
- 민감한 정보 수집 시 법적 규제 준수
- 데이터 활용 목적 명확히 → 윤리적 문제 방지
🚫 1-2-4. IP 차단 위험
- 과도한 요청 → 서버 차단 가능
- User-Agent/Proxy 설정, 요청 간 딜레이 삽입 등 회피 전략 필요
🔗 2. Open API
2-1. Open API 개요
📘 Open API란?
Open API는 누구나 접근할 수 있도록 공개된 API로, 개발자가 표준화된 방법으로 특정 서비스나 데이터에 접근할 수 있게 해주는 인터페이스입니다.
📌 특징
- 인증 방식: API Key, OAuth
- 사용량/요청 제한 존재
- 요청/응답 포맷과 예제 등을 공식 문서로 제공
🚀 장점
- 빠른 개발 (표준화된 인터페이스 제공)
- 손쉬운 데이터 확보
- 서비스 간 연동 및 혁신 촉진
2-2. Open API 사용법
📘 API 문서 구조
항목 | 설명 |
---|---|
Endpoint | API 요청 주소 |
Method | GET, POST, PUT, DELETE 등 |
Parameter | 쿼리 스트링 또는 요청 본문 데이터 |
Response | JSON, XML 등 |
인증 | API Key, OAuth 등 방식으로 수행 |
🧪 테스트 방법
- Postman: GUI 기반 테스트
- cURL: CLI 기반 요청 테스트
- 브라우저: GET 요청 시 URL 입력으로 간단 테스트 가능
📂 공공데이터포털 API 사용 순서
- 회원 가입 후 API 키 발급
- 문서에서 요청/응답 형식 확인
- Python 등으로 호출하여 응답 처리
2-3. API 크롤러 만들기 (Python)
✅ Step 1. 환경 설정
pip install requests pandas
- API 키는
.env
또는 별도 설정 파일로 안전하게 관리
✅ Step 2. 요청 예시
params = {"key": "{API_KEY}", "targetDt": "20241120"}
response = requests.get(API_URL, params=params)
if response.status_code == 200:
data = response.json()
else:
print("요청 실패")
✅ Step 3. 데이터 저장 (CSV 예시)
import csv
with open('movie_data.csv', 'w', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(['순위', '영화이름', '개봉일자'])
for item in items:
writer.writerow([item['rank'], item['movieNm'], item['openDt']])
✅ Step 4. 자동화 및 예외 처리
try:
response = requests.get(url, params=params)
response.raise_for_status()
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
✅ Step 5. 데이터 정제 및 저장
import pandas as pd
df = pd.read_csv('movie_data.csv')
df.dropna(inplace=True)
df['개봉일자'] = pd.to_datetime(df['개봉일자'])
df.to_csv('final_data.csv', index=False)
WEB 구조 정보 정리
탐색과 수집의 구조
형식: 웹, 웹 구조, HTML, HTTP, 서버, 통신 구조, 크롤러, 스파이더, JavaScript, AJAX, Selenium, robots.txt, sitemap.xml, BFS, DFS
3-1. WEB 구조 기초
3-1-1. 기본 구성 요소
URL (Uniform Resource Locator)
- 웹에서 자원의 위치를 나타내는 표준 주소 체계
- 프로토콜, 도메인, 경로, 쿼리 스트링 등으로 구성
HTTP / HTTPS
- 웹 클라이언트와 서버 간 통신을 위한 프로토콜
- 주요 요청 메서드: GET, POST, PUT, DELETE
- 응답 상태 코드: 2xx(성공), 3xx(리다이렉션), 4xx(클라이언트 오류), 5xx(서버 오류)
HTML / CSS / JavaScript
- HTML: 웹 페이지의 구조 정의
- CSS: 웹 페이지의 스타일 및 레이아웃 정의
- JavaScript: 웹 페이지의 동적 기능 구현
3-1-2. HTML 문서 구조
기본 구조:
<!DOCTYPE html>
,<html>
,<head>
,<body>
DOM (Document Object Model)
- HTML 문서를 트리 구조로 표현
- JavaScript 등을 통해 DOM 요소 접근 및 조작 가능
3-1-3. 웹의 연결성
- 하이퍼링크:
<a href="URL">
태그로 구현 - 웹 그래프: 페이지는 노드, 링크는 엣지로 구성된 그래프
- 탐색 알고리즘: 깊이 우선 탐색(DFS), 너비 우선 탐색(BFS)
3-2. HTTP 프로토콜과 크롤링
3-2-1. HTTP 요청과 응답 구조
- 요청 메서드: GET, POST, PUT, DELETE
- 상태 코드: 2xx, 3xx, 4xx, 5xx
- 헤더 정보: User-Agent, Accept, Content-Type 등
3-2-2. 크롤러 요청 구성
- User-Agent 설정 필요 (크롤러 신원 표시)
- 인증정보나 쿠키 등 헤더에 포함 가능
- 요청 간 딜레이 적용 권장 (서버 부하 방지 및 IP 차단 방지)
3-3. robots.txt와 sitemap.xml
3-3-1. robots.txt
웹 사이트의 루트 디렉토리에 위치한 크롤링 접근 제어 파일
예시:
User-agent: * Disallow: /private/
3-3-2. sitemap.xml
사이트 내 URL 목록 제공
크롤러가 페이지를 효율적으로 탐색하도록 도와줌
예시:
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <url> <loc>https://www.example.com/page1</loc> <lastmod>2023-10-01</lastmod> <changefreq>monthly</changefreq> <priority>0.8</priority> </url> </urlset>
robots.txt 내 명시:
Sitemap: https://www.example.com/sitemap.xml
3-4. 동적 웹 페이지 크롤링
3-4-1. 동적 렌더링
- JS 기반으로 렌더링된 콘텐츠는 일반 크롤러가 수집 불가
- AJAX, SPA 등으로 데이터가 비동기적으로 로딩됨
대응 방법:
- Selenium, Puppeteer 등의 헤드리스 브라우저 사용
- 네트워크 요청 중 API 엔드포인트 직접 호출
- Splash, Rendertron 등으로 JS 렌더링 처리
3-5. 크롤러 설계 시 고려 사항
3-5-1. URL 관리
- 중복 URL 정규화 필요
- 상대 경로를 절대 경로로 변환
- 대소문자, 슬래시 통일 등 표준화 필요
3-5-2. 상태 유지와 세션
- 로그인 유지 필요 시 쿠키 및 세션 정보 사용
- 서버로부터 받은 세션 정보를 다음 요청에 포함
3-5-3. 데이터 파싱
- HTML 파싱 도구: BeautifulSoup (Python), Cheerio (Node.js)
- XPath, CSS 선택자 활용
- 예외 및 오류 처리 로직 추가
3-6. 웹 크롤링 확장 전략
3-6-1. 스케줄링 및 주기적 크롤링
- Cron (Linux), Task Scheduler (Windows) 사용
- ETag, Last-Modified 등을 활용해 변경 여부 판단
3-6-2. 웹 표준 및 시맨틱 정보 활용
- W3C 표준 준수 웹 페이지는 크롤링 효율 높음
<meta>
태그, OG 프로토콜 등 활용 가능
4. 크롤링 데이터 저장
4-1. 데이터 저장 개요
4-1-1. 저장의 필요성
- 수집한 데이터를 안전하게 저장하고, 분석이나 공유, 학습 등에 활용하기 위해 영속성 확보 필요
- 구조화된 저장을 통해 검색과 처리 효율 향상
- 팀 및 프로젝트 간 재사용 가능
4-1-2. 저장 시 고려 사항
- 데이터 특성 파악: 표 형식, 중첩 구조 여부, 크기, 변경 빈도
- 활용 목적 고려: 분석용, 학습용, 웹 서비스용 등
- 보안 및 법적 준수: 민감 정보 암호화, 접근 권한 설정, 개인정보 보호법 준수
- 품질 관리: 저장 전 데이터 검증 및 정제
- 장애 대응: 저장 오류 기록 및 모니터링 체계
- 버전 및 확장성 설계
4-1-3. 저장 방식 종류
- 파일 시스템: CSV, JSON, XML, Excel
- 관계형 데이터베이스: MySQL, PostgreSQL
- NoSQL 데이터베이스: MongoDB, Redis
- 빅데이터 저장소: Hadoop HDFS, Amazon S3
- 클라우드 데이터베이스: Firebase, AWS DynamoDB
4-2. 파일 기반 저장
CSV
- 텍스트 기반, 표 형태에 적합
- Excel 등으로 열람 가능
- 중첩 데이터에는 부적합
import csv
data = [
{'name': 'Alice', 'age': 30, 'city': 'Seoul'},
{'name': 'Bob', 'age': 25, 'city': 'Busan'}
]
with open('data.csv', 'w', newline='', encoding='utf-8') as csvfile:
fieldnames = ['name', 'age', 'city']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for row in data:
writer.writerow(row)
JSON
- 키-값 구조, 계층적 데이터 표현 가능
- 웹 앱과 호환성 좋음
import json
data = [
{'name': 'Alice', 'age': 30, 'city': 'Seoul'},
{'name': 'Bob', 'age': 25, 'city': 'Busan'}
]
with open('data.json', 'w', encoding='utf-8') as jsonfile:
json.dump(data, jsonfile, ensure_ascii=False, indent=4)
XML
- 태그 기반, 문서 구조 표현
- 의미 표현은 우수하지만 구문 복잡
import xml.etree.ElementTree as ET
root = ET.Element('people')
person1 = ET.SubElement(root, 'person')
ET.SubElement(person1, 'name').text = 'Alice'
ET.SubElement(person1, 'age').text = '30'
ET.SubElement(person1, 'city').text = 'Seoul'
person2 = ET.SubElement(root, 'person')
ET.SubElement(person2, 'name').text = 'Bob'
ET.SubElement(person2, 'age').text = '25'
ET.SubElement(person2, 'city').text = 'Busan'
tree = ET.ElementTree(root)
tree.write('data.xml', encoding='utf-8', xml_declaration=True)
Excel
- 시각화 및 분석에 유리
- 비개발자 접근 용이
import pandas as pd
data = [
{'name': 'Alice', 'age': 30, 'city': 'Seoul'},
{'name': 'Bob', 'age': 25, 'city': 'Busan'}
]
df = pd.DataFrame(data)
df.to_excel('data.xlsx', index=False)
4-3. 관계형 데이터베이스 저장 (MySQL)
- 스키마 기반, SQL로 자유로운 조작 가능
- 데이터 무결성 보장, 스키마 변경은 어려움
import pymysql
data = [
{'name': 'Alice', 'age': 30, 'city': 'Seoul'},
{'name': 'Bob', 'age': 25, 'city': 'Busan'}
]
connection = pymysql.connect(
host='localhost',
user='user',
password='password',
db='mydatabase',
charset='utf8mb4'
)
try:
with connection.cursor() as cursor:
sql = "INSERT INTO people (name, age, city) VALUES (%s, %s, %s)"
for person in data:
cursor.execute(sql, (person['name'], person['age'], person['city']))
connection.commit()
finally:
connection.close()
4-4. NoSQL 저장
MongoDB
- 유연한 스키마, 중첩 구조에 적합
- JSON 형태의 문서 저장
from pymongo import MongoClient
data = [
{'name': 'Alice', 'age': 30, 'city': 'Seoul'},
{'name': 'Bob', 'age': 25, 'city': 'Busan'}
]
client = MongoClient('localhost', 27017)
db = client['mydatabase']
collection = db['people']
collection.insert_many(data)
Redis
- 키-값 저장, 인메모리 기반으로 속도 빠름
- 대용량에는 부적합
import redis
import json
data = [
{'name': 'Alice', 'age': 30, 'city': 'Seoul'},
{'name': 'Bob', 'age': 25, 'city': 'Busan'}
]
r = redis.Redis(host='localhost', port=6379, db=0)
for idx, person in enumerate(data):
r.set(f'person:{idx}', json.dumps(person))
4-5. 대용량 저장소
Hadoop HDFS
- 분산 파일 시스템, 수평 확장 가능
- 설정 및 실시간 처리에는 어려움
hdfs dfs -put data.csv /user/hadoop/data/
Amazon S3
- AWS의 객체 저장소, 인터넷을 통해 접근 가능
- 비용 발생, 네트워크 지연 가능성 있음
import boto3
s3 = boto3.client('s3')
s3.upload_file('data.csv', 'my-bucket', 'data/data.csv')
4-6. 클라우드 데이터베이스
Firebase Realtime Database
- 실시간 동기화 지원, 백엔드 간편 구축
- 관계형 구조에는 부적합
import firebase_admin
from firebase_admin import credentials, db
cred = credentials.Certificate('path/to/serviceAccountKey.json')
firebase_admin.initialize_app(cred, {
'databaseURL': '<https://your-database-name.firebaseio.com/>'
})
ref = db.reference('people')
data = {
'Alice': {'age': 30, 'city': 'Seoul'},
'Bob': {'age': 25, 'city': 'Busan'}
}
ref.set(data)
AWS DynamoDB
- 완전 관리형 NoSQL 서비스
- 확장성 높고, 모델링 복잡 가능성 있음
import boto3
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('people')
data = [
{'name': 'Alice', 'age': 30, 'city': 'Seoul'},
{'name': 'Bob', 'age': 25, 'city': 'Busan'}
]
with table.batch_writer() as batch:
for person in data:
batch.put_item(Item=person)
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- sql 조작문
- database
- mysql 분석 쿼리
- 중첩 쿼리
- sql 고급
- sql 쿼리 최적화
- 카테고리별 합계
- 파이썬 크롤러
- 회고록
- mysql 실습
- api 크롤링
- 데이터 조회 최적화
- Python
- 고유 값
- sql 그룹화
- SQL
- sql 쿼리 합치기
- MySQL
- 다중 열 distinct
- 파생 테이블
- google i/o 2025
- 조건문
- 데이터베이스
- 행 제한
- sql 다중 테이블
- 파이썬
- replace
- select 결과 제어
- 집합 연산
- requests 라이브러리
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
글 보관함