Done:

In Process:

네이버 영화 렌더링 호출 API 탐색

영화 리스트 파싱 로직 작성

Todo:

DB어떻게 짤지 고민하기

개봉 영화 리스트를 사용하려면 영화진흥원 koibs OPEN API를 사용해야 하지만, 퀄리티가 너무 별로라.. 그냥 네이버 파싱해서 사용하기로 했음.

아래 링크처럼

https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=0&ie=utf8&query=%EB%84%A4%EC%9D%B4%EB%B2%84+%EC%98%81%ED%99%94&ackey=lblhy0zf

검색하면 영화 리스트 위젯이 있음.

보통 이런경우는 자바스크립트 코드로 이뤄져 있기에, html을 좀 뒤적거리면 찾을 수 있음.

정확히는 크롬 개발자 도구를 사용하여 Item들이 묶여져 있는 부분을 보고, 그 근처 Script를 참고하였음

두가지 API를 사용할건데

현재상영영화:

https://m.search.naver.com/p/csearch/content/qapirender.nhn?_callback=%ED%98%84%EC%9E%AC%EC%83%81%EC%98%81%EC%98%81%ED%99%94_q&key=MovieAPIforPList&pkid=68&where=nexearch&start=0&display=1000&so=s1.dsc&q=%ED%98%84%EC%9E%AC%EC%83%81%EC%98%81%EC%98%81%ED%99%94

개봉예정영화 :

https://m.search.naver.com/p/csearch/content/qapirender.nhn?_callback=upcoming_q&key=MovieAPIforPList&pkid=68&where=nexearch&so=s2.dsc&q=%EA%B0%9C%EB%B4%89%EC%98%88%EC%A0%95%EC%98%81%ED%99%94&start=0&display=1000

를 사용할거다.

참고로 위 링크는 Json으로 나오는 링크는 아니고, 저기 HTML에 인라인으로 바로 꽂아버리는 스크립트라, 파싱하기가 좀 귀찮게 되어있다.

아래는 파싱 구현. nation은 Kobis API 처리할때 넣을 예정

import requests
import json
from bs4 import BeautifulSoup

class movieInfo:
    def __init__(self, name, release_date, genre, nation, poster_url):
        self.name = name # 영화 이름
        self.release_date = release_date # 개봉일
        self.genre = genre # 장르
        self.nation = nation # 국가
        self.poster_url = poster_url # 포스터 이미지 URL

def getUpcomingMovieList()-> List[movieInfo]:
    url = (
        "https://m.search.naver.com/p/csearch/content/qapirender.nhn?_callback=upcoming_q&key=MovieAPIforPList&pkid=68&where=nexearch&so=s2.dsc&q=%EA%B0%9C%EB%B4%89%EC%98%88%EC%A0%95%EC%98%81%ED%99%94&start=0&display=1000"
    )

    headers = {"User-Agent": "Mozilla/5.0"}
    res = requests.get(url, headers=headers, timeout=5)
    res.raise_for_status()

    # --- JSONP → JSON ---
    text = res.text.strip()
    json_str = text[text.find("(") + 1 : text.rfind(")")]
    json_str = json_str.replace("\\'", "'")  # JS escape 보정
    data = json.loads(json_str)

    movies = []

    for item in data.get("items", []):
        soup = BeautifulSoup(item.get("html", ""), "html.parser")

        # ✅ 핵심 수정: card_item 전체 순회
        for card in soup.select("div.card_item"):

            title = card.select_one("a.this_text")
            dday = card.select_one("span.icon_dday")
            release = card.select_one("dl.info_group.type_visible dd")
            cast = card.select_one("dd.type_ellip_2 span._text")
            img = card.select_one("img")

            info_dd = card.select("dl.info_group dd")
            
            movie_obj = movieInfo(
                name=title.get_text(strip=True) if title else None,
                release_date=release.get_text(strip=True) if release else None,
                genre=info_dd[0].get_text(strip=True) if len(info_dd) > 0 else None,
                nation="정보 없음",
                poster_url=img["src"] if img else None
            )
            movies.append(movie_obj)

        return movies

def getMovieList() -> List[movieInfo]:
    """
    현재 상영 중인 영화 정보를 파싱하여 movieInfo 객체 리스트로 반환합니다.
    Returns:
        List[movieInfo]: 영화 정보 객체 리스트          
    """
    # API URL
    url = "https://m.search.naver.com/p/csearch/content/qapirender.nhn?_callback=%ED%98%84%EC%9E%AC%EC%83%81%EC%98%81%EC%98%81%ED%99%94_q&key=MovieAPIforPList&pkid=68&where=nexearch&start=0&display=1000&so=s1.dsc&q=%ED%98%84%EC%9E%AC%EC%83%81%EC%98%81%EC%98%81%ED%99%94"
    
    # 요청 보내기
    response = requests.get(url)

    # 영화 정보를 담을 리스트
    movies = []

    # 영화 정보 파싱을 위한 함수
    def parsingByStartAndEndWord(startWord, endWord, text):
        startIndex = text.find(startWord) + len(startWord)
        endIndex = text[startIndex:].find(endWord) + startIndex
        return text[startIndex:endIndex], text[endIndex:]

    # 응답 상태 코드 확인
    if response.status_code == 200:
        soup = BeautifulSoup(response.text, 'html.parser')
        total = soup.text.find('total')
        url = url.replace('display=2', 'display=' + str(total))
        response = requests.get(url)
        soup = BeautifulSoup(response.text, 'html.parser')
        # 영화 리스트 파싱
        movie_elements = soup.text.split(r'<\/a>\n \n \n \n ')[1:]
        # 영화 데이터 처리
        for movie_element in movie_elements:
            # 영화 이름 파싱
            endIndex = movie_element.find(r'<\/a>\n <\/div>\n <\/div>\n \n \n ')
            name = movie_element[:endIndex]
            movie_element = movie_element[endIndex:]
            # 영화 카테고리 파싱
            category, movie_element = parsingByStartAndEndWord(r'<\/a>\n <\/div>\n <\/div>\n \n \n 개요<\/dt>\n ', r'<\/dd>\n ', movie_element)
            # 영화 상영시간 파싱 (사용하지 않음)
            _, movie_element = parsingByStartAndEndWord(r'<\/dd>\n ', r'<\/dd>\n ', movie_element)
            # 영화 개봉일 파싱
            release_date, movie_element = parsingByStartAndEndWord(r'<\/dd>\n <\/dl>\n \n\n 개봉<\/dt>\n ', r'<\/dd>\n ', movie_element)
            if release_date.startswith('n'):
                release_date = release_date[2:]
            # 영화 평점 파싱 (사용하지 않음)
            _, movie_element = parsingByStartAndEndWord(r'<\/dd>\n 평점<\/span><\/dt>\n <\/i>', r'<\/span><\/dd>\n ', movie_element)
            # 이미지 URL 파싱
            image_url = None
            image_urls = str(soup).split(r"src='")
            for image in image_urls[1:]:
                url = image.replace(r"amp;", "")
                endIndex = url.find(r"width=")
                image_url = url[2:endIndex-4]
                break  # 첫 번째 이미지만 추가
            # movieInfo 객체 생성 (genre=category, nation="정보 없음" 대입)
            movie_obj = movieInfo(
                name=name.strip(),
                release_date=release_date.strip(),
                genre=category.strip(),
                nation="정보 없음",
                poster_url=image_url if image_url else "이미지를 찾을 수 없습니다."
            )
            movies.append(movie_obj)
    return movies

PS. 개발 중간중간 검색해도 안나오거나, GPT가 모르는 부분 위주로 작성 예정…