[혼공분석] 2주차 - 2

LeeHsss·2025년 1월 19일
0

데이터 분석

목록 보기
3/9
post-thumbnail

Chapter 02. 데이터 수집하기

02-2. 웹 스크래핑 사용하기

웹 스크래핑이란 (Web Scraping)

프로그램으로 웹사이트의 페이지를 옮겨 가면서 데이터를 추출하는 작업
웹 크롤링(Web Crawling)이라고도 부른다.

검색 결과 페이지 가져오기

데이터프레임에서 특정 열만 가져오기

  • 원하는 열 이름을 리스트로 만들어서 데이터프레임의 인덱스처럼 사용하면 된다.
books = books_df[['no', 'ranking', 'bookname', 'authors', 'publisher', 'publication_year', 'isbn13']]
books.head()

데이터프레임 행과 열 선택하기: loc 함수

  • Ioc는 메서드이지만 대괄호를 사용해서 행의 목록과 열의 목록을 받는다.

  • 첫 번째 매개변수로 행의 목록을 전달.

  • 두 번째 매개변수로 열의 목록을 전달

    💡 iloc

    • 인덱스의 위치를 사용.
    • 열 이름이 곧 인덱스. 열 인덱스라고도 부름.

    e.g.)

    books_df.iloc[[0,1], [2,3]]
  • 리스트 대신 슬라이스 연산자(:) 를 쓸 수도 있다. (💡 파이썬의 슬라이싱과 다르게 마지막 항목도 포함한다.)

    e.g.)

    books_df.loc[0:3, 'no':'publisher'] 
  • 파이썬 슬라이싱처럼 스텝을 지정할 수도 있다.

    e.g.)

    books_df.loc[::2, 'no':'isbn13']

검색 결과 페이지 HTML 가져오기 : requests.get() 함수

import requests

isbn = 9788936434120 # '소년이 온다: 한강 장편 소설' isbn
url = 'http://www.yes24.com/Product/Search?domain=BOOK&query={}'
r = requests.get(url.format(isbn))

print(r.text) # HTML 출력 

HTML에서 데이터 추출하기 : 뷰티플수프

  • 파이썬 프로그래머들은 HTML 안에 있는 내용을 찾을 때는 뷰티풀수프를 널리 사용 한다.
    • 뷰티플수프 말고 스크래피(Scrapy) 패키지도 인기가 좋다.
    • Scrapy

뷰티플수프(BeautifulSoup) 사용하기

from bs4 import BeautifulSoup

soup = BeautifulSoup(r.text, 'html.parser')

💡 BeautifulSoup

  • 첫번째 매개변수는 파싱할 HTML 문서
  • 두번째 매개변수는 파싱에 사용할 파서 (Parser)
    • Parser: 입력 데이터를 받아 데이터 구조를 만드는 소프트웨어 라이브러리

태그 위치 찾기: find() 함수

  • 태그 위치는 BeautifulSoup 객체의 find() 함수를 사용하면 찾기 쉽다.
  • find 함수의 첫번째 매개변수에 찾을 태그 이름을 지정하고, attrs 매개변수에 찾으려는 태그의 속성을 딕셔너리로 지정한다.
# 예시 
soup.find('div', attrs={'id': 'search'})

id 속성이 search인 div 태그를 찾으라는 의미

# 도서 상세 페이지 링크 찾기 
prd_link = soup.find('a', attrs={'class':'gd_name'})

도서 상세 페이지 링크 찾기 결과

  • prd_link를 딕셔너리처럼 사용해 태그 안의 속성을 참조할 수 있다.
# 링크 주소 얻기
prd_link['href']

도서 상세페이지 링크 주소 조회 결과

테이블 태그를 리스트로 가져오기: fina_all() 함수

  • 특정 HTML 태그를 모두 찾아서 리스트로 반환해준다.

💡 find()와 find_all()의 차이점

  • find()는 지정된 이름을 가진 첫번째 태그를,
  • find_all()은 지정된 이름을 가진 모든 태그를 찾는다.

태그 안의 텍스트 가져오기 : get_text() 함수

  • 태그 안의 텍스트를 가져오기 위해서는 get_text() 함수를 사용 합니다.

전체 도서의 쪽수 구하기 (함수 정의)

def get_page_cnt(isbn):
    url = 'http://www.yes24.com/Product/Search?domain=BOOK&query={}'
    r = requests.get(url.format(isbn))

    soup = BeautifulSoup(r.text, 'html.parser')
    prd_info = soup.find('a', attrs = {'class': 'gd_name'})
    if prd_info == None:
        return ''

    url = 'http://www.yes24.com' + prd_info['href']
    r = requests.get(url) # 도서 상세 페이지 가져오기 
    soup = BeautifulSoup(r.text, 'html.parser')

    prd_detail = soup.find('div', attrs={'id': 'infoset_specific'})
    prd_tr_list = prd_detail.find_all('tr')

    for tr in prd_tr_list:
        if tr.find('th').get_text() == '쪽수, 무게, 크기':
            return tr.find('td').get_text().split()[0]

    return ''

데이터프레임 행 혹은 열에 함수 적용하기: apply() 함수

  • 판다스 데이터프레임은 한 행씩 순차적으로 처리하는데 최적화 되어있지 않다.
  • 그래서 데이터프레임을 for 문으로 반복하는 것은 아주 비효율적
  • apply() 함수를 사용하면 데이터프레임 행 또는 열에 함수를 일괄 적용할 수 있다.
  • axis 매개변수에 기본 값 0을 사용하면 열에, 1을 지정하면 행에 적용한다.

데이터프레임과 시리즈 합치기: merge() 함수

  • 판다스에서 두 데이터프레임을 합치거나 데이터프레임과 시리즈를 합칠 때 merge() 함수를 사용합니다.
    • 첫 번째와 두 번째 매개변수는 합칠 데이터프레임이나 시리즈 객체입니다.
    • 두 객체의 인덱스를 기준으로 합칠 경우 left_index와 right_index 매개변수를 True로 지정한다.
    • 시리즈 객체에 이름을 지정하는 방법: name 속성 사용

💡 merge() 함수 더 알아보기

  • 데이터프레임이나 시리즈를 합칠 때는 매개변수에 합칠 기준을 다양하게 지정하여 데이터를 원하는 형태로 만들 수 있다.
  1. on 매개변수

    • 합칠 때 기준이 되는 열을 지정한다. 이 열은 두 데이터프레임에 모두 존재해야 한다.

    • on 매개변수에 지정한 열의 값이 같은 행끼리 합쳐진다.

      pd.merge(df1, df2, on='col1')
      
      
  2. how 매개변수

    • 합쳐질 방식을 지정한다.
      • inner: 기본 값으로, 두 데이터프레임의 값이 같은 행만 합침
      • left: 첫 번째 데이터프레임을 기준으로 두 번째 데이터프레임을 합침 (두 번째 데이터프레임에 없는 값은 NaN으로 표시된다.)
         pd.merge(df1, df2, how='left', on='col1')
         
      • right: 두 번째 데이터프레임을 기준으로 첫 번째 데이터프레임을 합침 (첫 번째 데이터프레임에 없는 값은 NaN으로 표시된다.)
         pd.merge(df1, df2, how='right', on='col1')
         
      • outer: 두 데이터프레임의 모든 행을 유지하면서 합친다.
         pd.merge(df1, df2, how='outer', on='col1')
         
  3. left_on, right_on 매개변수

    • 합칠 기준이 되는 열의 이름이 서로 다를 경우 각 매개변수에 다르게 지정할 수 있다.
    • 지정한 열의 데이터타입이 같을 필요는 없지만, 비교 가능한 타입이어야 한다.
        # df1의 col1 열, df2의 col3 열 기준으로 합침
         pd.merge(df1,df2, left_on='col1', right_on='col3')
         
  4. left_index, right_index 매개변수

    • 합칠 기준이 열이 아니라 인덱스일 경우 지정할 수 있다. (Boolean 값)
    • 두 데이터프레임에 동일한 열이 존재할 경우에는 첫 번째 데이터프레임의 열 이름에는 _x 접미사가 붙고, 두 번째 데이터프레임의 열 이름에는 _y 접미사가 붙는다.
      pd.merge(df1, df2, left_on='col1', right_index=True)

웹 스크래핑할 때 주의할 점

  1. 웹 사이트에서 스크래핑을 허락하였는지 확인하기
    • robots.txt 파일에서 Disallow 되어 있지 않은지 확인
  2. HTML 태그를 특정할 수 있는지 확인하기
    • 태그 이름이나 속성 등 필요한 HTML 태그를 특정할 수 없다면 웹 스크래핑으로 데이터를 가져오는데 어려움이 있다.
    • 일부 웹 페이지는 웹 브라우저에 로딩된 후 HTML 대신 자바스크립트를 사용해서 웹 서버로부터 데이터를 가져와 화면을 채우는데, 이럴 때는 셀레니움 같은 고급 도구를 사용해야 한다.

💡 웹 스크래핑은 만능 도구가 아니며 최후의 수단으로 사용하는 것이 좋다.

숙제.

필수 숙제

다음과 같은 데이터프레임 df가 있을 때 loc 메서드의 결과가 다른 하나는 무엇인가요?

1. df.loc[[0,1,2], ['col1','col2']]
2. df.loc[0:2, 'col1':'col2']
3. df.loc[:2, [True,True]]
4. df.loc[::2, 'col1':'col2'] 💡(정답)
	- loc 메서드는 파이썬 slicing과 마찬가지로 
	  시작 index, 끝 index, step을 지정할 수 있다.
    - 파이썬 slicing과 다른 점은 loc 메서드는 끝 인덱스를 포함한다.

⬇️ 4번 결과

추가 숙제

p137-138 손코딩 실습으로 원하는 도서의 페이지 수를 추출하고 화면 캡처하기

한강 - 소년이 온다

profile
조금씩 지식의 영역을 넓혀가는 중이에요...😌

0개의 댓글

관련 채용 정보