본문 바로가기
내마음대로만들어보자/HTML

웹 개발 플러스 3주차(맛집 지도 만들기)

by 소농민! 2021. 4. 28.
728x90

이번 3주차 수업은 맛집 지도 만들기!

이번에는 말로만 듣던 Open Api를 사용해볼 수 있는 기회가 생겼다!! 하지만 또 새로운걸 배운다는건 

쉽지많은 않아 개발일지를 쓰면서 복습 필수!

 

※ 완성된 프로젝트 모습 

스파르타 맛집 지도 메인 화면 

 

일반적인 네이버,카카오 지도 등에서 할 수 있는 기본적인 기능들을 구성하고 있고,

위치정보, 맛집정보, 즐겨찾기 등등

 

이렇게 만들어본것처럼 Api 사용법만 알 수 있으면 다른 Api를 사용해서 보다 많은 정보들로 

웹 서비스, 앱 서비스를 만들 수 있을 것같은 좋은 생각이 드는 강의 였던것같다! 

 

이번 주차에서 가장중요한 점은 역시 " 셀레니움을 통한 웹 스크래핑" 

이전 강의에서 배운 크롤링의 단점을 보완할 수 있는 아주 좋은 녀석인것같음! 


※ 셀레니움 적용 코드 

from bs4 import BeautifulSoup

from selenium import webdriver

from time import sleep

driver = webdriver.Chrome('./chromedriver') # 드라이버를 실행합니다.

url = "<https://www.melon.com/chart/day/index.htm>"

# headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}

# data = requests.get(url, headers=headers)

 

driver.get(url) # 드라이버에 해당 url의 웹페이지를 띄웁니다.

sleep(5) # 페이지가 로딩되는 동안 5초 간 기다립니다.

 

req = driver.page_source # html 정보를 가져옵니다.

driver.quit() # 정보를 가져왔으므로 드라이버는 꺼줍니다.

 

# soup = BeautifulSoup(data.text, 'html.parser')

soup = BeautifulSoup(req, 'html.parser') # 가져온 정보를 beautifulsoup으로 파싱해줍니다.

 

songs = soup.select("#frm > div > table > tbody > tr")

print(len(songs))

 

for song in songs:

title = song.select_one("td > div > div.wrap_song_info > div.rank01 > span > a").text artist = song.select_one("td > div > div.wrap_song_info > div.rank02 > span > a").text

likes = song.select_one("td > div > button.like > span.cnt").text

 

print(title, artist, likes)

 

→ 셀레니움 기본 셋팅 코드로 알아두면 좋을것같다! 설명을 잘해주시니 이해하기 쉽다. 

 

* 셀레니움의 중요 스킬 

1. 원하지 않는 정보 지우기

likes_tag = song.select_one("td > div > button.like > span.cnt")

likes_tag.span.decompose() # span 태그 없애기

likes = likes_tag.text.strip() # 텍스트화한 후 앞뒤로 빈 칸 지우기

 

2. 검색 시 스크롤 내리기!! (네이버 이미지 검색창 예시 코드 참고)

from bs4 import BeautifulSoup

from selenium import webdriver

from time import sleep

 

driver = webdriver.Chrome('./chromedriver')

 

url = "https://search.naver.com/search.naver?where=image&sm=tab_jum&query=%EC%95%84%EC%9D%B4%EC%9C%A0"

driver.get(url)

sleep(3)

 

req = driver.page_source driver.quit()

soup = BeautifulSoup(req, 'html.parser')

images = soup.select(".tile_item._item ._image._listImage")

print(len(images))

 

for image in images:

src = image["src"]

print(src)

 

※ 1000픽셀 만큼 내리기 

driver.execute_script("window.scrollTo(0, 1000)") # 1000픽셀만큼 내리기

 

※ 맨밑까지 내리기 

sleep(1)

driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

sleep(10)

 

 

위의 내용들은 알고있으면 앞으로 스크래핑을 할때 유용하게 사용할 수 있을것같다. 

 

이제 본격적으로 네이버지도 Api 사용을 해보자!!! 

신청 및 정보에 대한 자세한 내용은 강의자료를 참고하자

 

1. 맛집 지도에 필수 스킬 

   - 확대/축소 버튼 

    let map = new naver.maps.Map('map', {

        center: new naver.maps.LatLng(37.4981125, 127.0379399),

        zoom: 10,

        zoomControl: true,

        zoomControlOptions: {

               style: naver.maps.ZoomControlStyle.SMALL,

               position: naver.maps.Position.TOP_RIGHT }

});

     - 마커 띄우기

     let marker = new naver.maps.Marker({

         position: new naver.maps.LatLng(37.4981125, 127.0379399),

         map: map

});

     - 마커 이미지 바꾸기

let marker = new naver.maps.Marker({

    position: new naver.maps.LatLng(37.4981125, 127.0379399),

    map: map,

    icon: "{{ url_for('static', filename='rtan_heart.png') }}"

});

 

   - 정보창 띄우고 닫기 

※ infowindow 만들고 열기 

  let infowindow = new naver.maps.InfoWindow({

      content: `<div style="width: 50px;height: 20px;text-align: center"><h5>안녕!</h5></div>`,

});       

      infowindow.open(map, marker);

 

※ infowindow 닫기 

infowindow.close();

 

※ 마커를 누를때마다 infowindow 여닫기 

naver.maps.Event.addListener(marker, "click", function () {

console.log(infowindow.getMap()); // 정보창이 열려있을 때는 연결된 지도를 반환하고 닫혀있을 때는 null을 반환

if (infowindow.getMap()) { infowindow.close();

} else {

     infowindow.open(map, marker);

  }

});

 

※ 맛집지도만들기 프로젝트 순서 

1. API설계 및 프로젝트 준비( Client ID 필수로 넣어야한다, API 사용을 위함) 

2. 맛집정보 스크래핑 (셀레니움 사용)

  - 셀레니움 기본 셋팅 코드는 "scraping.py참고"

  - ㉮스크래핑 하려고하는 카드 선택 → ㉯각각의 식당의 이름, 주소, 카테코리 등등 선택 

     ex) 

    places = soup.select("ul.restaurant_list > div > div > li > div > a")

    ㉯ for place in places:

          title = place.select_one("strong.box_module_title").text

사실 처음에 내가 스크래핑 하려는 정보를 찾는것도 힘들지만 개발자콘솔에서 설렉트 기능을 하면 그나마 쉽게 찾을 수 있다!

 

3. 맛집정보 좌표로 변환하기 (geocoding Api 참고)

    - Geocoding 연결하기 (클라이언드 아이디, 시크릿 키를 필수로 입력해야한다.)

    - 결과 출력하기 (scraping.py참고)

4. 맛집정보 DB에 저장하기 (여러페이지 스크래핑 하기)

    - 최대한 많은 DB를 확보하기위해 하단 "더보기" 버튼을 반복적으로 눌러서 스크래핑 하는게 포인트!!

      for i in range(10):

      try:

      btn_more = driver.find_element_by_css_selector("#foodstar-front-location-curation-more-self > div > button")       

      btn_more.click()

      time.sleep(5)

 except NoSuchElementException:

      break

5. 웹사이트 모습 만들기 (DB에서 맛집정보 가져오기. 각 맛집별 카드 만들기)

    - 웹사이트 모습을 만드는것은 디자인을 참고

    - 서버에서는 DB에 스캐래핑하여 저장된 정보들을 받아와야한다. (app.py)

    - 서버에서 받아온 정보들을 클라이언트에서는 보여줘야한다.  (index.html)

6. 정보 추가하기(마커띄우기, 정보창 infowindow 띄우기)

    - 마커띄우기 

      function make_marker(matjip) {

      let marker = new naver.maps.Marker({

      position: new naver.maps.LatLng(matjip["mapy"], matjip["mapx"]),

     map: map

    });

   markers.push(marker)

   return marker

}

 

   - 정보창 infowindow 띄우기 

infowindow 만들기

infowindow 가운데오게하기 

map.setCenter(infowindow.position)

 

7. 고급기능사용 (카드보이게 스크롤 움직이기, 제목클릭 시 정보창 띄우기, og태그, favicon)

  - 카드보이게 스크롤 움직이기

    $("#matjip-box").animate({

         scrollTop: $("#matjip-box").get(0).scrollTop + $(`#card-${i}`).position().top

}, 2000);

 

  - 제목클릭 시 정보창 띄우기

   a 태그를 클릭했을 때 새창이 뜨는게 아니라 javascript 함수를 실행하고 싶다면? → <a href="javascript:실행함수명()"> ...

 

function click2center(i) {

let marker = markers[i]

let infowindow = infowindows[i]

if (infowindow.getMap()) {

       infowindow.close();

} else {

infowindow.open(map, marker);

map.setCenter(infowindow.position)

}

}

a 태크 수정내용 

<a href="javascript:click2center(${i})" class="matjip-title">${matjip['title']}</a>

7. 즐겨찾기 기능 

  → 이부분은 숙제 해설영상 보고 복습해보자! 

 

 

온라인 강의에 관심이 있으신분들은 아래 링크로 수강하는경우 할인 가능합니다!

https://spartacodingclub.kr/?f_name=%EA%B0%95%ED%99%8D%EC%88%9C&f_uid=6044be3eea76fe086b066ce7