1.  BeautifulSoup

🍯  구문을 분석해서 필요한 내용만 추출 할 수 있는 기능을 가지고 있는 패키지

        ➡️  xml or html을 수프객체로 만들어서 추출하기 쉽게 만들어 준다.

from bs4 import BeautifulSoup as bs  # bs4 라이브러리에서 Beautiful Soup를 import
import requests
import pprint

# html 파일 가져오기
with open('./sample.html', 'r', encoding='utf-8') as file:
    html = file.read()

# html.parser : html 코드를 사용하기 쉽게 BeautifulSoup의 객체로 분석
soup = bs(html, 'html.parser')  
# 첫번째 인자: 분석할 내용 전달
# 두번째 인자: "html"로 분석한다는 것을 명시

print(type(soup))  # <class 'bs4.BeautifulSoup'>
print(soup)  # (html 출력)

print(soup.find('title').text)  # This is title
print(soup.find('div').text)  # Division의 약자로, 레이아웃을 나누는데 사용.
print(soup.find('h1').text.strip())  # This is heading1 text.

 


 

1) find ()

🥑  지정된 태그들 중에서 가장 첫 번째 태그만 가져오는 메소드(하나의 값만 반환)로 문자열 형태로 반환
       ➡️  일반적으로 하나의 태그만 존재하는 경우에 사용  만약 여러 태그가 있으면 첫 번째 태그만 가져옴

 

# 속성값 가져오는 경우 형식 (find, find_all 동일)
find(태그명['속성명'])
find(태그명.attrs['속성명'])
find(태그명).get(속성명)
find_all('태그명', attrs={'속성명':'값'})
# 위키피디아 '대구광역시' 페이지
url = 'https://ko.wikipedia.org/wiki/%EB%8C%80%EA%B5%AC%EA%B4%91%EC%97%AD%EC%8B%9C'
resp = requests.get(url)
soup = bs(resp.text, 'html.parser')

first_img = soup.find(name='img')  # img 태그 중에 제일 먼저 나오는 것
print(type(first_img))  # <class 'bs4.element.Tag'>
print(first_img)  
# <img alt="" aria-hidden="true" class="mw-logo-icon" height="50" 
# src="/static/images/icons/wikipedia.png" width="50"/>

target_img = soup.find(name='img', attrs={'alt': 'Daedongyeojido (Gyujanggak) 17-02.jpg'})
print(target_img)
# <img alt="Daedongyeojido (Gyujanggak) 17-02.jpg" class="mw-file-element" 
# data-file-height="3005" data-file-width="4000" decoding="async" height="376" 
# src="//upload.wikimedia.org/wikipedia/commons/thumb/c/c5/
# Daedongyeojido_%28Gyujanggak%29_17-02.jpg/500px-Daedongyeojido_%28Gyujanggak%29_17-02.
# jpg" srcset="//upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Daedongyeojido_
# %28Gyujanggak%29_17-02.jpg/750px-Daedongyeojido_%28Gyujanggak%29_17-02.jpg 1.5x, 
# //upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Daedongyeojido_%28Gyujanggak%
# 29_17-02.jpg/1000px-Daedongyeojido_%28Gyujanggak%29_17-02.jpg 2x" width="500"/>


 

2)  find_all() 

🥑  지정한 태그들을 모두 가져오는 메소드로 가져온 태그들은 모두 리스트에 보관

# 네이버 스포츠 페이지에서 박스 뉴스 제목 들고 옴
url = 'https://sports.news.naver.com/index.nhn'
response = requests.get(url)
soup = bs(response.text, 'html.parser')

today_list = soup.find('ul', {'class': 'today_list'})
print(today_list)

today_list_title = today_list.find_all('strong', {'class', 'title'})
pprint.pprint(today_list_title)  # 리스트로 반환

for title in today_list_title:
    print(title.text.strip())

1. today_list 결과
2. today_list_title 결과
3. 반복문 실행결과

 


 

3) find_all 사용 예제

a. 다음 뉴스 사이트 html 분석

url = 'https://news.daum.net/'
response = requests.get(url)
soup = bs(response.text, 'html.parser')


 

b. a 태그의 갯수 출력

 

   👾  html의 'a' 태그 : 다른 콘텐츠와 연결되는 하이퍼링크(hyperlink)를 정의

print('1. a 태그의 갯수')
print(len(soup.find_all('a')))  # 124

 

c. a 태그 20개만 출력

print('2. a 태그 20개만 출력')
for news in soup.find_all('a')[:20]:
    print(news.text.strip())

실행결과


 

d.  a 태그 링크 5개 출력

print('3. a 태그 링크 5개 출력')
for i in soup.find_all('a')[:5]:
    print(i.attrs['href'])
    print(i.get('href'))
    # -> 둘 중 하나만 쓰면 된다.
print("=" * 20)

 

실행결과


 

e.  특정 클래스 속성을 출력하기

print('4. 특정 클래스 속성을 출력')
print(soup.find_all('div', {'class': 'item_issue'}))
print("=" * 20)

실행결과


f.  링크를 텍스트 파일로 저장

print('5. 링크를 텍스트 파일로 저장')
file = open('../output_02/links.txt', 'w')  # 쓰기 전용 파일 생성

for i in soup.find_all('div', {'class': 'item_issue'}):
    file.write(i.find('a').get('href') + '\n')
file.close()

실행결과

 

 

 

 

 

[ 내용 참고 : IT 학원 강의 ]


 

1.  메소드 method

 

🐰  메소드 method란 특정 객체 object가 가지고 있는 함수 function을 의미
🐰  함수는 독립적으로 호출할 수 있지만, 메소드는 특정 객체를 통해서만 호출할 수 있음

함수()
객체.메소드() : 점(.) 연산자 사용
객체 -> 메소드() php, c

 


 

1)  count()

👩🏻‍🚀  문자열 내부에 포함된 특정 문자열의 개수를 반환하는 메소드

s = '내가 그린 기린 그림은 목 긴 기린 그림이고, 네가 그린 기린 그림은 목 짧은 기린 그림이다.'
print(s.count('기린'))  # 4

# 인덱스를 지정해서 범위를 지정할 수 있음
s = 'best of best'
print(s.count('best',5))  # 1 / 인덱스 5번 부터 검색

# 마이너스 인덱스를 사용할 수 있음
s = 'best of best'
print(s.count('best', -7))  # 1 / o부터 검색

 

 


2) find()

👩🏻‍🚀  문자열 내부에 포함된 특정 문자열을 찾고자 할 때 사용
👩🏻‍🚀  찾고자 하는 문자열이 있으면 그 문자열이 처음으로 나온 위치 즉 인덱스 index를 반환

 

 🐰  find() : 왼쪽부터 찾아서 처음 등장하는 위치를 찾는다

 🐰  rfind() : 오른쪽부터 찾아서 처음 등장하는 위치를 찾는다

 

s = 'apple'
print(s.find('p'))  # 1

# 찾는 문자열이 없는 경우 -1 반환
s = 'apple'
print(s.find('z'))  # -1

if s.find('z') == -1:
    print(s)

# 인덱스를 이용해서 검색할 범위를 지정 가능
# 시작할 인덱스를 지정하지 않는 경우에는 문자열의 처음부터 찾고, 시작할 인덱스를 지정하는 경우 지정된 인덱스부터 찾음
s = 'best of best'
print(s.find('best'))  # 0
print(s.find('best',5))  # 8


# find() 메소드와 찾는 방향이 다른 rfind() 메소드
# right와 find를 합친 이름으로 오른쪽부터 찾음
s = 'best of best'
print(s.find('best'))  # 8

 

  📌  문자열은 0번째 부터 시작, 결과는 해당 글자가 위치한 인덱스를 찾아 리턴함

  📌  찾는 문자열이 없는 경우  -1 반환

 


 

3) index()

👩🏻‍🚀  find() 메소드와 같은 역할을 수행하며 사용방법도 동일. 두 메소드의 차이점은 문자열이 없을 때 발생
👩🏻‍🚀  find() 메소드는 찾는 문자열이 없는 경우 -1을 반환, index() 메소드는 오류 발생

s = 'apple'
print(s.index('p'))  # 1
print(s.index('z'))  # ValueError : substring not found

 


 

4) upper() / lower() / capitalize()

 

 👩🏻‍🚀  upper : 모두 대문자로 변환한 결과를 반환
 👩🏻‍🚀  lower : 모두 소문자로 변환한 결과를 반환
 👩🏻‍🚀  capitalize : 첫 글자는 대문자로 변환하고 나머지는 소문자로 변환한 결과를 반환

 

s = 'Best of best'
print(s.upper())  # BEST OF BEST
print(s.lower())  # best of best
print(s.capitalize())  # Best of best

 


 

5)  join()

 

👩🏻‍🚀  인수로 전달한 반복가능객체(문자열, 리스트 등)의 각 요소 사이에 문자열을 포함시켜 새로운 문자열을 만들고 그 결과를 반환

문자열.join(문자열로 구성된 리스트)
print('-'.join('python'))  # p-y-t-h-o-n

print('+'.join(['a', 'b', 'c', 'd', 'e']))  # a+b+c+d+e

# 포함하는 문자 없이 단순하게 리스트의 요소들을 연결하고자 한다면 빈 문자열 사용
print(' '.join(['x', 'y', 'z']))  # x y z
a = {'a': 'apple', 'b': 'banana'}
print(''.join(a))  # ab / 딕셔너리의 경우 key를 연결

 

 


 

6) split()

 

👩🏻‍🚀  문자열을 '특정한 문자'로 자를 때 사용하는 함수  

s = 'Life is too short'
s2 = s.split()  # split() 메소드에 아무 인수도 전달하지 않으면 공백문자를 기준으로 각 문자열이 분리
print(s2)  # ['Life', 'is', 'too', 'short']

s = '010-1234-5678'
s2 = s.split('-')  # 공백대신 특정 문자열을 기준으로 분리하는 방법
print(s2)  # ['010', '1234', '5678']

 


 

7)  replace()

 

👩🏻‍🚀  문자열의 일부 문자열을 다른 문자열로 바꾼 결과를 반환

s = 'Life is too short'
s2 = s.replace('short', 'long')
print(s2)  # Life is too long

# 특정 문자열을 제거하기 위한 용도로 사용
s = '010-1234-5678'
s2 = s.replace('-', '')
print(s2)  #01012345678

 


 

8)  strip()

 

 strip()    문자열 양옆의 공백을 제거
 lstrip()  문자열 왼쪽의 공백을 제거
 rstrip()  문자열 오른쪽의 공백을 제거

 

s = '     apple'
print(len(s))  # 10

s2 = s.lstrip()
print(s2)  # apple
print(len(s2))  # 5

 

 

 

 

 

 

[ 내용 참고 : IT 학원 강의 자료 ]

+ Recent posts