작심 24/7

다음 웹툰 크롤링 하기 (BeautifulSoup, Selenium) 본문

크롤링

다음 웹툰 크롤링 하기 (BeautifulSoup, Selenium)

모닝수박 2020. 9. 30. 21:32

네이버 웹툰에 이어 이번에는 다음 웹툰 정보를 가져와보자.

 

내가 수집하고 싶은 정보 : 제목, 작가, 요일, 장르, 줄거리

 

Daum 웹툰

상상이 시작되는 곳 Daum 웹툰

webtoon.daum.net

네이버는 모든 웹툰 리스트를 한번에 볼 수 있게 되어있어서 수월했는데

다음은 요일별로 분리해놔서 조금 더 번거롭게 되어있다.

 

그래서 요일마다 클릭하면서 제목, 작가명과 요일을 수집하고

작품 링크로 들어가서 장르와 줄거리를 수집할 것이다.

 

필요한 모듈들

from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from time import sleep
import pandas as pd

 

요일마다 페이지를 이동하기 위해

기본 url 'http://webtoon.daum.net/' 뒤에

요일에 맞는 주소를 붙여서 이동할 예정이므로 week 리스트를 만들어서

각 요일에 맞는 주소를 저장해주고 월요일부터 일요일까지 순서대로 이동하였다.

url = 'http://webtoon.daum.net/'
week = ['#day=mon&tab=day', '#day=tue&tab=day', '#day=wed&tab=day', '#day=thu&tab=day', '#day=fri&tab=day', '#day=sat&tab=day', '#day=sun&tab=day']
title_list = [] ; id_list = [] ; author_list = [] ;  day_list = []  ; genre_list = [] ; story_list = [] ; platform_list = []
num = 366 # 네이버 웹툰 id가 365까지였음

 

네이버 웹툰과는 다르게 다음 웹툰은

웹툰 리스트들이 자바스크립트로 추가가 되어 있기 때문에

그냥 페이지 소스 보기로 html 코드를 보면 내가 찾는 정보가 나와있지 않고

개발자 도구로 코드를 봐야 한다.

 

그래서 requests로 소스를 가져오면

자바스크립트가 적용되기 전의 html 소스(= 페이지 소스 보기)를 가져오기 때문에

page_source를 이용해서 html소스(= 개발자 도구)를 가져와야 한다.

for i in range(7): #월요일부터 일요일까지
    URL = url + week[i]
    driver = webdriver.Chrome('C:/chromedriver.exe')
    driver.get(URL) #요일별로 링크 가져옴

    sleep(1)

    html = driver.page_source
    soup = BeautifulSoup(html, 'html.parser') # 제목, 작가, 요일 긁어오기 위해 현재 페이지 파싱

 

개발자 도구를 보면

 

현재 페이지에 해당하는 요일의 class명만 'btn_comm link_tab on'이 되어있고

 

제목은 'tit_wt'라는 class명을 가진 <strong> 안에 있고

작가는 'screen_out'이라는 class명을 가진 <span> 안에 있는 걸 알 수 있다.

    title = soup.find_all('strong', {'class': 'tit_wt'}) # 제목 수집
    author = soup.find_all('span', {'class': 'txt_info'}) # 작가 수집
    day = soup.find('a', {'class': 'btn_comm link_tab on'}) # 요일 수집
    p = 0 # 첫 번째 작품 링크부터 들어가기 위해

 

네이버 웹툰은 성인 웹툰이라도 작품 페이지는 로그인 없이 들어갈 수 있었지만

다음은 로그인이 무조건 필요했다.

로그인하는 코드를 구현하면 되지만

굳이 필요하지 않아서 그냥 '성인'이라 표시돼 있으면 넘기게 하였다.

 

그리고 요일이 두 개 이상인 웹툰도

요일만 추가해주고 넘겼다.

    for j in range(len(title)):
        t = title[j].text
        if (t[:2] == '성인'): # 성인 웹툰이면 넘어감
            p += 1
            continue
        elif (t in title_list): # 요일 두 개 이상이면 요일만 추가하고 넘어감
            day_list[title_list.index(t)] += ', ' + day.text
            p += 1
            continue

        id_list.append(num) ; num += 1 # id 리스트에 추가
        title_list.append(t) # 제목 리스트에 추가
        author_list.append(author[j].text[3:]) # 작가 리스트에 추가
        day_list.append(day.text) # 요일 리스트에 추가
        platform_list.append('다음 웹툰') # 플랫폼 리스트에 추가

 

이번 크롤링에서 가장 중요한 부분이다.

sleep(0.5)만 해도 중단 없이 빠르게 실행되던 네이버 웹툰과 달리,

다음 웹툰은 페이지를 이동하고 돌아오면서 로딩이 상당히 길어지는 경우가 많았다.

그래서 자꾸 빈 소스를 가져오고 중단되길래

 

1. 무조건 n초를 기다리는 sleep(n)

2. 페이치 호출이 될 때까지 최대 n초를 기다리는 implicitly_wait(n)

3. 특정 조건을 만족할 때까지 최대 n초까지 기다리는 Explicitly wait

 

이 세 가지 방법 중 가장 확실한 3번 방법인

selenium에서 제공하는 Explicitly wait를 사용하였다.

 

각 작품 링크를 들어가기 위해 'link_wt'라는 class명을 가진 <a>가 필요하기 때문에

class명이 'link_wt'인 모든 elements들이 나올 때까지

최대 15초를 기다려 달라는 코드를 작성하였다.

        page = WebDriverWait(driver, 15).until( # 필요한 데이터가 다 로딩될 때까지 최대 15초 기다려줌
            EC.presence_of_all_elements_located(
                (By.CLASS_NAME, "link_wt")
            )
        )[:-10] # 밑에 있는 랭킹 10개는 가져올 필요 없음

        page[p].click()
        p += 1

 

작품 링크를 들어가면

장르와 줄거리가 있는 이 부분을 주목해야 한다.

 

개발자 도구를 보면

 

'txt_genre'이라는 class명을 가진 <dt> 안에 장르가 있고

'txt_story'라는 class명을 가진 <dd> 안에 줄거리가 있는 것을 알 수 있다.

 

마찬가지로

페이지를 클릭하고 나서도 원하는 정보인 장르가 다 로딩될 때까지

최대 10초를 기다려 달라는 코드를 작성해주고 각 정보를 수집해준 뒤

driver.back()으로 뒤로가기 해준다.

        WebDriverWait(driver, 10).until(
            EC.presence_of_element_located(
                (By.CLASS_NAME, 'txt_genre')
            )
        )

        html =  driver.page_source
        soup = BeautifulSoup(html, 'html.parser') #장르, 줄거리 가져오기 위해 현재 페이지 파싱

        genre = soup.find('dd', {'class': 'txt_genre'}).text.strip() # 장르 수집 (strip은 개행 제거 함수)
        genre_list.append(genre) # 장르 리스트에 추가

        story = soup.find('dd', {'class' : 'txt_story'}).text # 줄거리 수집
        story_list.append(story) # 줄거리 리스트에 추가

        driver.back()

        sleep(3)

 

데이터 수집이 다 끝났으면

pandas를 이용해 DataFrame을 만들고

정보가 저장돼 있는 리스트를 추가해주고

to_csv로 csv파일을 생성해준다.

total_data = pd.DataFrame()
total_data['id'] = id_list
total_data['title'] = title_list
total_data['author'] = author_list
total_data['day'] = day_list
total_data['genre'] = genre_list
total_data['story'] = story_list
total_data['platform'] = platform_list
total_data.to_csv('다음_웹툰.csv', encoding='utf-8-sig')

 

그러면 이렇게 예쁘게 정리된 csv파일을 얻을 수 있다.

 

 

'크롤링' 카테고리의 다른 글

네이버 웹툰 크롤링 하기 (BeautifulSoup, Selenium)  (0) 2020.09.28
Comments