본문 바로가기
  • 실행력이 모든걸 결정한다
Crawling

[크롤링, 예제 1] BOJ 정답율 추출하기

by 김코더 김주역 2020. 10. 23.
반응형

아래 포스팅을 읽지 않았다면 무조건 읽고 올 것을 권장한다. 설치법과 robots.txt같이 필수적으로 알아둬야 하는 개념이 필요하다.

kimcoder.tistory.com/164

 

크롤링을 위한 준비과정 (Python, selenium, beautifulsoup 설치)

※크롤링을 할 때 지켜야 하는 룰이 있으니 robots.txt에 대해 모른다면 아래 포스팅을 읽고 오는 것을 강력히 권한다. kimcoder.tistory.com/163 크롤링의 정의와 이점 그리고 주의할 점 크롤링이란 무수

kimcoder.tistory.com

 

현 시점부터 크롤링은 기본적으로 파이썬을 이용할 예정이지만, 같은 예제를 Node.js에서 cheerio, request 모듈로 크롤링한 포스팅도 있다.

kimcoder.tistory.com/161

 

[Node.js] request, cheerio를 이용한 웹크롤링

이번 포스팅에서는 Node.js에서 request, cheerio 모듈을 이용하여, 백준 온라인 저지 사이트에 있는 특정 문제들의 정답률 데이터를 모두 긁어와서 평균까지 계산해주는 크롤링 봇 구현에 대해 다룰

kimcoder.tistory.com

 

 

크롤링은 기본적으로 이 절차를 따른다.

 

0. 크롤링 계획 세우기

백준 온라인 저지 사이트에 있는 특정 문제들의 정답률 데이터를 모두 긁어와서 평균까지 계산해주는 크롤링 봇을 만든다.

지나친 크롤링은 웹사이트에 트래픽을 줄 수 있으므로 가볍게 모든문제 1페이지에 있는 문제번호 1000~1099까지 총 100문제의 정답률 데이터들만 추출한다.

 

1. 크롤링할 페이지 접속 - Chrome으로 접속

/problemset/1 으로 접속했다. (www.acmicpc.net/problemset/1)

 

 

www.acmicpc.net/problemset/1

 

문제 - 1 페이지

 

www.acmicpc.net

 

2. 크롤링 가능 여부 확인(필수)

Disallow에 /problemset이 없으므로 불법x

(/problemset이 비허용이면 자동으로 그 하위 문서인 /problemset/1 도 비허용)

 

 

 

3. 크롤링할 대상 결정

 

 

 

 

4. 크롤링할 데이터가 있는 태그 파악

크롬 브라우저로 연 웹사이트에서 우클릭을하면 밑에 검사(N)이라는 요소가 뜰 것이다.

 

 

그것을 클릭하면

 

 

 

이런 식으로 우측 혹은 아래측에 웹 코드들이 뜰 것이다. HTML과 CSS코드들이 보인다.

복잡한 코드이지만 절대 겁먹지 말것. 다 몰라도 여러분들은 크롤링 할 수 있다.

구체적으로 이해하고 싶다면 생활코딩 유튜브의 HTML, CSS 강의에서 Tag, Class, Id 이 세 개의 개념을 익히고 오는 것을 추천한다. 하루이틀만에 가능하다.

 

이제 이 웹코드상에서 원하는 정답율 데이터가 어디 태그에 감싸져있는지 확인해야 하는데 방법은 간단하다.

 

빨간 동그라미안에 있는 inspect(검사) 아이콘을 클릭하고

 

 

 

원하는 데이터인, 본인이 아래 사진에 빨간 밑줄친 정답율 데이터 "44.143%" 을 클릭하면, 오른쪽 웹코드에 해당 데이터가 있는 태그로 이동되어 있는 것을 볼 수 있다.

<td>44.143%</td> == $0 에 진하게 강조 표시가 되어있지 않은가?

 

 

 

 

5. 태그 규칙 파악

바로위에 올린 사진을 보면서 따라와보자.

44.143% 데이터를 보면 <td> 태그로 감싸져 있고,

<td> 태그는 <tr> 태그로 감싸져 있고

<tr> 태그는 <tbody> 태그로 감싸져 있고

.... 여러 태그 들로 감싸져 있다.

 

이 이상의 상위 태그들까지는 굳이 반영 하지 않아도 되는데, 그 이유를 설명하겠다.

 

-태그 간단 설명-

<tbody> : 표

<tr> : 행

<td> : 열

 

이 페이지(www.acmicpc.net/problemset/1)에서, 표는 1페이지의 문제들에 해당하는 표 하나밖에 없으므로

웹 코드에서 <tbody> 태그(표)도 하나밖에 없다.

 

그렇기 때문에 이런 규칙을 세울 수 있게 되었다.

규칙 : 원하는 데이터는 <tbody> 태그 내의 모든 <tr> 태그 내의 6번째 <td> 태그 안에 있다.  

이 예제에서는 <tbody> 태그는 하나밖에 없으므로 <tbody> 태그 안에 있는 원하는 데이터 외의 다른 데이터가 딸려나올일이 없기 때문에, 굳이 <tbody>보다 위에 있는 상위 태그는 반영하지 않아도 된다. 이것이 이유이다.

만약 원하는 데이터가 있는 <tbody>태그 외 어딘가에 다른 <tbody> 태그가 있다고 한다면, 이 3개의 태그만으로 범위를 좁히기에는 위험하다. 예상치 못한 다른 <tbody> 태그 내의 데이터가 딸려나올 수도 있기 때문이다. 이런 경우를 처리하는 방법에 대해서는 앞으로 더 많은 크롤링 예제를 다루면서 설명할 기회가 충분할 것이다. 

이제 다음 단계로 넘어가보자.

 

 

6. 코딩

동적 크롤링이 요구되지 않기 때문에 selenium은 사용하지 않아도 괜찮다.

IE에서도 Chrome과 같이 모든 서비스가 동작하므로 Chrome driver도 사용하지 않아도 된다.

그래서 selenium, driver 대신 urllib 라는 라이브러리와 Beautifulsoup 모듈만 import했다.

BeautifulSoup 클래스는 웹문서를 파싱하여, 크롤링을 할 수 있게 문서 개체를 생성해준다.

자세한 설명은 주석을 참고하고 질문 사항이 있을 시 댓글을 남겨도 좋다.

 

#필수 모듈 및 라이브러리 import

import urllib.request
import urllib.parse
from bs4 import BeautifulSoup

#웹 접근
with urllib.request.urlopen('https://www.acmicpc.net/problemset/1') as response:
    #html코드 가져오기
    html = response.read()
    soup = BeautifulSoup(html,'html.parser') #'html.parser' 대신 'lxml'을 쓰기도 함
    
    #대상 선택(tbody -> tr -> 6번째 td)
    ratetexts = soup.select('tbody tr td:nth-child(6)')
    sum=0
    for text in ratetexts:
        print(text.text[0:-1]) #float형 정답율 데이터만 추출하기 위해 '%' cut
        sum+=float(text.text[0:-1]) #합계
    length = len(ratetexts) #대상의 크기
    ACP = round(sum/(len(ratetexts)),3) #평균을 소수 셋째 자리까지 표시
    print('Size='+str(length))
    print('Average Correct Percentage='+str(ACP)+'%')

 

 

7. 실행

이제 고생한 결과물을 감상해 볼 시간이다. 다들 이맛으로 코딩하지 않는가?

 

내 프로젝트 폴더는 바탕화면에 두었고 crawl1 이라는 이름의 폴더이고, 코드는 그 안에 boj1.py 라는 파일에 작성 되었다.

 

 

 

32.542% 로 정상적으로 출력된 것을 볼 수 있다.

BOJ 1000~1099번까지 총 100문제의 정답율 평균은 32.542%인 것이다.

따라오는 것도 마냥 쉬운일은 아니다.

성공 했다면, 스스로에게 칭찬하는 시간을 갖고

잘 안된다면, 이 포스팅에 댓글을 달아도 좋다. 최대한 빨리 답변할 것이다.

반응형

댓글