python/크롤링

[파이썬 크롤러] 웹 크롤러 만들기

끼발자 2021. 7. 21. 13:04
반응형

요즘 빌보드에서 BTS가 연일 국위선양 하고있다.

그런 의미로 빌보드 차트 크롤러를 만들어보자.

파이썬 크롤러는 크게 두 가지다.

 

1. bs4

 

2. Selenium

bs4는 uri를 통해 html소스를 가져와 파싱한다. uri가 바뀌지 않는 이상, 한 번 호출한 html을 파싱하므로, 빠른축에 속하지만,

javascript가 들어가 반응형 웹의 경우에 파싱이 어려울 수 있다. 우리가 가져오는건 우리가 보는 빈 껍데기일 뿐, 특정 버튼을 눌렀을 때,

그에 상응하는 데이터를 얻을 수 있다고 확신할 수 없다.

 

그래서 selenium을 사용한다.

셀레니움 ( 혹은 셀레늄 )은 제어가 가능한 chromedriver( 가장 많이 사용하며, 파이어폭스나 다른 브라우저도 지원 한다. 아마도)

을 코드로 제어하며 웹 입장에서는 진짜 유저가 조작한다고 생각하므로, 반응형 웹에서도 사용 가능하다.

이 포스트에서는 비교적 쉬운 bs4를 통한 크롤러를 다뤄보겠다.

 

일단, 크롤러를 작성하기 전에 당부하고 싶은 말이 있다.

  • 어느 웹에서나 크롤러를 두 손 들고 반기는 경우는 없다는 것.
  • 구글이나 페이스북 등 대형 플랫폼에서는 크롤러 방지하는 기능이 있다는 것.
  • 최근들어 무죄선고가 내려졌지만, 1심에서는 유죄선고를 받은 경우가 있다.(  야놀자 - 여기어때간 소송https://www.hani.co.kr/arti/society/society_general/978684.html )
  • 크롤러를 무단으로 사용하여 상업적으로 이용하게되면, 소송에 휘말릴 수 있다.
  • 가급적이면 제공하는 api를 사용하자.

어디까지나 가능성이며, 무분별하게 많은 request를 던지면 웹에서 알아서 컷 한다.

보통 uri 뒤에 ex) google.com/robots.txt 등과 같이 robots.txt를 붙이면

해당 사이트에서 허용하는 것 (Allow : ) 과 허용하지 않는 것 (Disallow : )를 확인 할 수 있다.

 

사담은 여기까지하고 설치부터 차근차근 알아보자.

 

pip install requests
pip install bs4

당신들이 어떤 ide를 사용하는지 나로썬 알 수 없다.

파이썬을 타겟으로 하고있으니, anaconda, pycharm, vscode 등등. 여러 ide가 있고, 대부분은 터미널 콘솔창을 제공해준다.

위와 같은 명령어로 requests, bs4 패키지를 내려받자.

 

빌보드의 hot-100의 uri는 다음과 같다. https://www.billboard.com/charts/hot-100

한국시간 기준 2021-07-21 오전 10시의 빌보드 차트이다. 버터는 저 밑으로 내려갔지만,

Permission To Dance가 1위로 올라갔다. 박세리, 박찬호, 박지성, 추신수, 페이커가 그러하듯 한국인이 세계적으로 명성을 떨치면 자국민으로 기분이 좋아지는 것은 당연한것인가. KPOP은 별로 좋아하지 않지만 어떤가. 나는 자랑스럽다.

 

각설하고,

import requests 
from bs4 import BeautifulSoup

uri = 'https://www.billboard.com/charts/hot-100'
req = requests.get(uri)
html = req.text
soup = BeautifulSoup(html,'html.parser')

까지만 작성해보자.

 

uri는 말 그대로 주소창에 있는 주소다.

네이버가 될 수도 있고, 구글이 될 수도 있다. 

입맛에 맞춰서 변경해도 된다.

 

req는 requests를 줄여서 썼다. 어떤 의미인가 하면,

uri를 요청(request) 해서 가져와라(get) 라는 의미이다.

다른말로 쓰자면, 해당 uri의 페이지 소스를 가져와라는 의미이며, .text 는 텍스트로 바꿔 보여줘라 하는 의미이다.

 

호기심 많은 독자들이라면 req, html, soup를 출력했으리라 생각한다.

아닐수도 있고.

soup는 requests에서 얻어온 html을 예쁘게 바꿔서 보여준다. ( html과 soup은 내용만 따져봤을 때, 똑같다.)

 

자, 호기심이 많아 출력했던, 하지 않았던. 이제 당신들은 빌보드의 오늘자 html소스를 가져왔다.

이제 해당 소스에서 내가 가지고 오고 싶은 데이터를 알아야한다.

 

F12를 눌러보자. 아니면 우클릭-> 페이지 소스보기 를 통해서 소스를 볼 수 있다.

뭔가 굉장히 개발자가 된 것 같다.

어렸을 때, 스크린샷 찍다가 잘 못 눌러서 개발자 페이지뜨면 이게 뭔가 하고 무서워했던 기억이 있다.

나만 그런거 아닌가. 아님 말고.

 

대충 F12 누르면 나오는 화면

저 흰색 칸에 소스가 나온다.

우리가 중요하게 봐야 할 것은 위 사진에서 왼쪽 맨 위에 보이는 버튼.

저 버튼을 누르고, 페이지에서 우리가 데이터를 얻고자하는 영역을 클릭하면 친절하게도 해당되는 코드로 가준다.

 

짜잔. 이런식으로.

나의 목표는 빌보드 1~100위의 순위와 제목과 가수를 가져오고 싶다.

저렇게 클릭하게되면, 오른쪽에 Elements에서 자동으로 이동해서 하이라이트 해준다.

 

<span class="chart-element__rank flex--column flex--xy-center flex--no-shrink"><span class="chart-element__rank__number">1</span><span class="chart-element__trend font--semi-bold chart-element__trend--new color--accent">New</span></span>

클래스명을 써놨으니 위의 방법으로 찾아가도 되고,

Ctrl + F 한 다음에 저 클래스를 찾아도 된다.

 

찾았다면, 왼쪽의 자그마한 화살표가 보인다. 화살표를 눌러서 펼치면, 좀 더 디테일한 코드들이 보인다.

<span class= %%% > </span> 이런식으로 감싸져 있는게 보일텐데, 이 사이에 있는 값이 우리가 보는 값이다.

1위를 눌렀으니 저 사이엔 1이 들어가 있다.

 

해당 클래스명을 가지고 있는 값은 1부터 100까지 이다 클래스를 복사해서 Ctrl + F 로 찾으면 여러개가 나올 수 있다.

 

우리가 가져가고 싶은건 span으로 싸여있는 복잡한게 아니라, 저 사이에 있는 알짜배기 1이라는 숫자만 가져가고 싶다.

html소스에서 저 값만 가져오는 방법이 두 가지 존재하는데, 

  1. find_all 메소드를 통한 접근.
  2. select 메소드를 통한 접근.

등이 있다.

find_all을 통한 접근은.

soup.find_all('span':{'class':'chart-element__rank_number'})

해당 태그( span, div 등등) : { 클래스 : 클래스명 } 과 같이 호출하면 된다.

soup.find_all 은 리스트로 반환해주고, 해당 클래스명이 존재하지 않으면 빈 리스트를 리턴한다.

soup.find 는 해당 클래스명을 가진 값중 가장 앞에있는 인덱스를 가져온다.

 

두번째 select를 통한 접근은,

soup.select('.chart-element__rank__number')

훨씬 간편해보인다. select는 css의 태그로 찾는 메소드다.

클래스명 앞에 .만 붙여주면 찾을 수 있다. 클래스와 클래스 아이디를 통한 검색은 클래스 앞에 .을 붙인다.

클래스 이름이 여러개인경우에는 .으로 연결해주면 된다

ex) .a.b.c ==> 클래스 명이 a이면서 b이면서 c

 

위처럼 클래스명을 통해 태그를 찾았다면, 리스트 형태로 반환되고, 각각의 text만 가져오도록 만들어주자.

[rank.text for rank in soup.select('.chart-element__rank__number')]

위의 soup.select('.chart-element__rank__number')을 어떤 변수에 할당했다면, 그 변수를 in 뒤에 써주어도 된다.

리스트 컴프리헨션을 이용해서 한 줄로 만들었는데 이는 다음과 같은 역할을 한다.

def rank_list():
    list_ = []
    for rank in soup.select('.chart-element__rank__number'):
    	list_.append(rank)
    return list_

 

알아두면 유용한 정보이니 익숙해지길 바란다.

 

위에 방법을 그대로 따라서 가수와 곡을 수집하면, 우리가 원하는 오늘자 빌보드 100을 수집할 수 있다.

 

pandas의 DataFrame을 이용하면, 좀 더 데이터를 쉽게 다룰 수 있다.

 

selenium 예제는 다른 포스트에서 다뤄보기로 하자.

반응형