본문 바로가기
국비 교육/데이터

[데이터 수집] 웹 스크래핑 - 2

by 육츠 2023. 10. 31.
Contents 접기

BeautifulSoup 패키지

import requests
from bs4 import BeautifulSoup 설치

parser 종류
- html.parser : 파이썬 기본제공
- lxml : 기본값
- xml
- html5lib

from bs4 import BeautifulSoup

# html.parser
soup = BeautifulSoup('<a></p>','html.parser')
print('html.parser')
print(soup)
# html.parser
# <a></a> 강제 형변환

#lxml
soup = BeautifulSoup('<a></p>','lxml')
print('lxml')
print(soup)
# lxml
# <html><body><a></a></body></html> 강제 형변환

 

기본 사용법

- text: 태그 없이 안에 내용만 출력
- name: 태그 이름 출력
- string: 서브쿼리 없을때 출력

import requests
from bs4 import BeautifulSoup

url ='https://ko.wikipedia.org/wiki/%EC%9B%B9_%ED%81%AC%EB%A1%A4%EB%9F%AC'
res = requests.get(url)

# soup 객체 생성
soup = BeautifulSoup(res.text,'lxml')

# 태그 이용한 접근 가능
print(soup.title.text)
print(soup.footer.ul.li.text)
# print(soup.footer.ul.li.find_next_sibling().text) # 같은 레벨에 있는 다른 li 태그 읽어옴


# 태그와 속성을 이용한 접근
print(soup.a) # soup 객체에서 첫 번째로 만나는 a element를 출력
print(soup.a['href']) 
# print(soup.a['id']) # 만약 속성이 존재하지 않을 경우 error 발생

# find() 함수를 이용한 태그 내의 다양한 속성을 이용한 접근
print(soup.find('a',attrs={'title':'구글봇'}))

# 웹 크롤러 - 위키백과, 우리 모두의 백과사전
#  이 문서는 2023년 4월 30일 (일) 18:34에 마지막으로 편집되었습니다.
# 모든 문서는 크리에이티브 커먼즈 저작자표시-동일조건변경허락 4.0에 따라 사용할 수 있으며, 추가적인 조건이 적용될 수 있습니다. 자세한 내용은 이용 약관을 참고하십시오.Wikipedia®는 미국 및 다른 국가에 등록되어 있는 Wikimedia Foundation, Inc. 소유의 등록 상표입니다.
# <a class="mw-jump-link" href="#bodyContent">본문으로 이동</a>
# #bodyContent
# <a href="/wiki/%EA%B5%AC%EA%B8%80%EB%B4%87" title="구글봇">구글봇</a>

 

HTML 은 계층적 구조를 가지고 있다. (부모자식 관계, 형제관계 존재)

자신을 포함한 부모 태그까지 출력

html = """
<html>
    <head>
        <title>crawl</title>
    </head>
    <body>
        <p class='a' align='center'>text1</p>
        <p class='b' align='center'>text2</p>
        <p class='c' align='center'>text3</p>
        <div>
            <img src='/source' width='300' height='200'>
        </div>
    </body>
</html>
"""

from bs4 import BeautifulSoup

soup = BeautifulSoup(html,'html.parser')
contens = soup.find('body')
img_tag = contens.find('img')

print(img_tag.parent) # 자기 자신을 포함한 부모까지

#<div>
#<img height="200" src="/source" width="300"/>
#</div>

print(img_tag.find_parent('body')) # 지정된 특정 부모 태그까지 올라가 검색반환
# <body>
# <p align="center" class="a">text1</p>
# <p align="center" class="b">text2</p>
# <p align="center" class="c">text3</p>
# <div>
# <img height="200" src="/source" width="300"/>
# </div>
# </body>

result = soup.find('body')
print(result.text) # 검색결과의 하부 태그에 있는 모든 텍스트만 검색결과로 가져온다


# text1
# text2
# text3

형제 태그를 검색하는 방법
- find_next_sibling(): 바로 다음 형제 태그를 검색
- find_next_siblings(): 모든 다음 형제 태그를 검색
- find_previous_sibling(): 바로 이전 형제 태그를 검색
- find_previous_siblings(): 모든 이전 형제 태그를 검색

 

검색

- find(): 해당 태그에 대한 첫 번째 정보
- find_all(): 해당 태그에 대한 모든 정보를 리스트 형식으로 (limit 으로 개수 제한)
- css 속성

import requests
from bs4 import BeautifulSoup

res = requests.get('http://www.naver.com')
soup = BeautifulSoup(res.text,'lxml')

print(soup.find_all('a',limit=2))
# [<a href="#topAsideButton"><span>상단영역 바로가기</span></a>,
# <a href="#shortcutArea"><span>서비스 메뉴 바로가기</span></a>]

# css 속성
result = soup.find_all('span',attrs={'class':'blind'})
print(result[0])

# <span class="blind">재생시간</span>
# 개수를 len() 하여 세고 첫 번째 값만 우선 보여줌