티스토리 뷰

🐱‍👤크롤링 준비 2가지

  1. 해당 사이트에 요청해서 크롤링할 html을 가져오는 것 // requests 패키지를 통해서 하면 됩니다. 
  2. bs4(beautifulSoup) 패키지 다운로드 -> 사이트에서 특정 요소(e.g. 영화제목 등) 가져오기를 도와줍니다.
❗ beautifulSoup이라고 치지마시고 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')

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

 


🌞beautifulsoup내 미리 정의된 다른 방법

이제 bs4 사용법에 따라 html 요소를 긁어와봅시다. (파이썬 문법아님 주의🐱‍👤)

# 선택자를 사용하는 방법 (copy selector)
soup.select('태그명')
soup.select('.클래스명')
soup.select('#아이디명')

soup.select('상위태그명 > 하위태그명 > 하위태그명')
soup.select('상위태그명.클래스명 > 하위태그명.클래스명')

# 태그와 속성값으로 찾는 방법
soup.select('태그명[속성="값"]')

# 한 개만 가져오고 싶은 경우
soup.select_one('위와 동일')
soup.select() -전부 가져오는 것 
soup.select_one() - 하나만 가져오는 것 
태그 안의 텍스트를 찍고 싶을 땐 → 태그.text
태그 안의 속성을 찍고 싶을 땐 → 태그['속성'] e.g.) 태그['alt'] // alt값을 가져오고싶다!

🐱‍👤예시를 통해 알아보기 

  • 우선 내가 가져오고싶은 정보 위에 커서를 올려두고 우클릭->검사->copy-> copy selector를 통해 셀렉터(선택자) 값을 복사해서 가져옵니다. *(크롬 개발자도구는 항상 정확하지 않습니다. 근데 유용하니까 쓰삼)

네이버 영화의 타이틀 '밥정'과 '그린 북'의 셀렉터를 카피해왔다. 

#old_content > table > tbody > tr:nth-child(2) > td.title > div > a <!--밥정 -->
#old_content > table > tbody > tr:nth-child(3) > td.title > div > a <!--그린 북-->
  • 여기서 차이점을 보자면 nth-child(n) 에 해당하는 부분을 제외하고  #old_content > table > tbody > tr 이 겹치는 것을 알 수 있다. 해당 정보를 이용해서 모든 tr태그들을 가져오자 
movies = soup.select('#old_content > table > tbody > tr')
print(movies) #해당 결과를 출력해보면 []리스트 형태라는 것을 알 수 있다.

print(movies) 결과 -> 리스트 []

  • movies 변수에 담은 것은 .select메소드를 사용했기 때문에 모든 tr태그를 담은 []리스트이다. (결과값을 출력해보면 리스트안에 딕셔너리가 담긴걸 확인할 수 있음).  해당 웹페이지를 봐도 <tr></tr>... 이 반복하기 때문에 
  • 변수에 담긴 내용물이 리스트인 것을 알았으니 for in 문을 돌려야겠죠?
for movie in movies:
    #a태그 찾아오기
    a = movie.select_one('td.title > div > a')
    print(a)
    # a를 출력해보면 None과 a태그들이 보이는데 None은 가로선들이다.
  • tr태그들의 뭉탱이를 movie라는 변수안에 담습니다. movie.select_one('')메소드를 사용하면 영화명이 담겨있는 a태그를 가져올 수 있습니다. 위에서 우리가 긁어왔던 셀렉터에서 앞부분은 사용하고 뒷 부분은 사용하지 않았던 것을 기억할겁니다. 공통되지 않는 부분(:nth-child(n))을 제외한 셀렉터의 뒷 부분(td.title > div > a )을 바로 지금 사용합니다 

print(a) 결과물

이렇게하면 각각의 a태그가 잘 불러와진 것을 확인할 수 있습니다. 중간에 None 이라는 부분은 중간에 있는 가로선 때문에 생긴 것입니다. 조건문을 통해서 None을 없애줍시다. 

for movie in movies:
    #a태그 찾아오기
    a = movie.select_one('td.title > div > a')
    # a를 출력해보면 None과 a태그들이 보이는데 None은 가로선들이다.
    #if문을 통해서 None은 제외시켜 보자
    # 파이썬 조건식에서 아니다 표현 2가지 != , is not
    if a is not None:
    	#a태그의 내용물을 가져오는 것이므로 .text사용
        title = a.text
        print(title)
    #영화명을 가져오게 됐다!
❗파이썬 if문에서 조건식에서 not(부정)을 표현하는 방법은 2가지가 있습니다. 
1. !=
2. is not 

 

+ 위에서 배웠던 것을 참고하여 제목, 평점, 순위 등을 가져올 수 있습니다. 

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('크롤링할웹페이지URL',headers=headers)

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

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 // a태그의 텍스트가져오기
        rank = movie.select_one('td:nth-child(1) > img')['alt'] //img태그의 alt속성값가져오기
        star = movie.select_one('td.point').text // td태그의 텍스트 가져오기
        print(rank, title, star)

all ref: 스파르타 코딩클럽 웹개발 종합반 

댓글