새로새록

bs4 -메소드 체이닝 & 엑셀/csv저장 본문

소프트웨어융합/코드잇 정리.py

bs4 -메소드 체이닝 & 엑셀/csv저장

류지나 2021. 12. 17. 15:05

Beautiful Soup 라이브러리

Beautiful Soup 공식 문서


 

메소드 체이닝

메소드 체이닝은 메소드의 리턴값을 변수에 저장하지 않고, 리턴값에 바로 또 다른 메소드를 호출하는 것을 뜻합니다.

예를 들어 select_one() 메소드는 태그를 리턴하는데요. select_one() 바로 뒤에 태그에 쓰는 메소드를 호출해 주면 됩니다. select_one(), select(), get_text() 같은 것들이 있겠죠?

# 1. selector1에 매칭되는 태그를 찾은 다음 그 안에서 selector2에 매칭되는 태그 선택
soup.select_one(selector1).select_one(selector2)

# 2. selector1에 매칭되는 태그를 찾은 다음 그 안에서 selector2에 매칭되는 모든 태그 선택
soup.select_one(selector1).select(selector2) 

# 3. selector1에 매칭되는 태그를 찾은 다음 그 안에서 텍스트 추출
soup.select_one(selector1).get_text()

메소드 체이닝을 사용하면 코드가 더 간결해 지지만, 코드의 가독성은 떨어질 수 있으니까 주의해 주세요. 특히 체인이 너무 길어지면 코드의 가독성이 떨어질 겁니다.

참고로 이번 레슨 첫 부분에서 본 .tagname 문법도 체이닝을 할 수 있습니다. 태그를 계속 타고 들어가야 할 때 .tagname을 계속 붙여 써 주면 됩니다.

...
    <div class="data">
      <div>
        <h2>제목</h2>
        <p>내용<b>키워드</b>내용</p>
        <a href="www.example.com">링크</a>
      </div>
    </div>
...

예를 들어 위와 같은 HTML 구조에서 b 태그 안에 있는 키워드를 가져와야 한다면. 아래와 같은 코드를 쓸 수 있습니다.

div_tag = soup.select_one('div.data')
keyword = div_tag.div.p.b.get_text()
print(keyword)
키워드

엑셀저장
import requests
from bs4 import BeautifulSoup
from openpyxl import Workbook


wb = Workbook(write_only=True)
ws = wb.create_sheet('TV Ratings')
ws.append(['순위', '채널', '프로그램', '시청률'])



response = requests.get("https://workey.codeit.kr/ratings/index")
rating_page = response.text

soup  = BeautifulSoup(rating_page, 'html.parser')
for tr_tag in soup.select('tr')[1:]:
    td_tags = tr_tag.select('td')
    row = [
        td_tags[0].get_text(), # 순위
        td_tags[1].get_text(), # 채널
        td_tags[2].get_text(), # 프로그램
        td_tags[3].get_text(), # 시청률
    ]
    ws.append(row)
wb.save('시청률_2010년1월1주차.xlsx')

 

csv저장
import csv
import requests
from bs4 import BeautifulSoup

# CSV 파일 생성
csv_file = open('시청률_2010년1월1주차.csv', 'w')
csv_writer = csv.writer(csv_file)

# 헤더 행 추가
csv_writer.writerow(['순위', '채널', '프로그램', '시청률'])

response = requests.get("https://workey.codeit.kr/ratings/index")
rating_page = response.text

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

for tr_tag in soup.select('tr')[1:]:
    td_tags = tr_tag.select('td')
    row = [
        td_tags[0].get_text(),
        td_tags[1].get_text(),
        td_tags[2].get_text(),
        td_tags[3].get_text()
    ]
    # 데이터 행 추가
    csv_writer.writerow(row)

# CSV 파일 닫기
csv_file.close()

엑셀
import requests
from bs4 import BeautifulSoup
from openpyxl import Workbook

# 워크북 생성
wb = Workbook(write_only=True)
ws = wb.create_sheet()
ws.append(['지점 이름', '주소', '전화번호'])

# HTML 코드 받아오기
response = requests.get("https://workey.codeit.kr/orangebottle/index")

# BeautifulSoup 사용해서 HTML 코드 정리
soup = BeautifulSoup(response.text, 'html.parser')

# 모든 지점에 대한 태그 가져오기
branch_tags = soup.select('div.branch')

for branch_tag in branch_tags:
    # 각 태그에서 지점 이름, 전화번호 가져오기
    branch_name = branch_tag.select_one('p.city').get_text()
    address = branch_tag.select_one('p.address').get_text()
    phone_number = branch_tag.select_one('span.phoneNum').get_text()
    ws.append([branch_name, address, phone_number])

wb.save('오렌지_보틀.xlsx')

 

 

CSV
import requests
from bs4 import BeautifulSoup
import csv

# CSV 파일 생성
csv_file = open('오렌지_보틀.csv', 'w')
csv_writer = csv.writer(csv_file)
csv_writer.writerow(['지점 이름', '주소', '전화번호'])

# HTML 코드 받아오기
response = requests.get("https://workey.codeit.kr/orangebottle/index")

# BeautifulSoup 사용해서 HTML 코드 정리
soup = BeautifulSoup(response.text, 'html.parser')

# 모든 지점에 대한 태그 가져오기
branch_tags = soup.select('div.branch')

for branch_tag in branch_tags:
    # 각 태그에서 지점 이름, 전화번호 가져오기
    branch_name = branch_tag.select_one('p.city').get_text()
    address = branch_tag.select_one('p.address').get_text()
    phone_number = branch_tag.select_one('span.phoneNum').get_text()
    csv_writer.writerow([branch_name, address, phone_number])

csv_file.close()

import requests
from bs4 import BeautifulSoup
from openpyxl import Workbook

# 워크북 생성
wb = Workbook(write_only=True)
ws = wb.create_sheet()
ws.append(['기간', '순위', '프로그램', '시청률'])

for year in range(2010, 2019):
    for month in range(1, 13):
        for weekIndex in range(0, 5):
            # 웹 페이지 가져와서 BeautifulSoup 생성
            url = "https://workey.codeit.kr/ratings/index?year={}&month={}&weekIndex={}".format(year, month, weekIndex)
            response = requests.get(url)
            rating_page = response.text
            soup = BeautifulSoup(rating_page, 'html.parser')

            for tr_tag in soup.select('tr')[1:]:
                # 데이터 행의 채널이 SBS인 경우만 데이터 행 저장
                channel = tr_tag.select_one('td.channel').get_text()
                if channel == 'SBS':
                    # 데이터 행의 기간, 순위, 프로그램, 시청률 저장
                    period = "{}년 {}월 {}주차".format(year, month, weekIndex + 1)
                    td_tags = tr_tag.select('td')
                    rank = td_tags[0].get_text()
                    program = td_tags[2].get_text()
                    percent = td_tags[3].get_text()
                    ws.append([period, rank, program, percent])

wb.save('SBS_데이터.xlsx')



메소드 체이닝