반응형
정적 크롤링을 배우고 처음 해봤던 연습
서브웨이 홈페이지 들어가서 보면 편한데 왜 이렇게 저장하는지 잘 이해는 안 갔지만
일단 해본다.
1. 사용하는 package
BeautifulSoup
HTML에서 필요한 데이터를 추출하고 가공하는 데 사용
urllib.request
Url과 연결 소통하기 위해 사용
pandas
자료를 엑셀형태로 변환
2. 홈페이지 확인
어떤 정보를 가져올지 정했기에 subway에 들어가 매장 정보가 나와 있는 메뉴를 찾아 들어간다.
https://www.subway.co.kr/storeSearch?page=51&rgn1Nm=&rgn2Nm=#storeList
매장 정보는 53페이지 까지 나와있고 각 페이지당 10개소의 정보가 들어 있는 걸 확인할 수 있고
그리고 url을 확인해 보면 각 page=51 이 부분의 숫자가 각 페이지에 따라 변하는 것을 확인 할 수 있다.
각 페이지 url을 들어갈 수 있도록 for문으로 page 부분을 돌려준다.
51 부분에 % d를 주어 1~53까지 순차적으로 방문하게 된다.
def Subway_store(result):
for page in range(1,54):
# print(Subway_url)
각 방문한 페이지의 html을 저장하고
html = urllib.request.urlopen(Subway_url)
# print(html)
beautifulsoup으로 파씽하여 soupSubway에 저장
soupSubway = bs(html,"html.parser") # 파씽
f12를 눌러 개발자 모드로 소스를 보면 tbody 안에 각 tr하나에 매장 정보들이 담겨 있는 것을 확인할 수 있다.
아래의 테이블 구조
<tbody>
<tr>
<td></td>
<td></td>
<tr>

파씽된 soupSubway에서 .find 모듈로 tbody 부분만 떼어서 다시 tag_tbody에 저장한다.
tag_tbody = soupSubway.find("tbody")
print(tag_tbody)
tag_tbody를 출력하면 tbody 부분만 깔끔할게 짤려 출력 되는 것이 확인 가능하다.
<tbody>
<tr>
<td><div class="num">521</div></td>
<td><a href="/storeDetail?franchiseNo=557">파주야당역</a></td>
<td>
<div class="title"><a href="/storeDetail?franchiseNo=557">경기도 파주시 경의로 1080, 102호 </a></div>
</td>
<td>
<div class="service">
<span class="on">아침메뉴</span><!-- 해당서비스 on클래스 추가 -->
<span>24시간</span><!-- 해당서비스 on클래스 추가 -->
<span class="on" style="display:none;">딜리버리</span><!-- 해당서비스 on클래스 추가 -->
<!--<span th:class="${shop.pkYn == 'Y'} ? 'on':''">주차가능</span>--><!-- 해당서비스 on클래스 추가 -->
</div>
</td>
<td><div class="coming">Coming Soon</div></td>
<td><a href="/storeDetail?franchiseNo=557" target="_blank"><img alt="자세히보기" src="/images/common/icon_detail_view.png"/></a></td><!-- 20180307 -->
</tr>
<tr>
<td><div class="num">520</div></td>
<td><a href="/storeDetail?franchiseNo=556">전주혁신</a></td>
<td>
<div class="title"><a href="/storeDetail?franchiseNo=556">전라북도 전주시 덕진구 안전로148 </a></div>
</td>
<td>
<div class="service">
<span class="on">아침메뉴</span><!-- 해당서비스 on클래스 추가 -->
<span>24시간</span><!-- 해당서비스 on클래스 추가 -->
<span class="on" style="display:none;">딜리버리</span><!-- 해당서비스 on클래스 추가 -->
<!--<span th:class="${shop.pkYn == 'Y'} ? 'on':''">주차가능</span>--><!-- 해당서비스 on클래스 추가 -->
</div>
</td>
다시 tbody안에서 각 tr을 방문하며 필요한 정보를 찾아야 한다.
tag_tbody.find_all 모듈로 tr이 들어간 모든 부분을 찾아 store 로 for문을 돌린다.
for store in tag_tbody.find_all("tr"):
각 tr에서 find_all로 td 부분을 찾아주면 필요한 정보까지 도착한 것
store_td = store.find_all("td")
각 td는 홈페이지에서 보여지는 것과 같이 순서대로 'No/ 매장명/ 주소/ 주요정보/ 전화번호'로 되어있고
각 정보를 string 혹은 text로 저장하여 result에 append 해준다.
store_num = store_td[0].string
store_name = store_td[1].string
store_address = store_td[2].text
store_phone = store_td[4].string
result.append([store_num]+[store_name]+[store_address]+[store_phone])
return
def main():
result = [ ] #result 배열 생성
Subway_store(result) #[CODE 1] 호출
판다스로 result에 담긴 정보를 dataframe형으로 바꿔 준다. columns명을 정해주고 Subway_tbl 에 저장
Subway_tbl = pd.DataFrame(result, columns=('매장번호', '매장명', '주소','전화번호'))
to_csv로 csv형으로 저장 (저장할 경로및 파일명, 인코딩utf-8이 한글이 안깨지니까, mode와 index는 옵션이 기억 안난다)
Subway_tbl.to_csv('/content/drive/MyDrive/Colab Notebooks/Subway.csv', encoding='utf8', mode='w', index=True)
del result[:]
if __name__ == '__main__':
main()
전체 코드
from bs4 import BeautifulSoup as bs # 크룰링
import urllib.request # URL 연결
import pandas as pd # 엑셀변환
import datetime # 날짜 사용
#[CODE 1]
def Subway_store(result):
for page in range(1,51):
Subway_url = 'https://www.Subway.co.kr/storeSearch?page=%d&rgn1Nm=&rgn2Nm=#storeList' %page
# print(Subway_url)
html = urllib.request.urlopen(Subway_url)
# print(html)
soupSubway = bs(html,"html.parser") # 파씽
# print(soupSubway)
tag_tbody = soupSubway.find("tbody")
print(tag_tbody)
for store in tag_tbody.find_all("tr"):
# if len(store) <= 9: # 마지막 페이지 3이하 개선...
# break
store_td = store.find_all("td")
store_num = store_td[0].string
store_name = store_td[1].string
store_address = store_td[2].text
store_phone = store_td[4].string
result.append([store_num]+[store_name]+[store_address]+[store_phone])
return
#[CODE 0]
def main():
result = []
print('Subway store crawling >>>>>>>>>>>>>>>>>>>>>>>>>>')
Subway_store(result) #[CODE 1] 호출
Subway_tbl = pd.DataFrame(result, columns=('매장번호', '매장명', '주소','전화번호'))
Subway_tbl.to_csv('/content/drive/MyDrive/Colab Notebooks/Subway.csv', encoding='utf8', mode='w', index=True) #cp949
del result[:]
if __name__ == '__main__':
main()
저장된 Subway.csv.
페이지 다하기에는 너무 많아서 for page in rage(1, 2)로 한 페이지만 크롤링했음

반응형