순서
- url 준비
- requests를 사용하여 url로부터 정보 가져오기
- beautifulsoup을 사용하여 html 형식으로 파싱하기
- 원하는 정보 지정해서 담기
- 문자열만 추출
0. 라이브러리
import requests # url에서 정보 요구!!
from bs4 import BeautifulSoup # 이걸로 가져온 정보를 정리할거야
1. url 준비
url = '찾고자 하는 정보가 포함된 페이지 url'
2. requests를 사용하여 url로부터 정보 가져오기
content = requests.get(url).content # url로부터 정보(content)를 가져와
url에 담긴 정보가 이렇게나 많습니다.
이걸 컴퓨터가 이해하기 쉽게 정리하는 작업을 beautifulsoup이 도와줍니다.
3. beautifulsoup을 사용하여 html 형식으로 파싱하기
컴퓨터가 이해하기 쉬운 형태(html)로 변환(parsing)하는 개념.
soup = BeautifulSoup(content, 'html.parser')
훨씬 깔끔해졌죠?
이 많은 정보 중에서 제가 원하는 정보만 가져오겠습니다.
4. 원하는 정보 지정해서 담기
# 가장 먼저 나오는 하나만 찾아라 : find()
names = soup.find_all(attrs={'class' : 'sr-hotel__name'}) # 호텔 이름
rates = soup.find_all(attrs={'class' : 'bui-review-score__badge'}) # 호텔 평점
잠깐!
'sr-hotel__name' 이게 호텔 이름을 뜻하는 클래스인지 어떻게 알았을까요?
부킹닷컴 화면으로 돌아가서 F12를 눌러보시면 개발자도구 창이 생성됩니다.
지금 보여지는 화면이 어떤 구조로 되어있는지 확인할 수 있는 공간인데요,
개발자 도구창의 왼쪽 모서리에 마우스 커서 모양을 클릭하시고 크롤링하고자 하는 정보에 마우스를 가져가면
해당 정보를 정의하고 있는 class 값 혹은 id 값을 찾을 수 있습니다.
이렇게 말이죠 !!
5. 문자열만 추출
마지막으로 필요한 문자열만 추출하면 끝입니다.
print(soup.find_all(attrs={'class':'sr-hotel__name'})[0].text)
print(soup.find_all(attrs={'class':'bui-review-score__badge'})[0].text)
예시로 리스트의 첫번째 요소만 추출했습니다.
이제 for문을 사용해서 모든 정보를 가져오는건 식은죽 먹기죠?
결론
이번 포스팅은 beautifulsoup이 어떻게 작동하는지, 간단한 뼈대를 집중해서 분석해보았습니다.
하지만 실제 유의미한 데이터로 사용하기 위해서는
체크인/아웃 날짜, 호텔이름, 평점, 인원 수, 객실 유형, 가격, 할인율 등 더 많은 정보를 필요로 합니다.
이에 따라 객실이 매진되어 가격정보가 사라지는 경우,
주말에는 2박 이상만 판매하는 호텔의 경우 등
다양한 예외사항에 대해서 고민하고 분석해야 할 필요가 있습니다.
실제로 제가 게스트하우스에서 일을 하며 경쟁사들의 객실 가격을 실시간으로 파악하기 위해 코드를 짰었는데,
에러가 발생할때마다 수정해주며 정말 많이 보완해주었던 기억이 있습니다.
특히 가격 정보는 beautifulsoup으로 크롤링되지 않았었는데, 그 이유를 찾는데 30시간 이상 투자한 것 같습니다.
이것과 관련해서는 selenium을 활용한 크롤링 편에서 설명해보겠습니다.
전체 코드 입니다.
import requests
from bs4 import BeautifulSoup
import pandas as pd
url = 'https://www.booking.com/searchresults.ko.html?label=gen173nr-1FCAEoggI46AdIM1gEaH2IAQGYARe4ARfIAQzYAQHoAQH4AQuIAgGoAgO4AsLN3PYFwAIB0gIkZTkwMGZhZWMtY2YzZS00M2UwLTkxMDMtNDFkYjQzOTVjNzZh2AIG4AIB&sid=fcf64615c790e8ee11e9baa9f0175b1c&sb=1&sb_lp=1&src=index&src_elem=sb&error_url=https%3A%2F%2Fwww.booking.com%2Findex.ko.html%3Flabel%3Dgen173nr-1FCAEoggI46AdIM1gEaH2IAQGYARe4ARfIAQzYAQHoAQH4AQuIAgGoAgO4AsLN3PYFwAIB0gIkZTkwMGZhZWMtY2YzZS00M2UwLTkxMDMtNDFkYjQzOTVjNzZh2AIG4AIB%3Bsid%3Dfcf64615c790e8ee11e9baa9f0175b1c%3Bsb_price_type%3Dtotal%26%3B&ss=%EB%AA%85%EB%8F%99%2C+%EC%84%9C%EC%9A%B8%2C+%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD&is_ski_area=&checkin_year=2020&checkin_month=7&checkin_monthday=23&checkout_year=2020&checkout_month=7&checkout_monthday=24&group_adults=2&group_children=0&no_rooms=1&map=1&b_h4u_keep_filters=&from_sf=1&ss_raw=%EB%AA%85%EB%8F%99&ac_position=0&ac_langcode=ko&ac_click_type=b&dest_id=2000&dest_type=district&place_id_lat=37.5607331089608&place_id_lon=126.985566718492&search_pageview_id=13161f61126b001a&search_selected=true&search_pageview_id=13161f61126b001a&ac_suggestion_list_length=5&ac_suggestion_theme_list_length=0#map_closed'
content = requests.get(url).content
soup = BeautifulSoup(content, 'html.parser')
names = soup.find_all(attrs={'class':'sr-hotel__name'})
rates = soup.find_all(attrs={'class':'bui-review-score__badge'})
containers = []
for i in range(len(rates)):
container = []
container.append(names[i].text[1:-1])
container.append(rates[i].text)
containers.append(container)
df = pd.DataFrame(data = containers, columns = ['name','rate'])
df
'Data Handling > Data Collecting' 카테고리의 다른 글
selenium - 지하철역 인근 점포 수(카페, 호프집, 제과점 등) 크롤링 (0) | 2020.11.03 |
---|---|
selenium - 부킹닷컴 객실 가격 크롤링 (5) | 2020.06.03 |
pandas.read_html() - 네이버 금융 두바이유 시세 크롤링 (0) | 2020.06.03 |
공공데이터포털 API - 대한민국 국경일 및 공휴일 (0) | 2020.06.02 |
API의 필요성 (0) | 2020.06.02 |