Python/Web Crawling+Scraping

(예제) - 한국 도쿄올림픽 medal count 가져오기 -

metamong 2022. 3. 22.

! -- 저번 포스팅에서는 HTML 형식의 파일이 존재한다면 open()을 이용해서 가져오고 BeautifulSoup parsing을 통해 직접 데이터를 검색했던 적이 있었다. 이번에는 직접 web browser url을 이용하여 web page를 가져오고 원하는 data를 찾아 출력하는 실습을 해보겠다 -- !

 

(하단 HTML file - BeautifulSoup 검색 포스팅)

 

HTML 문서를 BeautifulSoup으로 검색하기 (+re module)

! -- web browser에서 직접적인 url을 가져와 parsing하는 web crawling은 아니지만 web에 존재하는(또는 컴퓨터에 자체적으로 존재하는) HTML file 내용을 가져와 나타내는 방법을 알아본다 -- ! ** BeautifulS..

sh-avid-learner.tistory.com


Q) 문제 - 2020 도쿄올림픽 대한민국 팀의 금메달, 은메달, 동메달, 그리고 총 메달 count를 출력하기

 

- 파란 줄의 data를 가져오자 -

 

1. urllib

** urllib library 사용

→ can treat a web page much like a file

→ simply indicate which web page you would like to retrieve & urllib handles all of the HTTP protocol and header details

 

import urllib.request
from bs4 import BeautifulSoup

 

→ once the web page has been opened with urllib.urlopen, we can treat it like a file & read through it using a for loop

→ the headers are still sent, but the urllib code consumes the headers and only returns the data to us

 

data = urllib.request.urlopen('https://en.wikipedia.org/wiki/2020_Summer_Olympics_medal_table')

2. parsing using BeautifulSoup

** urllib로 가져온 web broswer의 data는 'utf-8 (mostly)' 형식으로 구성되어 있다. 따라서 bytes object 형식의 data를 internal format인 unicode형태로 꼭 바꿔줘야 한다 = parsing

→ 즉, utf-8 형태를 unicode 형태로 바꾸기 위해 html.parser를 사용하며 BeautifulSoup library가 이를 돕는다.

(BS - tolerates highly flawed HTML and still lets you easily extract the data you need)

 

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

3. web page 방문 - 가져올 data html code 확인

* web page를 직접 방문하고 개발자 도구에 들어가 원하는 data의 code를 확인해 본다.

 

 

<확인 - 분석 결과>

 

→ 도쿄올림픽 medal table은 한 table로 구성되어 있음 - <tr> <th> <td> code 검색해야 됨

→ 한국은 16위로 16번째 <tr> tag에 정보가 위치해 있음 - 원하는 단 한 개의 <tr>만 가져와야 함

→ 두 번째 <th> tag에 South Korea medal table이라는 link로 가는 a tag가 nested

→ nested 된 link인 <a> tag의 title은 "South Korea at the 2020 Summer Olympics"임 - 이를 활용하여 특정 <tr> tag를 가져올 것

 해당 <tr>의 3, 4, 5, 6번째 <td> tag가 우리가 가져와야 할 정보 (금, 은, 동, 합계 data)

 

4. find() & find_parent() & find_all() 활용하여 web crawling 실습

[1] tr tag 한 행 가져오기 - South Korea

* medal table에서 South Korea가 차지하는 한 행 <tr> tag를 가져온다

 

South_Korea_tr = soup.find("a", {"title":"South Korea at the 2020 Summer Olympics"}).find_parent("tr")
South_Korea_tr

 

- 출력결과 -

 

<tr><td>16</td><th scope="row" style="background-color:#f8f9fa;text-align:left"><img alt="" class="thumbborder" data-file-height="600" data-file-width="900" decoding="async" height="15" src="//upload.wikimedia.org/wikipedia/commons/thumb/0/09/Flag_of_South_Korea.svg/22px-Flag_of_South_Korea.svg.png" srcset="//upload.wikimedia.org/wikipedia/commons/thumb/0/09/Flag_of_South_Korea.svg/33px-Flag_of_South_Korea.svg.png 1.5x, //upload.wikimedia.org/wikipedia/commons/thumb/0/09/Flag_of_South_Korea.svg/44px-Flag_of_South_Korea.svg.png 2x" width="22"/> <a href="/wiki/South_Korea_at_the_2020_Summer_Olympics" title="South Korea at the 2020 Summer Olympics">South Korea</a> <span style="font-size:90%;">(KOR)</span></th><td>6</td><td>4</td><td>10</td><td>20</td></tr>

 

→ South Korea at the 2020 Summer Olympics라는 title을 가진 a tag를 find로 찾는다

 find한 결과 tag의 상위 tag인 tr tag를 불러오기 위해 find_parent("tr")을 뒤에 붙인다

→ 그 결과 South Korea의 medal 정보가 담겨 있는 medal table의 한 행(row) tr tag를 찾았다

[2] tr의 td tag 찾기

* 이 중 우리가 관심있는 부분은 td tag로 감싼 medal count (총 세 개 tag)

→ 총 세 개 tag를 찾기 위해 find가 아닌 find_all 함수 사용 (2개 이상 모두 불러와야 하므로)

 

trData = South_Korea_tr.find_all("td")
trData

 

- 출력결과 -

 

[<td>16</td>, <td>6</td>, <td>4</td>, <td>10</td>, <td>20</td>]

[3] 원하는 정보만 출력 - for문

* for문을 이용해 2~4번째 td tag의 contents (.text 사용)만 골라 출력한다

 

for i in range(4):
    print(int(trData[i+1].text))

 

- 출력결과 -

 

6
4
10
20

 

 한국은 도쿄올림픽에서 6개의 금메달, 4개의 은메달, 10개의 동메달, 총 20개의 메달을 획득했음을 알 수 있다.

 python code를 통해 web page의 원하는 data를 찾을 수 있슴!


 

* 출처) 2021 공공데이터 청년인턴(일경험수련생) 상시교육

댓글