데이터 수집 방법
크롤링
: 추천 x (*불법 소지 다분함, 최근까지도 다수 기업의 법적 분쟁 사례 있음)
크롤링의 최종목표: 웹데이터를 DataFrame으로 변환
API
: 추천 o (*고비용, 이용 제한 x, 이용매뉴얼만 잘 익히면 API 크롤링 완)
- 부동산 데이터 수집(서울시 빅데이터 센터, 공공데이터 포털) https://data.seoul.go.kr/together/guide/useGuide.do
- 공공데이터 요청 시, 응답할 때 두가지 컨셉으로 응답 (XML, JSON)
- 일괄처리 함수 만들기 (처리.py)
- 자동 적용
- 배치 처리
- 윈도우에서는 스케쥴러 프로그램
- Linux에서는 Crontab 설정
- 해당 스크립트 (처리.py)가 정해진 시간에 코드가 돌아감
- 일괄처리 함수 만들기 (처리.py)
웹 스크래핑 시, 주의점
1. 어떤 웹 페이지를 스크래핑 하고자 한다면, 먼저 robots.txt 확인하기!
웹 스크래핑 요청이 많을 경우, 웹 서버에 부담됨, 간혹 일정 기간 접속이 막히기도 함
2. HTML 태그를 특정할 수 있는지 확인!
웹 스크래핑으로만 가져오기 힘든 페이지가 존재함, 또 웹 페이지는 언제 어떻게 바뀔지 모르기 때문에 스크래핑 프로그램이 원하는 데이터를 찾지 못하는 경우가 빈번하게 발생하며 이를 유지 보수하기어렵게 만듦
yes24의 ISBN 정보 가져오기
1. ISBN을 활용해 YES24의 도서 검색 페이지의 HTML을 가져온다.
2. 검색 결과에서 해당 도서를 선택하여 상세 페이지를 가져온다.
3. 상세 페이지의 '쪽수' 페이지가 있는 '품목정보'인 <div>를 선택하여 테이블에 있는 < tr>태그를 가져옵니다.
4. 쪽수가 들어 있는 <th>를 찾아 <td>에 담긴 값을 반환합니다.
5. 데이터프레임 행 혹은 열에 함수 적용하기: apply() 메서드
6. top10_books의 각 행에 get_page_cnt() 함수를 적용하여 10개 도서의 쪽수를 한 번에 구하기 -> 각 행 또는 열에 함수를 일괄 적용 시, apply() 메서드 사용
7. lambda로 작성 시, page_count = top10_books.apply(lambda row: get_page_cnt2(row['isbn13']), axis=1)
8. 데이터프레임과 시리즈 합치기: merge() 함수
(*시리즈 객체의 name 속성을 사용하면 간단하게 이름 지정 가능! / 두 객체의 인덱스를 기준으로 합칠 경우, left_index와 right_index 매개변수를 True로 지정)
# 반복 작업을 get_page_cnt() 함수로 만들어 ISBN 쪽수 반환하기
def get_page_cnt(isbn):
# Yes24 도서 검색 페이지 URL
url = 'http://www.yes24.com/Product/Search?domain=BOOK&query={}'
# URL 에 ISBN을 넣어 HTML을 가져옵니다.
r = requests.get(url.format(isbn))
soup = BeautifulSoup(r.text, 'html.parser') # HTML 파싱
# 검색 결과에서 해당 도서를 선택합니다.
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')
# 품목정보 <div>를 선택합니다.
prd_detail = soup.find('div', attrs={'id':'infoset_specific'})
# 테이블에 있는 <tr> 태그를 가져옵니다.
prd_tr_list = prd_detail.find_all('tr')
# 쪽수가 들어 있는 <th>를 찾아 <td>에 담긴 값을 반환합니다.
for tr in prd_tr_list:
if tr.find('th').get_text() == '쪽수, 무게, 크기':
return tr.find('td').get_text().split()[0]
return ''
# 데이터프레임 행 혹은 열에 함수 적용하기: apply() 메서드
top10_books = books.head(10)
# top10_books의 각 행에 get_page_cnt() 함수를 적용하여 10개 도서의 쪽수를 한 번에 구하기 -> 각 행 또는 열에 함수를 일괄 적용 시, apply() 메서드 사용
def get_page_cnt2(row):
isbn = row['isbn13']
return get_page_cnt(isbn)
# lambda로 작성 시, page_count = top10_books.apply(lambda row: get_page_cnt2(row['isbn13']), axis=1)
page_count = top10_books.apply(get_page_cnt2, axis=1) # axis 매개변수 1-> 행, 0->열
print(page_count)
# 데이터프레임과 시리즈 합치기: merge() 함수
page_count.name = 'page_count' # 시리즈 객체의 name 속성을 사용하면 간단하게 이름 지정 가능!
print(page_count)
top10_with_page_count = pd.merge(top10_books, page_count, left_index=True, right_index=True) # 두 객체의 인덱스를 기준으로 합칠 경우, left_index와 right_index 매개변수를 True로 지정
top10_with_page_count