Dev/python

python 정적 크롤링 subway매장 정보 csv로 저장하기

uragil 2022. 11. 15. 10:06
반응형

정적 크롤링을 배우고 처음 해봤던 연습

서브웨이 홈페이지 들어가서 보면 편한데 왜 이렇게 저장하는지 잘 이해는 안 갔지만

일단 해본다.

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)로 한 페이지만 크롤링했음

반응형