Django

Django 실습(1) 핫딜 크롤링해서 상품 사이트 만들기

UserDonghu 2023. 10. 5. 23:54

https://userdonghu.tistory.com/entry/Django-%ED%8A%9C%ED%86%A0%EB%A6%AC%EC%96%BC

 

Django 튜토리얼

Python 설치 이후. Django 프로젝트 파일 열기. mkdir mysite 로 폴더 만들고 cd mysite로 이동하기. python -m venv venv # 가상환경 설정. 뒤가 이름 source ./venv/bin/activate # 가상환경 실행 pip install django # 장고 설

userdonghu.tistory.com

Django 튜토리얼을 통해서 mysite 폴더 안에 가상환경을 구성하고 django 설치, startproject, runserver까지 하기.

 

 

python manage.py startapp 으로 main, accounts, product 앱 생성

 

hotdealproject / settings.py에 INSTALLED_APPS에 앱 추가

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "main",
    "product",
    "accounts",
]

 

hotdealproject / urls.py 에 url패턴 추가

from django.contrib import admin
from django.urls import path, include # include 추가

urlpatterns = [
    path("admin/", admin.site.urls),
    path("", include('main.urls')),
    path("product/", include('product.urls')), # product/로 시작하는 주소를 받으면 product폴더에 urls.py를 보겠다.
    path("accounts/", include('accounts.urls')),
]

 

각 app폴더들에 urls.py 파일 추가하기.

 

main앱 먼저 수정.

main / urls.py 에 url패턴 추가

from django.urls import path # path 함수 import
from . import views # views.py 파일 import

app_name = 'main' # 앱의 네임스페이스 설정

urlpatterns = [
    path('', views.index, name='index'), # 127.0.0.1:8000/ 주소에서 views.py의 index함수를 호출하겠다.
    path('about/', views.about, name='about'),
    path('contact/', views.contact, name='contact'),
]

 

main / views.py 에 함수 정의

from django.shortcuts import render

def index(request):
    return render(request, 'main/index.html') # templates/main/index.html을 보여준다.

def about(request):
    return render(request, 'main/about.html')

def contact(request):
    return render(request, 'main/contact.html')

 

 

main / templates / main 안에 html 파일 생성

 

accounts앱과 product앱도 같은 방식으로 수정.

 

product / urls.py 는 ~/product/1, ~/product/2 ... 처럼 상품의 번호로 url을 설정하기 위해서 <int:pk>/ 사용.

from django.urls import path
from . import views

app_name = 'product'

urlpatterns = [
    path('', views.index, name='index'),
    path('<int:pk>/', views.product, name='product'), # product/1, product/2... 와 같이 들어올때
]

 

urls의 <int:pk>를 views에서 이렇게 보냄

from django.shortcuts import render

def index(request):
    return render(request, 'product/index.html')

def product(request, pk): # pk를 인자로 넣어서
    return render(request, 'product/product.html', {'no': pk}) # 항상 딕셔너리 형태로 html에 보냄

 

product / templates / product / product.html 에서는 이렇게 사용

<h1>{{no}}번째 상품</h1> 
<!-- product/2 이면 2번째 상품, product/4 면 4번째 상품 -->

<a href="{% url 'product:index' %}">상품 목록 페이지로 가기</a> 
<!-- urls에서 네임스페이스 product의 name='index'인 path호출 -->

 

python manage.py runserver 를 하고,

127.0.0.1:8000/

127.0.0.1:8000/about

127.0.0.1:8000/contact

127.0.0.1:8000/accounts

127.0.0.1:8000/accounts/login

127.0.0.1:8000/accounts/logout

127.0.0.1:8000/product

127.0.0.1:8000/product/1

127.0.0.1:8000/product/5

다 잘 나오는지 확인.

 

크롤링해서 상품 정보 가져오기

pip install requests, pip install bs4 로 크롤링할 모듈 설치

 

BeautifulSoup으로 핫딜 게시판을 크롤링한 코드를 조금 수정해서 사용.

https://userdonghu.tistory.com/entry/Python-%EC%8B%A4%EC%8A%B5-%ED%95%AB%EB%94%9C-%ED%81%AC%EB%A1%A4%EB%A7%81-%ED%95%B4%EB%B3%B4%EA%B8%B0

 

Python 실습 - 핫딜 크롤링 해보기

원래 목표는 핫딜 게시판을 크롤링하는 py파일을 만들어서 그걸 매 시간 정각마다 실행되도록 외부 서버를 이용한 후, 만약 새 글이 올라왔으면 나에게 알림을 보내는 것이었지만 아직 그렇게

userdonghu.tistory.com

 

product / views.py 에서 크롤링 코드로 상품DB 만들어서 html로 보내기

from django.shortcuts import render
from django.http import HttpResponse # 간단한 오류페이지 구현을 위해 import
import requests
from bs4 import BeautifulSoup
import re

mykeyword = '애플워치' # 검색하고싶은 키워드
res = requests.get(f'https://www.fmkorea.com/search.php?mid=hotdeal&category=1196845148&listStyle=webzine&search_keyword={mykeyword}&search_target=title') # 가전제품 카테고리에서 제목 검색
res.raise_for_status() # 200(정상)이 아니면 오류 발생

html = res.text
soup = BeautifulSoup(html, 'html.parser')

productDB = {} # 상품 DB 만들기
productcount = 0 # 상품 개수 count

productlist = soup.select('#content>.content_dummy>div>div>div>ul>li')

for container in productlist:
    productcount += 1 # 상품 개수 + 1

    title = container.select('.title a')[0].text.strip()
    title = re.sub(r'\t|\xa0|\[\d+\]', '', title)

    price = container.select('.hotdeal_info>span')[1].select('.strong')[0].text

    productDB[productcount] = {'title': title, 'price': price} # DB에 1: {'title': 상품1, 'price': 100원} 이런식으로 넣음

def index(request):
    return render(request, 'product/index.html', {'productDB': productDB}) # 딕셔너리 productDB로 index.html에 보내기

def product(request, pk):
    if productDB.get(pk): # DB에 상품이 있으면
        return render(request, 'product/product.html', {'no': pk, 'product': productDB.get(pk)}) # 딕셔너리로 pk는 no로 보내고 DB의 pk번째 상품은 product로 보냄
    else: # DB에 없으면
        return HttpResponse('잘못된 접근입니다.') # 간단한 오류페이지 보여주기

 

product / templates / product / index.html

<h1>상품 목록 페이지 입니다.</h1>
<a href="{% url 'main:index' %}">메인 페이지로 가기</a>

<!-- django templates launguage 사용해서 for문으로 DB에서 key와 value뽑아서 보여주기 -->
{% for i, j in productDB.items %}
<p><a href="./{{i}}">{{i}} : {{j.title}}</a></p>
{% endfor %}

 

product / templates / product / product.html

<h1>{{no}}번째 상품</h1> 
<!-- product/2 이면 2번째 상품, product/4 면 4번째 상품 -->
<a href="{% url 'product:index' %}">상품 목록 페이지로 가기</a> 
<!-- urls에서 네임스페이스 product의  name='index'인 path호출 -->
<p>이름 : {{product.title}}</p>
<p>가격 : {{product.price}}</p>
<p>~상세정보~</p>

 

결과

 

메인 페이지와 about, contact, product, accounts, login, logout 다 잘 작동.

 

product 페이지에 크롤링해온 핫딜 목록을 출력

 

링크 누르면 해당되는 product/번호 페이지로 이동해서 상세정보 보여줌

 

DB에 있는 상품 개수를 넘는 번호 product/100 으로 가면 잘못된 접근이라고 나옴

크롤링 키워드 수정해가면서 product 새로고침하니까 재밌다.

 

Django를 이용한 간단한 실습 끗