ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2023.5.15 ~ 2023.5.21 공부일지 (크롤링 - 3) [코드풀이]
    [Python] 2023. 5. 22. 14:33

    코드를 싸아악 갈았다. 그래서 저번에 소개해준 BeautifulSoup 내용은 요번엔 아쉽게도 사용하지 못하게 되었다.

     

    드디어 네이버 웹툰을 크롤링 해보았다.

    필자는 spider 를 사용하였다.

     

    코드를 먼저 살펴보겠다.

    import openpyxl
    import requests
    from tqdm import tqdm
    import time
    
    
    def series_info(series_id):
        '''시리즈ID를 입력받아, 장르와 관심수를 반환한다'''
        series_info_url = 'https://comic.naver.com/api/article/list/info?titleId=' + str(series_id)
        series_res = requests.get(series_info_url)
        series_info = series_res.json()
    
        try: 
            favorite_count = series_info['favoriteCount']
            genre = [genre['tagName'] for genre in series_info['curationTagList'] if genre['curationType'][:6] == 'GENRE_'][0]
        except: # 성인작품은 로그인 필요하여 에러 발생함
            favorite_count = None
            genre = None
        return favorite_count, genre
    
    def episode_info(series_id):
        '''시리즈ID를 입력받아, 에피소드개수와 완결일을 반환한다'''
        episode_info_url = 'https://comic.naver.com/api/article/list?titleId=' + str(series_id) + '&page=1&sort=DESC'
        episode_res = requests.get(episode_info_url)
        episode_info = episode_res.json()
        
        try:
            epi_cnt = episode_info['totalCount']
            completed_date = episode_info['articleList'][0]['serviceDateDescription']
        except: # 성인작품은 로그인 필요하여 에러 발생함
            epi_cnt = None
            completed_date = None
        return epi_cnt, completed_date
    
    
    ## 완결작 ## 최대 페이지 수정 필요
    
    start_page = 1
    last_page = 40
    
    wb = openpyxl.Workbook()
    ws = wb.active
    ws.append([
        'series_id', 'series_title', 'author', 'is_adult', 'star_score', 'favorite_count', 'genre', 'epi_cnt', 'completed_date'
    ])
    
    for page in tqdm(range(start_page, last_page + 1)):
        time.sleep(1)
    
        url = 'https://comic.naver.com/api/webtoon/titlelist/finished?page=' + str(page) + '&pageSize=45&order=UPDATE'
        res = requests.get(url)
        contents = res.json()['titleList']
        
        # 요청 실패 시 처리
        if res.status_code != 200:
            print(str(page) + '_' + str(res.status_code))
            continue
        
        # 파싱
        for content in contents:
            series_id = content['titleId']
            series_title = content['titleName']
            author = content['author']
            adult = content['adult']
            star_score = content['starScore']
            
            favorite_count, genre = series_info(series_id)
            epi_cnt, completed_date = episode_info(series_id)
            
            ws.append([
                series_id, series_title, author, adult, star_score, favorite_count, genre, epi_cnt, completed_date
            ])
    
    wb.save('네이버웹툰_완결작.xlsx')
    
    
    ## 요일연재
    
    wb = openpyxl.Workbook()
    ws = wb.active
    ws.append([
        'series_id', 'series_title', 'author', 'is_adult', 'star_score', 'day'
    ])
    
    
    url = 'https://comic.naver.com/api/webtoon/titlelist/weekday?order=user'
    res = requests.get(url)
    contents = res.json()['titleListMap']
    
    
    for day in contents.keys():
        for content in contents[day]:
    
            series_id = content['titleId']
            series_title = content['titleName']
            author = content['author']
            adult = content['adult']
            star_score = content['starScore']
            day_ = day
    
            ws.append([
                series_id, series_title, author, adult, star_score, day_
            ])
    wb.save('네이버웹툰_연재_요일연재.xlsx')
    
    
    ## 매일연재
    
    wb = openpyxl.Workbook()
    ws = wb.active
    ws.append([
        'series_id', 'series_title', 'author', 'is_adult', 'star_score'
    ])
    
    
    url = 'https://comic.naver.com/api/webtoon/titlelist/weekday?week=dailyPlus&order=user'
    res = requests.get(url)
    contents = res.json()['titleList']
    
    # 파싱
    for content in contents:
        series_id = content['titleId']
        series_title = content['titleName']
        author = content['author']
        adult = content['adult']
        star_score = content['starScore']
    
        ws.append([
            series_id, series_title, author, adult, star_score
        ])
    
    wb.save('네이버웹툰_연재_매일플러스.xlsx')

     

    1. series_info (series_id) 함수

    : 시리즈ID를 입력받아 해당 웹쿤의 장르와 관심수를 반환하는 함수이다. 시리즈 정보를 가져오기 위해 API를 호출하고, JSON 응답을 파싱하여 장르와 관심수를 추출한다. 

     

    2. episode_info (series_id) 함수

    : 시리즈ID를 입력받아 해당 웹툰의 에피소드 개수와 완결일을 반환하는 함수입니다. 에피소드 정보를 가져오기 위해 API 를 호출하고, JSON 응답을 파싱하여 에피소드 개수와 완결일을 추출한다. 

     

    3. 완결작 크롤링

    : start_page 부터 last_page 까지의 페이지를 순회하며 완결작을 크롤링한다. 각 페이지의 API를 호출하여 완결작의 정보를 가져오고, 엑셀 파일에 기록한다. series_info 함수와 episode_info 함수를 활용하여 관심수, 장르, 에피소드 개수, 완결일을 추출한다. 

     

    4. 요일 연재작 크롤링

    : 각 요일별로 연재되는 작품 목록을 크롤링 한다. API 를 호출하여 요일별 작품 정보를 가져오고, 엑셀 파일에 기록한다. 각 작품의 시리즈ID, 제목, 작가, 성인 여부, 별점을 추출하여 기록한다.

     

    5. 매일 연재작 크롤링

    : 매일 연재되는 작품 목록을 크롤링 한다. API 를 호출하여 매일 연재작 정보를 가져오고, 엑셀 파일에 기록하고 다음은 4번과 같다.

     

    위의 코드를 실행하면 각각 "네이버웹툰_완결작.xlsx", "네이버웹툰_연재_요일연재.xlsx", "네이버웹툰_연재_매일플러스_xlsx" 파일에 해당 정보가 저장된다.

     

    tqdm 사용법

    (다음에 다시 제대로 정리해보는 시간을 가질 예정) 

     

     

    파이썬에서 반복 루프를 돌다 보면 징행이 얼마나 되었는지 progress Bar 를 통해 알수 있다. 

     

    이처럼 반복문에서 진행률을 Progress Bar 로 표현해주고 남은 시간 정보까지 알렺는 것이 바로 tqdm 이다.

     

    1. 기본적인 사용법

    tqdm은 순회가능한 객체 (리스트, 튜플, 이터레이터) 를 첫 번째 인자로 넣어주고 for 문에 삽입하면 된다.

     

    from tqdm import tqdm
    import time
     
    for i in tqdm(range(10)): ## tqdm 첫 번째 인자에 순회가능한 객체 전달
        time.sleep(0.01)

     

    pbar = tqdm(range(10)) ## tqdm 객체 생성
    for i in pbar:
        time.sleep(0.01)
    pbar.close() ## 반복이 끝나고 close 사용 강력 권장

    다음과 같이 변수에 할당해서 사용할 수 있다.

     

     

     

    Description

    Progress Bar 폭 / 모양

     

     

    def 란 무엇인가?

    파이썬에서 def 는 함수를 정의하는 키워드이다. 

    함수는 재사용 가능한 코드 블록으로, 특정 작업을 수행하거나 값을 반홚나는 등의 역할을 한다. 

    def 를 사용하여 함수를 정의하면 해당 함수를 호출하여 필요한 작업을 수행할 수 있다.

     

    함수 정의의 기본 구조는 다음과 같다. 

    def 함수이름(매개변수):
        # 함수의 기능 구현
        # 필요한 작업 수행
        # 반환 값이 있다면 반환
    
    # 예시
    def greet(name):
        print("안녕하세요, " + name + "님!")
    
    # 함수 호출
    greet("홍길동")

    위의 예시에서 'greet' 함수는 'name' 이라는 하나의 매개변수를 받는다.

    함수 내부에서는 받은 'name'을 활용하여 인사말을 출력한다.

    이후 함수를 호출할 때 "홍길동" 을 인자로 전달하면 

    " 안녕하세요, 홍길동님! " 이 출력되는 것이다.

     

    함수 정의에는 매개변수가 있을 수도 있고 없을 수도 있다. 매개변수는 함수에 전달되는 값으로 함수 내부에서 활용될 수 있다. 함구가 값을 반환해야 한다면 'return' 문을 사용하여 반환할 수 있다. 

     

    간단한 예시 하나를 더 보겠다.

    def add_numbers(a, b):
        result = a + b
        return result
    
    sum = add_numbers(3, 5)
    print(sum)  # 출력: 8

    위의 예시에서 'add_numbers' 함수는 'a' 와 'b' 라는 두 개의 매개변수를 받는다. 

    두 값을 더한 후 'return' 문을 사용하여 결과를 반환한다. 

    함수를 호출할 때 3 과 5를 인자로 전달하면 반환된 결과값인 8이 변수 'sum'에 저장되고 출력된다.

     

    파이썬에서 뿐만 아니라 다른 언어에서도 함수는 코드의 재사용성과 모듈화를 높혀주는 중요한 개념이다. 

    함수를 정의하여 비슷한 작업을 반복하지 않고 효율적으로 코드를 구성할 수 있다.

     

    + 함수 사용하는 것에 익숙해지고 주석 다는 것을 습관화 하자!

     


    글 수정하다가 날라가서 두 번째 작성 중..

     

    프로그램의 실행 결과가 궁금하시다는 형님들이 많아서 내용을 추가할려고 합니다.

     

    위의 코드를 실행했을 때

    코드에서 import 한 tqdm 덕분에 오른쪽 콘솔창에 보면 진행 상황이 나오게 된다.

     

    그리고 콘솔창 위를 보면 "네이버웹툰_연재_매일플러스.xlsx", "네이버웹툰_연재_요일연재.xlsx", "네이버웹툰_완결작.xlsx" 이렇게 세 개의 파일이 생성된 것을 볼 수 있다. 

     

    "네이버웹툰_연재_매일플러스.xlsx"

     

    이렇게 series_id / series_title / author / is_adult / star_score 이 차례대로 125개의 웹툰이 정리되어 있다. 

     

     

     

    "네이버웹툰_연재_요일연재.xlsx"

    이 밑으로 백여개 넘게 더 있지만 생략하겠다.

     

    네이버웹툰_연재_매일플러스와 다른 점은 어느 요일에 올라오는 웹툰인지까지 저장되어 있다는 점이다. 

     

     

    "네이버웹툰_완결작.xlsx"

    series_id / series_title / author / is_adult / star_score / favorite_count / genre (장르) / epi_cnt (몇화까지 있는지) / completed_date 가 정리되어 있다. 

     

     

    이상 크롤링 결과물이였습니다.

     

    다음에는 클론 코딩이 아닌 직접 다 짜보는게 목표입니다!

     

     

Designed by Tistory.