파이썬/파이썬 활용

파이썬 활용 07 - 1 -웹 스크래핑 (BeautifulSoup4 - 네이버웹툰)

H-V 2021. 11. 4. 10:57

유투버 '나도코딩'님 강의 참조

 

 

 

01 BeautifulSoup4 기본 1

  • BeautifulSoup4 을 사용하기 위해서 2가지를 설치를 해줘야 한다!
    beautifulsoup4 - 실제로 스크래핑을 위한 패키지
    lxml - lxml은 스크래핑시 구문들을 파싱하기 위한 패키지

 

  • 간단 테스트 (네이버 웹툰)
import requests
from bs4 import BeautifulSoup

url ="https://comic.naver.com/webtoon/weekday"
res = requests.get(url)
res.raise_for_status()

#URL을 통해 가져온 HTML문서를 'lxml'을 통해 파싱을 하고 객체로 만듬
soup = BeautifulSoup(res.text, "lxml")
print(soup.title)

  1. 'res' 변수에 requests.get(url) 정보를 담음 (HTML 형식으로 담김)
  2. 'soup' 변수에 BeautifulSoup 을 이용한 res.text(HTML)를 스크래핑, 파싱은 'lxml'로 진행
  3. 스크래핑 + 파싱이 되었으니 soup 변수를 통해 내용들을 가져올 수 있음

 

*여러가지를 가져와보자

import requests
from bs4 import BeautifulSoup

url ="https://comic.naver.com/webtoon/weekday"
res = requests.get(url)
res.raise_for_status()

#URL을 통해 가져온 HTML문서를 'lxml'을 통해 파싱을 하고 객체로 만듬
soup = BeautifulSoup(res.text, "lxml")
# print(soup.title)
# print(soup.title.get_text())
# print(soup.a)
# print(soup.a.attrs)
print(soup.a["href"])

 

 

 

  • 위의 같은 정확한 파싱은 그 웹사이트에대한 정확한 이해가 있으면 가능하나 보통 웹 스크래핑시에는 어렵다. 그래서 웹의 상태를 잘 모를때 쓸 수 있는 '.find()' 를 알아보자
  • 예를 들어 이 웹 페이지에서 '웹툰 올리기' 라는 버튼에 대해서 스크래핑을 하고싶다고 가정하자.

  • 그러면 F12를 누른 후 아래 사진에 나와있는 버튼을 클릭 후 원하는 곳을 클릭하면 아래처럼 나온다
    검사버튼을 가져다보면 이 버튼이 가지고 있는 특성을 볼 수 있는데 class를 특성으로 가져오면 쉬울 것 같다!
import requests
from bs4 import BeautifulSoup

url ="https://comic.naver.com/webtoon/weekday"
res = requests.get(url)
res.raise_for_status()

soup = BeautifulSoup(res.text, "lxml")

*웹페이지에 특정 기능이 하나라면 "a" 위치는 생략 가능 하다
print(soup.find("a", attrs={"class":"Nbtn_upload"}))

 

  • 또 다른 예제를 보자
    인기급상승 웹툰의 1위를 가져와 보자

    print(soup.find("a", attrs={"onclick":"nclk_v2(event,'rnk*p.cont','570503','1')"}))
    
    <a href="/webtoon/detail?titleId=570503&amp;no=379" onclick="nclk_v2(event,'rnk*p.cont','570503','1')" title="연애혁명-375. 입장정리">연애혁명-375. 입장정리</a>​

혹은 아래와 같이 된다

print(soup.find("li", attrs={"class":"rank01"}))

or

rank1 = soup.find("li", attrs={"class":"rank01"})
print(rank1.a)

 

 

 

02 BeautifulSoup4 기본 2

  • BeautifulSoup을 이용해서 부모 혹은 자식 객체에 바로 접근이 가능 하다

→ 인기급상승 만화에서 순위별로 들고 와 보자

rank2 = rank1.next_sibling.next_sibling
rank3 = rank2.next_sibling.next_sibling
print(rank3.a.get_text())

나노마신-073. 제29장. 주군이 돌아왔다 (2)

*그 외 이전것 들고오기, 부모속성 들고오기 등이 있다
# rank2 = rank3.previous_sibling.previous_sibling
# print(rank2.a.get_text())
# print(rank1.parent)

→ 하지만 형제 혹은 자식을 찾을때 같은 구분을 두번 반복해서 쓰는 번거로움이 있다 (다른 웹에는 없을 수 도 있기때문에 맞지 않다.) 이럴때 쓰는 것이 따로 있다

rank2 = rank1.find_next_sibling("li")
print(rank2.a.get_text())

독립일기-시즌2 18화 입맛의 변화

현재 순위는 li 태크에 규칙적으로 묶여있는걸 볼 수 있다.

→find_next_sibling() 함수는 다음 자식 혹은 형제들 중 괄호안의 내용을 포함 하고 있는 것들만 들고 올 수 있다. 

더보기

find_next_sibling() 함수도 previous를 붙여서 이전것들을 들고 올 수 있다.

여러 형제들이 있으면 find_next_siblings()로 한번에 여러개를 들고 올 수 있다.

 

webtoon = soup.find("a", text="연애혁명-375. 입장정리")

print(webtoon)

이런 식으로 텍스트만 이용해서도 추출이 가능 하다. 

 

 

 

03 BeautifulSoup4 활용 1

  • 요일별 전체 들고 오기
import requests
from bs4 import BeautifulSoup

url ="https://comic.naver.com/webtoon/weekday"
res = requests.get(url)
res.raise_for_status()

soup = BeautifulSoup(res.text, "lxml")

#네이버 웹툰 요일별 전체 목록 가져오기
cartoons = soup.find_all("a", attrs={"class":"title"})
for cartoon in cartoons:
    print(cartoon.get_text())
    
...
보통아이
호수의 인어
다시 또 봄
가짜인간
호시탐탐
거래하실래요?
푸른불꽃
짝사랑의 유서
독신마법사 기숙아파트
샤인 스타
...

 

 

  • 현재 페이지에는 없는 만화 정보를 들고 와 보기

검색을 해야 나오는 만화이다. 이 URL을 들고 파싱 해보자

  • 똑같이 어떠한 목록을 들고 올지 검사를 눌러서 찾자!
    현재 이 페이지에서 제목을 들고 오려고 하니 테이블로 구성이 되어있지만 <a>태그에는 딱히 다른 정보가 없다. 그래서 바로 위 부모의 <td>태그로 들고 와보자 안 될 수도 있다.
import requests
from bs4 import BeautifulSoup

url ="https://comic.naver.com/webtoon/list?titleId=675554"
res = requests.get(url)
res.raise_for_status()

soup = BeautifulSoup(res.text, "lxml")

cartoons = soup.find_all("td", attrs={"class":"title"})
# print(cartoons)
title = cartoons[0].a.get_text()
print(title)

후기 + 10년 후 가우스

→ 다행히 잘 들고 온다! *.find_all() 함수는 리스트 형식으로 들고 온다는것을 명심 하자!

 

  • 이제 이것을 활용해서 모든 제목 + 링크를 들고와서 링크를 클릭하면 페이지로 이동하도록 해보자!
import requests
from bs4 import BeautifulSoup

url ="https://comic.naver.com/webtoon/list?titleId=675554"
res = requests.get(url)
res.raise_for_status()

soup = BeautifulSoup(res.text, "lxml")

cartoons = soup.find_all("td", attrs={"class":"title"})

for cartoon in cartoons:
    title = cartoon.a.get_text()
    link = "https://comic.naver.com" + cartoon.a["href"]
    print(title, link)

잘 들고 온다! 링크는 컨트롤 + 마우스 왼클릭으로 하면 페이지로 이동 한다!

 

 

  • 가우스 전자 평점 들고 오기

→항상 스크래핑시에는 검사를 통해 화면을 분석 해야 한다! 평점이 어떻게 구성되어있는지 한번 보자

평점을 들고 와야 하니 div안에 9.98이 어느 태그에 속해 있는지를 잘 봐야 한다.

# 평점 구하기
total_ratings = 0
cartoons = soup.find_all("div", attrs={"class":"rating_type"})
for cartoon in cartoons:
    rating = cartoon.strong.get_text()
    print(rating)
    total_ratings += float(rating)

print("Total Ratings: ",total_ratings)
print("Average Ratings: ",total_ratings / len(cartoons))

9.98
9.98
9.97
9.97
9.97
9.98
9.97
9.97
9.97
9.97
Total Ratings:  99.72999999999999
Average Ratings:  9.972999999999999

 

※ 파이썬은 인터프리터 언어이기때문에 터미널창에서 바로 코드를 짜 볼 수도 있다.