Python/Web Crawling+Scraping

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

metamong 2022. 3. 21.

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

 

** BeautifulSoup library tolerates highly flawed HTML & still lets you easily extract the data you need

(repairs & parses HTML to make it easier for a program to understand)

1. import & parsing

1> BeautifulSoup import

2> open()의 read() method를 사용하여 sample.html file을 받는다. (encoding은 utf-8 방식)

3> BeautifulSoup(class constructor)을 사용해 dirty HTML을 clean soup으로 변경: returns the entire document at that web page

(BeaufitulSoup knows how to deal with utf-8 string - 즉 utf-8을 unicode형식으로 변경)

* html.parser: Python 3 library에 속한 HTML parser

4> soup 객체의 prettify() 함수를 사용해 html 구조를 파악하기 쉽게 출력해 준다.

 

from bs4 import BeautifulSoup

page = open('sample.html','rt',encoding='utf-8').read()
soup = BeautifulSoup(page,'html.parser')
print(soup.prettify())

 

(+) sample.html (예시) 내용

 

<!DOCTYPE html>
<html>
    <head>
        <title>
            아주 쉬운 HTML문서 샘플입니다.
        </title>
    </head>
    <body>
        <div>
            <p class="inner-text first-item" id="first">
                교육센터
                <a href="http://www.credu.com" id="credu">
                크레듀
                </a>
            </p>
            <p class="inner-text second-item">
                파이썬 사이트
                <a href="https://www.python.org" id="python">
                Python 
                </a>
            </p>
        </div>
        <p class="outer-text first-item" id="second">
            <b>
                데이터 과학은 멋집니다.
            </b>
        </p>
        <p class="outer-text">
            <b>
                지속적인 학습이 필요합니다. 
            </b>
        </p>
    </body>
</html>

 

2. find_all() & find()로 원하는 내용 출력하기

* prettify()의 output을 통해 전체적인 html 구조를 파악했으며, 이젠 html의 원하는 tag 이름을 두 find()에 집어넣어 tag 내용을 출력한다

* find_all() 함수는 특정 tag를 모두 검색하는 함수이고, find() 함수는 특정 tag 한 개(첫번째 한 개)만 검색하는 함수이다

 

[1] 기초 & 특성 class_, id 가지는 tag 찾기

Q) 예를 들어 p tag 한 개만 검색하고 싶거나 & outer-text class 속성을 가지는 모든 p tag를 검색하고 싶을 때

 

print(soup.find('p'))
print(soup.find_all('p',class_='outer-text'))
print(soup.find("p", {"class":"outer-text"})) # same with the 2nd row code

 

* 출력결과) '더보기' 클릭

 

- find

더보기
더보기
<p class="inner-text first-item" id="first">
                교육센터
                <a href="http://www.credu.com" id="credu">
                크레듀
                </a>
</p>

 

- find_all

더보기
더보기
[<p class="outer-text first-item" id="second">
<b>
                데이터 과학은 멋집니다.
            </b>
</p>, <p class="outer-text">
<b>
                지속적인 학습이 필요합니다. 
            </b>
</p>]

 

Q) tag의 id 속성이 first인 경우를 검색하고 싶을 때

 

print(soup.find_all(id='first'))

 

* 출력결과 - 더보기 클릭

더보기
더보기
[<p class="inner-text first-item" id="first">
                교육센터
                <a href="http://www.credu.com" id="credu">
                크레듀
                </a>
</p>]

[2] get_text() - 내부 contents 상세 출력

Q) 특정 tag안의 문자열을 반환하고 싶을 때 (get_text() 사용) - 내부 콘텐츠만 반환하고 싶을 때

 

for tag in soup.find_all('p'):
	print(tag.get_text())

 

* 출력결과 - 더보기 클릭

더보기
더보기
                교육센터
                
                크레듀
                


                파이썬 사이트
                
                Python 
                



                데이터 과학은 멋집니다.
            



                지속적인 학습이 필요합니다.

 

[3] 두 종류의 tag 반환 - list 형태 인자

Q) 두 종류의 tag - p & a tag들을 반환하고 싶을 때 - list 형태로 find_all() 인자에 집어넣어 반환 가능

 

print(soup.find_all(['a', 'p']))

 

* 출력결과 - 더보기

더보기
더보기
[<p class="inner-text first-item" id="first">
                교육센터
                <a href="http://www.credu.com" id="credu">
                크레듀
                </a>
</p>, <a href="http://www.credu.com" id="credu">
                크레듀
                </a>, <p class="inner-text second-item">
                파이썬 사이트
                <a href="https://www.python.org" id="python">
                Python 
                </a>
</p>, <a href="https://www.python.org" id="python">
                Python 
                </a>, <p class="outer-text first-item" id="second">
<b>
                데이터 과학은 멋집니다.
            </b>
</p>, <p class="outer-text">
<b>
                지속적인 학습이 필요합니다. 
            </b>
</p>]

 

[4] lambda function 정의하여 검색하기

* lambda 특정 함수(일회성 함수)로 만들어 해당 함수의 반환값으로 원하는 tag를 검색할 수 있다.

 

→ tag의 속성값이 1개인 tag만 선택하여 해당 tag를 반환하는 lambda 함수를 만들고 find_all()에 집어넣어 반환한다

 

print(soup.find_all(lambda tag:len(tag.attrs) == 1))

 

* 출력결과 - 더보기

더보기
더보기
[<p class="inner-text second-item">
                파이썬 사이트
                <a href="https://www.python.org" id="python">
                Python 
                </a>
</p>, <p class="outer-text">
<b>
                지속적인 학습이 필요합니다. 
            </b>
</p>]

 

3. re 모듈과 결합하여 '더 상세하게' 검색하기

* 정규표현식 pattern을 정의하는 python에 내장된 re module

→ re를 통해 수많은 tag들 중 원하는 tag를 정규표현식(regular expression)을 사용하여 더 효율적이게 검색할 수 있다.

→ 주로 re.compile() 활용

 

import re

 

Q) a로 시작하는 tag name의 tag만 검색

 

tagsStartingWitha = soup.findAll(re.compile('^a'))
print(tagsStartingWitha)
print([tag.name for tag in tagsStartingWitha])

 

→ 출력결과) 더보기 클릭

더보기
더보기
[<a href="http://www.credu.com" id="credu">
                크레듀
                </a>, <a href="https://www.python.org" id="python">
                Python 
                </a>]
['a', 'a']

 

→ findAll의 결과 'a'로 시작하는 총 tag들의 집합체가 list 형태로 tagsStartingWitha에 저장된다

→ 해당 list의 각각의 tag의 tag.name을 print하면 해당 HTML 파일에 존재하는 'a로 시작하는' 태그명이 출력된다.

 

Q) b로 끝나는 tag name의 tag만 검색

→ re.compile 인자에 "b$"를 집어넣는다


BeautifulSoup 간단 학습 끝! 🤟

 

 

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

댓글