개발과 계발/웹 개발

웹스크래핑(크롤링) 기초 - beautifulsoup4 사용법

멈 무 2022. 11. 27. 20:57

파일 - 설정 - + 버튼 - requests 검색해서 설치

파일 - 설정 - + 버튼 - bs4 검색해서 설치

 

기본세팅

import requests
from bs4 import BeautifulSoup

# 타겟 URL을 읽어서 HTML를 받아오고,
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
data = requests.get('https://movie.naver.com/movie/sdb/rank/rmovie.naver?sel=pnt&date=20210829',headers=headers)

# HTML을 BeautifulSoup이라는 라이브러리를 활용해 검색하기 용이한 상태로 만듦
# soup이라는 변수에 "파싱 용이해진 html"이 담긴 상태가 됨
# 이제 코딩을 통해 필요한 부분을 추출하면 된다.
soup = BeautifulSoup(data.text, 'html.parser')

#############################
# (입맛에 맞게 코딩)
#############################

 

 

<네이버 영화 랭킹에서 제목 따오기>

https://movie.naver.com/movie/sdb/rank/rmovie.naver?sel=pnt&date=20210829 

 

랭킹 : 네이버 영화

영화, 영화인, 예매, 박스오피스 랭킹 정보 제공

movie.naver.com

 

영화 제목 위에서 우클릭 - 검사 열고

그럼 해당부분이 파랗게 되어있는데

거기서 우클릭 - copy - copy selector 선택

 

 

그리고 파이참에서 붙여보면

이렇게 나옴

영화 제목 두개를 가져온거고,

구조를 보면

#old_content > table > tbody > tr

여기까지는 똑같은걸 알 수 있음

그래서 같은 경로까지만 가져오고

movies = soup.select('#old_content > table > tbody > tr')

 

검사로 보면 영화 제목들은

<tr> ... </tr>들이 쭈루룩 있는걸 알 수 있음

 

그래서 그 하나하나를 반복해줘야하므로

'td.title > div > a'

이걸 for 반복문으로 반복해줌

그리고 점선을 제외해주기 위해서

if 문으로 text만 print함

movies = soup.select('#old_content > table > tbody > tr')

for movie in movies:
    a = movie.select_one('td.title > div > a')
    if a is not None:
        print(a.text)

 

그럼 결과는

 

 

 

<연습문제: 순위, 제목: 평점 가져오기>

movies = soup.select('#old_content > table > tbody > tr')

for movie in movies:
    a = movie.select_one('td.title > div > a')
    b = movie.select_one('td:nth-child(1) > img')
    c = movie.select_one('td.point')
    if a is not None:
        title = a.text
        rank = b['alt']
        star = c.text
        print(rank, title, star)

 

요러케 하니까 원하는대로나왔음!

나는 a 선언해준것처럼 b, c 각각 선언 후  title, rank, star 에 할당햇눈데

 

정답을 보면

import requests
from bs4 import BeautifulSoup

headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
data = requests.get('https://movie.naver.com/movie/sdb/rank/rmovie.naver?sel=pnt&date=20210829',headers=headers)

soup = BeautifulSoup(data.text, 'html.parser')

#old_content > table > tbody > tr:nth-child(3) > td.title > div > a
#old_content > table > tbody > tr:nth-child(4) > td.title > div > a

movies = soup.select('#old_content > table > tbody > tr')

for movie in movies:
    a = movie.select_one('td.title > div > a')
    if a is not None:
        title = a.text
        rank = movie.select_one('td:nth-child(1) > img')['alt']
        star = movie.select_one('td.point').text
        print(rank, title, star)

그냥 바로 movie.seletc_one을 붙여주었음!

 

 

여기서 약간 헤맸던거는

제목은 text만 추출하기에 text 붙이면되고

숫자는 number라고해야하나..? 했는데 틀림. 그냥 똑같이 text였음

 

 

젤 어려웠던게 순위인데

구조상 img파일이기때문에 img를 가져오는건 아니였고

그 위치에서 alt = "00" 이런식으로 되어있어서 

alt값을 가져오는ㄱㅓ였음!

 

alt값을 어떻게 가져오나...

a.alt 

a.alt.text 

 

이런식으로 해봣는데 다 오류뜸

그러다가 혹시 괄호 쳐서 가져오나 ? 해서 

{} ,  [] 이런 괄호 넣어봣는데 됐다

 

리스트 형식인지, []가 맞았음

 

<img src="https://ssl.pstatic.net/imgmovie/2007/img/common/bullet_r_r03.gif" alt="03" width="14" height="13">

 

순위 그림? 있는 부분 검사해서 나온게 요거인데

img alt width height가 리스트로 넣어져 있는 형태인가보다 했음

 

완성본