본문 바로가기
TOP
데이터 스킬업/웹크롤링

[파이썬: 웹크롤링] #03 html에서 데이터 출력하기 with BeautifulSoup

by 티챠림 2023. 3. 1.

[왕초보 웹크롤링 무작정 따라하기] html 구조 파악하기, 태그, css 선택자, xpath, 경로 검색, 데이터 찾기


#03 html에서 데이터 출력하기 with BeautifulSoup


html 구조 파악하기 (바로가기 Click)

데이터 경로 지정하기 (바로가기 Click)

텍스트 추출하기 (바로가기 Click)


requestsBeautifulSoup으로 불러온 html을 불러왔다면 select()find() 함수로 정보가 위치한 경로를 지정하여 필요한 정보만 추출할 수 있다. 경로를 지정해주기 위해서는 먼저 html 문서 어디에 원하는 정보가 위치해 있는 파악해야 한다. 

1. html 불러오기
2. 원하는 정보의 경로 파악
3. 정보가 위치한 경로 지정
4. 필요한 정보만 추출

 

아래 코드는 네이버의 '주간 예능 시청율' 검색 페이지의 html을 불러온 것이다. 이를 이어서 순위와 프로그램명을 크롤랑하는 코드를 만들어보자. (네이버에 '주간 예능 시청률' 검색 후, 주소 창의 url을 복붙하여 사용하세요.)

 

import requests
from bs4 import BeautifulSoup 

response = requests.get("https://search.naver.com/search.naver?where=nexearch&sm=tab_etc&mra=blUw&qvt=0&query=%EC%A3%BC%EA%B0%84%EC%98%88%EB%8A%A5%20%EC%8B%9C%EC%B2%AD%EB%A5%A0")  
soup = BeautifulSoup(response.text, 'html.parser') 
soup

#문제1. 순위 / 프로그램명 크롤링하기

네이버-검색-결과
네이버에서 검색한 시청률 정보(좌), 파싱된 html 출력 결과(우)

 

 

 

 

 

  html 구조 파악하기

순위와 프로그램명을 크롤링하기 위해 html 상에서 각 정보가 어디에 위치해 있는지 살펴보도록 하자. html은 웹브라우저의 개발자 도구를 열어 확인할 수 있다. 개발자 도구'F12'를 누르거나 찾고 싶은 정보에 마우스를 올려두고  '마우스 오른쪽 클릭-검사'를 눌러 열 수 있다. 

 

개발자도구로 순위 정보의 html 경로를 확인(좌), 필요한 정보들의 html 구조 확인(우)

'순위'와 '프로그램명'의 경로를 확인해보면 순위별로 비슷한 구조가 반복되는 것을 확인할 수 있다. 순위별로 <span ~>과 <a ~>까지 동일하게 반복된다. 필요한 정보의 경로가 반복되는 구조를 가졌다면 반복되는 패턴에서 각 경로가 구분되는 요소를 찾으면 된다. 이 예제에서는 순위별로 반복되는 <span>태그에 class라는 선택자를 갖고 class="num_n1"의 n 뒤에 오는 숫자가 다른 것을 확인할 수 있다. 

 

이처럼 html은 아래의 표와 같은 <태그>와 'CSS 선택자'로 구성되고 일정한 패턴을 이루기도 한다. 이러한 반복되는 패턴과 식별되는 선택자를 활용하면 몇 줄의 코드만으로 많은 양의 데이터를 추출할 수 있다. 웹크롤링을 하기 위해서는 html의 구조와 패턴을 이해하는 것이 매우 중요하니 눈에 익혀두도록 하자.

<태그> <div> 콘텐츠가 들어갈 영역 html을 구성하는 각 영역
구조를 파악할 수 있음

<p> 텍스트가 들어가는 한 줄
<span> 텍스트가 들어가는 한 문장
<a> 외부로 연결된 하나의 링크
... ...
css 선택자 class = 중복 될 수 있는 그룹이름 각 영역의 이름표
반복되는 패턴에서 각 객체를 구분할 수 있음
id = 중복되지 않는 유일한 이름

 

 

 

  데이터 경로 지정하기

필요한 정보들의 경로를 찾았다면 select() 또는 find() 함수에 경로를 직접 적어거나 복붙하면 된다. 경로 복사는 필요한 정보가 담겨있는 영역에 마우스를 올리고 '마우스 우클릭 - Copy - Copy selector'를 누르면 된다. 1위 프로그램명의 경로를 복사해 보면 '#main_pack > section.sc_new.cs_rating > div > div.api_cs_wrap > div.rating_cnt > div > table > tbody > tr:nth-child(1) > td:nth-child(2) > p > a', 2위 프로그램명의 경로는 '#main_pack > section.sc_new.cs_rating > div > div.api_cs_wrap > div.rating_cnt > div > table > tbody > tr:nth-child(2) > td:nth-child(2) > p > a'인 것을 알 수 있다.

 

1위 프로그램명 경로:  '~~동일한 경로~~ > tr:nth-child(1) > ~동일~'
2위 프로그램명 경로:  '~~동일한 경로~~ > tr:nth-child(2) > ~동일~'

 

개발자도구에서 선택자 복사(좌), 1위와 2위 프로그램명의 경위치(우)

 

두 경로를 비교해보면 tr:nth-child 구간에서 갈라지는 것을 알 수 있다. 즉, 갈라진 이후의  'td > p > a'의 패턴마다 각 순위의 프로그램명이 위치해 있다고 생각해볼 수 있다. select() 함수의 괄호 안에 복사한 1위 프로그램명 경로와 파악한 패턴을 각각 넣고 출력해 보도록 하자.

import requests
from bs4 import BeautifulSoup

response = requests.get("https://search.naver.com/search.naver?where=nexearch&sm=tab_etc&mra=blUw&qvt=0&query=%EC%A3%BC%EA%B0%84%EC%98%88%EB%8A%A5%20%EC%8B%9C%EC%B2%AD%EB%A5%A0")
soup = BeautifulSoup(response.text, 'html.parser') 

first_program = soup.select('#main_pack > section.sc_new.cs_rating > div > div.api_cs_wrap > div.rating_cnt > div > table > tbody > tr:nth-child(1) > td:nth-child(2) > p > a') 
programs = soup.select('td>p>a') 

print(first_program)
print(programs)

코드 실행 결과

 

1위 프로그램명의 경로를 넣은 출력값은 [리스트] 안에 1개의 프로그램명 <태그>가 들어가 있고, 패턴을 넣은 출력값에는 여러개의 프로그램명 <태그>가 있는 것을 확인할 수 있다.

 

 

 

 

  텍스트 추출하기

이제 불필요한 <태그>정보를 제외한 프로그램명 텍스트만 뽑아내면 된다. get_text() 메소드를 통해 <태그>에 위치한 텍스트를 추출할 수 있는데, 이 메소드는 [리스트] 자료형에 사용할 수는 없다. 각 <태그>들을 리스트 밖으로 꺼내서 메소드를 실행해야 한다. [리스트] 안의 요소들은 인덱스를 지정하거나 반복문을 사용하는 방식으로 뽑아낼 수 있다. 

import requests
from bs4 import BeautifulSoup

response = requests.get("https://search.naver.com/search.naver?where=nexearch&sm=tab_etc&mra=blUw&qvt=0&query=%EC%A3%BC%EA%B0%84%EC%98%88%EB%8A%A5%20%EC%8B%9C%EC%B2%AD%EB%A5%A0")
soup = BeautifulSoup(response.text, 'html.parser') 

first_program = soup.select('#main_pack > section.sc_new.cs_rating > div > div.api_cs_wrap > div.rating_cnt > div > table > tbody > tr:nth-child(1) > td:nth-child(2) > p > a') 
programs = soup.select('td>p>a') 

print(first_program[0].get_text()) #인덱스로 리스트 안에서 요소를 선택

for p in programs: #반복문을 통해 요소를 하나씩 꺼내서 출력
    print(p.get_text())

코드 실행 결과

 

get_text로 각 경로의 텍스트를 출력해보니, 1위 프로그램명의 경로를 복사한 값은 정상적이지만 패턴을 사용한 값은 뽑을 생각이 없던 채널명이 함께 출력된 것을 확인할 수 있다. 반복된 패턴 안에 미처 파악하지 못한 정보가 포함되어 있었던 것이다. 

 

▼반복 된 html 패턴 안에 불필요한 경로 걸러내기▼

 

[파이썬: 웹크롤링] #05 웹에서 텍스트 정보 뽑아내기 with BeautifulSoup, select, get_text (feat. 중복 경로

[왕초보 웹크롤링 무작정 따라하기] 웹크롤링, BeatifulSoup, 태그 추출, .select(), 텍스트 추출, 문자값 추출, get_text() #04 웹에서 텍스트 정보 뽑아내기 문자 데이터 추출하기 (바로가기 Click) 중복 경

charimlab.tistory.com

댓글