Code States

Product Management Research #9 (Python - Crawling / HTML)

Narks 2023. 5. 18. 21:14

데이터 수집에 관해 얘기를 하며

크롤링이라는 얘기를 잠깐 언급했었다.

법적인 문제야 둘째 치고라도...

 

기업 내부의 데이터를 직접 볼 수 없는 사람이라면

외부에서 그 정보를 수집해야만 하는데,

코딩의 코자도 모르는 사람이라도 

Python과 Html을 조금만 찾아보면

간단한 데이터는 긁어올 수 있다.

 

웹툰 시장에서 인기 있는 작품을 보기 위해

Naver Webtoon에 나와있는 정보를 긁어와 보도록 하자.

 

긁는것도 막 긁으면 안된다

 

 

실행하기에 앞서 준비물이 몇 가지 있는데,

자료를 긁어와서 나눠줄 Python과

Beautifulsoup이라는 라이브러리,

그리고 Selenium이라는 패키지를 설치해야 한다.

사용하는 웹 버전에 맞는 Webdriver도 필수다.

(파이썬, 라이브러리 등은 잘 모르면 일단 넘어가자)

(그리고 구글 검색은 신이다.)

 

준비는 완료되었다고 가정하고 ,

일단 Naver Webtoon 홈페이지에 들어가서

F12를 누르면 아래와 같은 화면을 볼 수 있다.

 

벌써 머리가 아프다

 

우리가 원하는 건 서비스 중인 전체 시리즈이므로

ORIGINAL로 들어가 보도록 하자.

 

Webtoon - ORIGINALS

 

여기서부터 HTML 지식이 조금 필요한데

HTML은 Tag라는 녀석을 사용한다는 것만 기억하자.

 

 

Webtoon - unOrdinary

 

Ctrl + Shift + C를 누르면 Inspector라는 녀석이

자동으로 웹페이지의 요소를 표시해 준다.

unOrdinary라는 시리즈의 박스는 

<a href = 으로 시작하는 부분을 알 수 있다.

 

Webtoon - I Was the Final Boss

 

이번에는 I Was the Final Boss라는 시리즈다.

역시나 <a href로 시작하고 있다.

 

어라? 뭔가 공통점이 있지 않은가?

사람은 눈치가 빨라야 한다.

박스 안에는 모두 a라는 녀석과

href뒤에 누가 봐도 웹툰 시리즈 링크가 있다.

 

그렇다면!!!

파이썬으로 HTML에서 a라는 녀석을 찾거나

그 위에 <li>라는 녀석을 찾으면

관련 자료를 다 가져올 수 있을 것이다.

 

개발을 하는 사람도 결국 사람이고

코드를 정리하려면 규칙이라는 게 있을 수밖에 없다.

HTML의 태그나 속성 같은 건 자세히 몰라도

규칙만 찾으면 자료를 찾을 수 있다는 것.

 

이제 파이썬으로 a라는 녀석을 긁어와 볼 차례다.

Beautifulsoup과 Selenium이라는 녀석들이

아래와 같이 입력하면 알아서 페이지로 이동해서

내용을 가져와줄 것이다.

 

import requests
from bs4 import BeautifulSoup

url = 'https://www.webtoons.com/en/dailySchedule'
response = requests.get(url)

if response.status_code == 200:
    html = response.text
    soup = BeautifulSoup(html, 'html.parser')
    a_tag = soup.select('a')
    print(a_tag)

 

a_tag

 

문제가 발생하고 말았다.

우리가 원하는 건 시리즈와 url 등이지

페이지 내의 모든 정보는 아니었다.

 

그럼 시리즈 제목을 찾으려면 어떻게 해야 할까?

다시 Ctrl + Shift + C를 눌러 Inspector로

시리즈 제목을 보자.

 

subj

 

이 녀석은 <p로 시작하고 class는 subj라고 되어있다.

아무리 봐도 subj는 시리즈의 제목 같아 보이지 않는가?

 

<p class="subj">unOrdinary</p>라는 부분을 우클릭하여

selector라는 녀석을 Copy 하게 되면

CSS selector를 알 수 있다.

 

 

CSS selector

 

#dailyList > div.daily_section._list_THURSDAY.on > ul > li:nth-child(1) > a > div > p.subj

 

역시나 p가 있고 p.subj로 확인된다.

자 그럼 파이썬에서 p.subj를 모두 가져오면

과연 어떻게 될까?

 

import requests
from bs4 import BeautifulSoup

url = 'https://www.webtoons.com/en/dailySchedule'
response = requests.get(url)
# print(response.status_code)

if response.status_code == 200:
    html = response.text
    soup = BeautifulSoup(html, 'html.parser')
    title = soup.select('p.subj')
    print(title)

 

p.subj

 

성공이다!

제목만 추려서 모두 가져온 모습이 보인다.

여기서 조금 더 발전시켜서 작가와 장르 등

필요한 부분을 모두 가져올 수 있다.

 

import requests
from bs4 import BeautifulSoup

url = 'https://www.webtoons.com/en/dailySchedule'
response = requests.get(url)
# print(response.status_code)

if response.status_code == 200:
    html = response.text
    soup = BeautifulSoup(html, 'html.parser')
    title = soup.select('p.subj')
    author = soup.select('p.author')
    genre = soup.select('p.genre')
    like_grade = soup.select('em.grade_num')

 

그런데 우리는 하나의 페이지 내에서 

시리즈의 세부내용이나 에피소드 개수 혹은

구독자 수를 알 수는 없다.

그럼 어떻게 해야 할까?

 

처음에 a 태그를 통해 가져온 내용에는

url이 포함되어있었으니,

해당 url로 이동하면 시리즈가 나올 것이고

해당 페이지에서 필요한 내용을 덧붙이면

우리가 원하는 자료를 완성할 수 있을 것이다.

 

그렇다면 다시 a 태그로 돌아가보자.

 

<a href="https://www.webtoons.com/en/super-hero/unordinary/list?title_no=679" class="daily_card_item NPI=a:list,i=679,r=1,g:en_en" data-title-unsuitable-for-children="false" data-title-unsuitable-for-children-skin="harmful_white_skin1">
												<img src="https://webtoon-phinf.pstatic.net/20220201_169/16436787350192trlC_JPEG/4unOrdinary_Return_desktop_thumbnail_2.jpg?type=a138" width="138" height="138" alt="unOrdinary">
												<p class="genre g_super_hero">Superhero</p>
												<div class="info">
													<p class="subj">unOrdinary</p>
													<p class="author">uru-chan</p>
													<p class="icon_area"><span class="txt_ico_up2">UP</span></p>
												</div>
												<p class="grade_area"><span class="ico_like3">like</span><em class="grade_num">58.1M</em></p>
											</a>

 

a 태그 안에서 href라는 녀석 뒤에 url이 들어가 있다.

HTML에서 attribute라는 녀석이 있는데,

이 속성값이 href라는 hypertext reference의 약자라는 뜻이다.

 

잘 모르겠다고? 그러려니 하자.

어쨌든 href라는 녀석만 따로 뽑는다는 게 중요하다.

 

파이썬에서는 a 태그라는 녀석 안에,

href를 가진 값 중에서도

정상적인 링크를 가지지 않은

필요 없는 녀석들을 제외한 뒤

링크만 목록으로 쏙쏙 집어넣어줄 것이다.

 

lst_url_link = []

import requests
from bs4 import BeautifulSoup

url = 'https://www.webtoons.com/en/dailySchedule'
response = requests.get(url)
# print(response.status_code)

if response.status_code == 200:
    html = response.text
    soup = BeautifulSoup(html, 'html.parser')
    title = soup.select('p.subj')
    author = soup.select('p.author')
    genre = soup.select('p.genre')
    like_grade = soup.select('em.grade_num')

    a_tag = soup.select('a')
    for n in a_tag:
        link = n.attrs['href']
        if not 'list?title' in link:
         continue
    lst_url_link.append(link)

 

필요한 값들을 뽑는 법을 알았으니 이제는

url을 통해 시리즈 웹페이지로 이동해 보자.

 

Selenium은 Python에서 웹브라우저와

상호작용을 자동화 하는데 사용된다.

페이지로 이동하거나 클릭하는 등

특정 동작을 시킬 수 있는 녀석이다.

 

위에서 사용한 링크를 get을 이용해 가져와보자.

 

lst = []
lst_url_link = []
webtoon_lst = []

from selenium import webdriver
from selenium.webdriver.common.by import By
import time
from bs4 import BeautifulSoup

driver = webdriver.Chrome()
url = 'https://www.webtoons.com/en/dailySchedule'
driver.get(url)
soup = BeautifulSoup(driver.page_source, 'html.parser')

a_tag = soup.select('a')
for n in a_tag:
    link = n.attrs['href']
    if not 'list?title' in link:
        continue
    lst_url_link.append(link)

for m in range(0, len(lst_url_link)):
    #print(lst_url_link[m])
    url = lst_url_link[m]
    driver.get(url)
    time.sleep(1)

 

Crawling

 

 

HTML과 CSS 같은 부분을 잘 모르더라도

구글신과 함께하면 크롤링 정도는 금방 가능하다.

물론 최적화나 여러 측면에서는 부족하겠지만

몇 만 줄의 코드를 작성할 것도,

이걸로 협업을 할 것도 아니므로 신경 쓰지 말자.

 

작동하면 그만이다.

 

다음글로 이어집니다.

2023.05.22 - [Product Manager] - Product Management Research #10 (서비스 확장 / API)