728x90

Review
참고 포스팅 :

2020/05/23 - [Python Programming/Using Packages] - [데이터크롤링] 데이터크롤링을 위해 HTML 이해하기

[데이터크롤링] 데이터크롤링을 위해 HTML 이해하기

안녕하십니까, 간토끼입니다. 파이썬 관련 첫 포스팅입니다. (사실 파이썬은 자신없지만) 데이터크롤링 시리즈는 약 5번에 걸쳐 게시될 예정입니다. 1. 데이터크롤링 데이터크롤링, 혹은 스크래�

datalabbit.tistory.com

2020/05/24 - [Python Programming/Using Packages] - [데이터크롤링] Requests, BeautifulSoup 패키지를 이용한 파이썬 크롤링 맛보기

[데이터크롤링] Requests, BeautifulSoup 패키지를 이용한 파이썬 크롤링 맛보기

Review 참고 포스팅 : 2020/05/23 - [Python Programming/Using Packages] - [데이터크롤링] 데이터크롤링을 위해 HTML 이해하기 [데이터크롤링] 데이터크롤링을 위해 HTML 이해하기 안녕하십니까, 간토끼입니다...

datalabbit.tistory.com


안녕하십니까, 간토끼입니다.

어느덧 데이터 크롤링 시리즈의 세 번째 게시글입니다.

첫 포스팅에서는 크롤링을 위해 HTML 구조를 살펴보았고,
그 다음 포스팅에서는 requests, beautifulsoup 패키지를 이용해 직접 크롤링을 해봤습니다.
이번 포스팅에서는 이렇게 크롤링한 결과를 Openpyxl 패키지를 이용해 엑셀 파일에 저장해보는 방법에 대해서 다뤄보겠습니다.


Openpyxl 패키지파이썬에서 엑셀을 다룰 수 있는 도구입니다.

사실 엑셀같은 스프레드시트 형식의 데이터를 다룰 수 있는 패키지는 판다스(Pandas)가 정말 유명하죠.
물론 R에서는 기본적으로 데이터프레임을 다룰 수 있도록 설계가 되어있습니다만, 파이썬은 그렇지 않으므로 판다스를 이용해 데이터프레임 형식을 다룰 수 있도록 해줍니다.

이것만 보면 판다스와 Openpyxl이 크게 다르지 않아 보이지만, 약간 주안점이 다르다고 보시면 됩니다.
판다스는 데이터프레임 자체를 다룰 수 있도록 하는 패키지라면,
openpyxl은 엑셀을 파이썬에서 다룰 수 있도록 하는 패키지라는 거죠.

따라서 패키지의 여러 옵션이나 기타 여러 사항이 엑셀을 다루는 것과 유사하게 설계 되어있습니다.

# Opnepyxl 패키지 설치하기
pip install openpyxl

마찬가지로 저번 패키지 설치와 유사하게 pip 명령어를 사용하여 패키지를 설치해줍니다.
pip 명령어는 Anaconda Prompt이나 Terminal을 통해 실행해야 한다고 말씀드렸습니다.

설치하셨다면 openpyxl의 구조를 한번 살펴보겠습니다.

우리가 일반적으로 아는 엑셀은 크게 3가지 구조로 이루어져 있습니다.
1. Workbook : 엑셀파일의 전체 작업공간 -> 여러개의 sheet를 포함하는 전체 집합 개념
2. Sheet : 단일 작업공간 -> 데이터프레임 자체
3. Cell : 데이터가 저장되는 작은 공간 -> Sheet 내 하나의 성분

마찬가지로 openpyxl 에서도 이와 유사한 구조를 기반으로 명령을 내릴 수 있습니다.

# 1. openpyxl 가져오기
import openpyxl

# 2. 내가 작업할 Workbook 생성하기
wb = openpyxl.Workbook()

# 3. 작업할 Workbook 내 Sheet 활성화
sheet = wb.active

# 4. Sheet 내 Cell 선택 (A1셀에 1이라는 값 할당)
sheet['A1'] = 1

# 5. 작업 마친 후 파일 저장 (파일명 저장할 때 확장자 - .xlsx 필수 !)
wb.save("파일명.xlsx")


위 과정을 거치면 엑셀 파일의 A1 셀에 1이 입력되어 있는 것을 확인할 수 있습니다.

혹은 엑셀 파일도 결국은 데이터프레임 형식이므로, 행렬과 유사하게 행번호와 열번호로 데이터를 선택할 수도 있습니다.

# 행번호, 열번호로 데이터 입력하기
sheet.cell(row = 1, column = 1).value = 1

.cell(row = m, column = n ).value 라는 method를 이용하면 (m,n)자리에 직접 값을 입력할 수 있습니다.

근데 이렇게 하나씩 데이터를 삽입하려면 굉장히 귀찮지 않을까요?

우리가 일반적으로 데이터프레임에 데이터를 쌓는 과정을 생각해보면,
특정 행에 각 변수(열)에 따라 데이터를 차곡차곡 쌓아나가는 걸 생각해볼 수 있습니다.

  나이 성별
1번 사람 25 178
2번 사람 23 162
... ... ... ...
n번 사람 47 165


이런 데이터프레임이 있다고 가정하면, 먼저 1번 사람을 고정하고 (나이, 성별, 키)를 입력하겠죠?
그 다음은 2번 사람을 고정하고, 2번 사람의 (나이, 성별, 키)를 입력할 것입니다.
이런 식으로 쭉 반복하며 n번 사람의 데이터까지 입력하면 데이터프레임을 완성할 수 있을 것입니다.

즉 for문을 중첩으로 쌓아서, 특정 i번째 행을 고정하면, i번째 행에 해당하는 데이터를 각 열에 맞게 삽입을 하겠죠.

openpyxl에서는 이러한 번거로운 과정을 방지하고자 .append( ) 함수를 이용할 수 있게 해줍니다.
즉 특정 행의 데이터를 list 형식으로 저장한 후, 일괄적으로 각 행에 추가할 수 있게 해준다는 것이죠.

저번 주에 다룬 네이버TV 예제를 이용해 직접 수집 후 엑셀 파일로 저장해보겠습니다.

# 네이버TV 예제 : 데이터 수집 및 저장

# 1. 패키지 install
import requests
from bs4 import BeautifulSoup
import openpyxl

# 2. Workbook 생성
wb = openpyxl.Workbook()

# 3. Sheet 활성
sheet = wb.active

# 4. 데이터프레임 내 header(변수명)생성
sheet.append(["제목", "채널명", "조회수", "좋아요수"])

# 5. 데이터 크롤링 과정
raw = requests.get("https://tv.naver.com/r")
html = BeautifulSoup(raw.text, 'html.parser')

container = html.select("div.inner")

for con in container:
	t = con.select_one("dt.title").text.strip() #제목
    c = con.select_one("dd.chn").text.strip() #채널
    h = con.select_one("span.hit").text.strip() #조회수
    l = con.select_one("span.like").text.strip() #좋아요수
    
    # sheet 내 각 행에 데이터 추가
    sheet.append([t, c, h, l])


# 6. 수집한 데이터 저장
wb.save("naver_tv.xlsx")


잘 담긴 걸 알 수 있습니다.

좀 더 재밌는 예제를 살펴보죠.
여긴 다음이니까... 이번엔 네이버 말고 다음 뉴스의 기사 데이터를 수집해봅시다.

import requests
from bs4 import BeautifulSoup
import openpyxl

wb = openpyxl.Workbook()
sheet = wb.active

# 1. 검색어 입력하기
search = input("검색할 데이터를 입력해주세요 : ")

# 2. 데이터 크롤링 진행하기
sheet.append(["검색어명", "기사 제목", "기사 요약"])

for p in range(1, 10+1, 1):
    raw = requests.get("https://search.daum.net/search?w=news&DA=PGD&enc=utf8&cluster=y&cluster_page=1&q={s}&p={p}".format(s = search, p = p))
    html = BeautifulSoup(raw.text, 'html.parser')

    container = html.select("ul#clusterResultUL li")
    for c in container:
        # 기사 제목 : div.wrap_tit.mg_tit a
        title = c.select_one("div.wrap_tit.mg_tit a").text.strip()
        # 기사 요약 : p.f_eb.desc
        content = c.select_one("p.f_eb.desc").text.strip()

        sheet.append([search, title, content])

wb.save("daum_news.xlsx")


요즘 류현진 뭐하나 궁금해서 류현진을 검색했습니다.
input을 이용해 원하는 검색어를 받아주고, 크롤링을 진행합니다.

그리고 다음 주소를 보면
"https://search.daum.net/search?w=news&DA=PGD&enc=utf8&cluster=y&cluster_page=1&q={s}&p={p}".format(s = search, p = p)

이렇게 되어있는데요.
주소에서 q = ' ' 부분은 검색어를 입력받는 부분이고, p = ' ' 이 부분은 페이지를 입력받는 부분입니다.
이를 이용해 format 메소드를 사용하여 검색어와 원하는 페이지를 모두 입력해봅시다.

코드를 보면 저는 1페이지부터 10페이지까지 수집했어요.

결과입니다.

짜잔~ 이렇게 결과가 잘 수집된 걸 알 수 있습니다.
한 페이지당 기사가 10개 있으니, 10페이지 담아서 총 100개가 담겼습니다.

다음 포스팅에서는 텍스트말고 이미지 데이터를 크롤링해보겠습니다.

감사합니다.
잘 읽으셨다면 게시글 하단에 ♡(좋아요) 눌러주시면 감사하겠습니다 :)
(구독이면 더욱 좋습니다 ^_^)



- 간토끼(DataLabbit)
- University of Seoul
- Economics, Data Science

728x90

+ Recent posts