Nonamed Develog
[TIL][240910] Django와 웹 크롤링 본문
웹 크롤링이란?
웹 크롤링은 프로그램을 통해 웹사이트를 자동으로 탐색하고, 그 안에서 데이터를 추출하는 과정을 의미한다. 이 작업은 "크롤러" 또는 "스파이더"라 불리는 스크립트에 의해 수행되며, 크롤러는 웹 페이지의 링크를 따라가며 데이터를 수집한다. 주로 분석, 모니터링, 데이터베이스에 정보를 저장하는 등의 목적으로 사용된다.
웹 크롤링의 주요 개념
- 요청(Requests): 크롤러는 HTTP 요청을 통해 웹 페이지의 내용을 가져온다. Python에서는 주로 requests 라이브러리를 사용해 웹 페이지에 요청을 보낸다.
- 파싱(Parsing): HTML을 가져온 후, 이를 분석하고 필요한 데이터를 추출한다. BeautifulSoup(bs4) 또는 lxml과 같은 라이브러리를 사용해 HTML 구조를 파싱한다.
- 탐색: 크롤러는 HTML에서 찾은 링크를 따라가며 다른 페이지를 탐색하여 데이터 수집을 진행한다.
- 속도 조절(Rate Limiting): 웹 크롤링 시 서버에 부담을 주지 않기 위해 너무 많은 요청을 짧은 시간 안에 보내지 않도록 속도를 조절해야 한다. robots.txt 파일의 규칙을 준수하여 서버에 부담을 주지 않도록 해야 한다.
- 데이터 저장: 수집한 데이터를 파일(CSV, JSON)이나 데이터베이스(SQL, NoSQL)에 저장할 수 있다.
Django에서 웹 크롤링을 활용하는 방법
Django는 주로 웹 개발에 사용되지만, 크롤링한 데이터를 자동으로 Django 애플리케이션에 삽입하는 데에도 사용할 수 있다. Django의 데이터베이스 모델, 관리 명령, 스케줄링 기능을 활용하여 크롤링한 데이터를 처리할 수 있다.
Django에서 웹 크롤링을 구현하는 이론적인 단계
크롤링 목적 정의: 먼저 어떤 데이터를 수집하고 그 데이터를 Django 프로젝트에서 어떻게 사용할지를 명확히 정해야 한다. 예를 들어, 전자 상거래 웹사이트의 상품 데이터를 수집하거나, 다양한 뉴스 웹사이트에서 블로그 게시물을 추출할 수 있다.
Django 모델 설정: 크롤링한 데이터를 저장할 모델을 models.py에 정의한다. 예를 들어, 상품 데이터를 수집하는 경우, 아래와 같이 Product 모델을 정의할 수 있다.
class Product(models.Model):
title = models.CharField(max_length=255)
price = models.DecimalField(max_digits=10, decimal_places=2)
description = models.TextField()
image_url = models.URLField()
source_url = models.URLField()
def __str__(self):
return self.title
크롤러 로직 작성 (독립 스크립트 또는 Django 관리 명령): Python의 requests와 BeautifulSoup 같은 라이브러리를 사용해 웹 페이지를 가져오고 파싱한다. 이를 독립된 Python 스크립트로 작성할 수 있지만, Django와 통합하려면 관리 명령(management command) 형태로 작성하는 것이 좋다.
import requests
from bs4 import BeautifulSoup
from django.core.management.base import BaseCommand
from products.models import Product
class Command(BaseCommand):
help = '웹사이트에서 상품 데이터를 크롤링합니다.'
def handle(self, *args, **kwargs):
url = 'https://example.com/products'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
for product in soup.find_all('div', class_='product'):
title = product.find('h2').text
price = product.find('span', class_='price').text
description = product.find('p', class_='description').text
image_url = product.find('img')['src']
source_url = product.find('a')['href']
# Django 모델에 데이터 저장
Product.objects.create(
title=title,
price=price,
description=description,
image_url=image_url,
source_url=source_url
)
self.stdout.write(self.style.SUCCESS(f'{title} 크롤링 성공'))
이 스크립트는 특정 URL에서 제품 목록을 가져와 HTML을 파싱한 후, Django의 Product 모델에 데이터를 저장한다.
크롤링 프로세스 스케줄링: Django는 기본적으로 작업 스케줄링 기능이 포함되어 있지 않지만, Celery(비동기 작업 처리용) 또는 크론(cron) 작업(유닉스 기반 시스템)을 사용해 크롤링 작업을 정기적으로 실행할 수 있다.
0 3 * * * /path/to/virtualenv/bin/python /path/to/django/manage.py crawl_products
또는 분산 작업 처리가 필요한 경우 Django Q나 Celery를 사용할 수도 있다.
크롤링한 데이터 뷰에서 처리하기: 크롤링한 데이터를 Django 모델에 저장한 후, 이를 웹 페이지에서 보여주려면 뷰에서 해당 데이터를 쿼리해야 한다. Django의 클래스 기반 뷰(CBVs)나 함수 기반 뷰(FBVs)를 사용해 저장된 데이터를 웹 페이지에 표시할 수 있다.
from django.shortcuts import render
from products.models import Product
def product_list(request):
products = Product.objects.all()
return render(request, 'products/product_list.html', {'products': products})
대규모 크롤링 처리: 대규모 웹 크롤링 작업이 필요하다면, Scrapy와 같은 크롤링 프레임워크를 사용하는 것이 더 효율적일 수 있다. Scrapy는 다중 스레드를 사용해 크롤링을 병렬로 처리할 수 있어 성능이 뛰어나며, Django와 통합하여 모델에 데이터를 저장하거나 API로 데이터를 전송할 수 있다.
윤리적인 웹 크롤링 고려 사항
- robots.txt 파일 준수: 크롤링을 하기 전, 해당 웹사이트의 robots.txt 파일을 확인하여 크롤링 규칙을 준수해야 한다.
- 서버 과부하 방지: 시간 간격을 두고 요청을 보내 서버에 과도한 부담을 주지 않도록 해야 한다. Python의 time.sleep()을 사용하거나 Scrapy의 속도 조절 기능을 활용할 수 있다.
- 페이징 처리: 많은 웹사이트가 콘텐츠 목록을 페이징 처리한다. 크롤러가 페이지 내비게이션을 처리할 수 있도록 다음 링크를 따라가거나 특정 페이징 요소를 파싱하는 기능을 구현해야 한다.
'WHAT I LEARN > TIL' 카테고리의 다른 글
[TIL][240912] Pull Request와 Local Merge (1) | 2024.09.13 |
---|---|
[TIL][240911] 프로젝트 시작, 끝 없는 문서 작성...(SA) (1) | 2024.09.11 |
[TIL][240906] Troubleshooting 3: url routing의 순서 (0) | 2024.09.09 |
[TIL][240906] Troubleshooting 2: 중복된 코드의 냄새 (0) | 2024.09.06 |
[TIL][240905] RefreshToken 속 check_blacklist() (0) | 2024.09.05 |