API 설계
1. scraping.py
2. 메인페이지 (index.html)
- 지도에 마커로 맛집 보여주기
- 마커를 클릭하면 목록에서 해당 맛집 찾아주기
- 목록에서 맛집클릭하면 마커로 찾아주기
- 각 맛집 별 마커, 정보창, 카드 만들고 서로 연결하기
3. 스크래핑 해온 정보를 나타내기 (prac_map.html)
프로젝트 setting
뼈대 준비
main, matjip(GET)
# index - get_matjips, make_card, make_marker, add_info, click2center
# prac_map - map, marker, infowindow
- scraping.py
- static - 배너, favicon 이미지
스크래핑 (scraping.py)
1. 맛집 정보 스크래핑
- 셀레니움으로 스크래핑하기
- 각 식당에 해당하는 카드선택하고 식당 이름, 주소, 카테고리, 출연 프로그램과 회차 정보를 출력하기
driver.get(url)
time.sleep(5)
req = driver.page_source
driver.quit()
soup = BeautifulSoup(req, 'html.parser')
places = soup.select("ul.restaurant_list > div > div > li > div > a")
print(len(places))
for place in places:
title = place.select_one("strong.box_module_title").text
address = place.select_one("div.box_module_cont > div > div > div.mil_inner_spot > span.il_text").text
category = place.select_one("div.box_module_cont > div > div > div.mil_inner_kind > span.il_text").text
show, episode = place.select_one("div.box_module_cont > div > div > div.mil_inner_tv > span.il_text").text.rsplit(" ", 1)
print(title, address, category, show, episode)
2. 맛집 정보를 좌표로 변환
- 요청 파라미터, geocode (status,addresses[].x 나와있음)
- 네이버에서 제공하는 geocoing을 통해 맛집의 경도와 위도 표시하기
- 주소에 오류가 있어 결과를 하나도 받지 못하는 경우가 있으므로 결과가 있을 때만 값을 출력
headers = {
"X-NCP-APIGW-API-KEY-ID": "[내 클라이언트 아이디]",
"X-NCP-APIGW-API-KEY": "[내 클라이언트 시크릿 키]"
}
r = requests.get(f"https://naveropenapi.apigw.ntruss.com/map-geocode/v2/geocode?query={address}", headers=headers)
response = r.json()
if response["status"] == "OK":
if len(response["addresses"])>0:
x = float(response["addresses"][0]["x"])
y = float(response["addresses"][0]["y"])
print(title, address, category, show, episode, x, y)
else:
print(title, "좌표를 찾지 못했습니다")
3. 맛집 정보 DB에 저장하기
- 더보기 버튼을 10번 눌러서 정보 스크래핑
- DB에 저장하기 (doc = {} \ db.matjips.insert_one(doc))
btn_more = driver.find_element_by_css_selector("#foodstar-front-location-curation-more-self > div > button")
btn_more.click()
time.sleep(5)
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
doc = {'title' : title, ...}
db.matjips.insert_one(doc)
메인페이지(index.html)
1. 전체 모습 만들기
- 배너와 지도, 카드 만들기(지도는 prac_map.html 에서)
- DB에서 맛집 정보 찾아오기(get_matjips())
- 카드 만들기 (make_card())
@app.route('/matjip', methods=["GET"])
def get_matjip():
matjip_list = list(db.matjips.find({}, {'_id': False}))
return jsonify({'result': 'success', 'matjip_list': matjip_list})
<head>
<script type="text/javascript"
src="https://openapi.map.naver.com/openapi/v3/maps.js?ncpClientId={발급ID}&submodules=geocoder"></script>
<script>
let y_cen = 37.4981125
let x_cen = 127.0379399
let map;
let markers = [];
let infowindows = [];
$(document).ready(function () {
map = new naver.maps.Map('map', {
center: new naver.maps.LatLng(y_cen, x_cen),
zoom: 12,
zoomControl: true,
zoomControlOptions: {
style: naver.maps.ZoomControlStyle.SMALL,
position: naver.maps.Position.TOP_RIGHT
}
});
get_matjips()
})
</script>
</head>
function get_matjips() {
$('#matjip-box').empty();
$.ajax({
type: "GET",
url: '/matjip',
data: {},
success: function (response) {
let matjips = response["matjip_list"]
for (let i = 0; i < matjips.length; i++) {
let matjip = matjips[i]
console.log(matjip)
make_card(i, matjip);
let marker = make_marker(matjip);
add_info(i, marker, matjip)
}
}
});
}
2. 정보 추가하기
- 마커 띄우기(make_marker(), prac_map.html에 저장되어 있음)
- 정보창 띄우기(add_info(), prac_map.html에 저장되어 있음)
function make_marker(matjip){
let marker = new naver.map.Marker({
position : new naver.maps.Lating(matjip["mapy"], matjip["mapx"]),
map : map //어느 맵에 표시될 것인가! (맨 위에 설정했던 map 불러온거임)
});
markers.push(marker)
return marker
}
function add_info(i, marker, matjip){
let html_temp = `<div class="iw-inner">
<h5>${matjip['title']}</h5>
<p>${matjip['address']}
</div>`;
let infowindow = new naver.maps.InfoWindows({
content: html_temp,
maxWidth: 200,
backgroundColor: "#fff",
borderColor: "#888",
borderWidth: 2,
anchorSize: new naver.maps.Size(15, 15),
anchorSkew: true,
anchorColor: "#fff",
pixelOffset: new naver.maps.Point(10, -10)
});
infowindows.push(infowindow)
naver.maps.Event.addListener(marker, "click", function(e) {
if(infowindow.getMap()){
infowindow.close();
}else{
infowindow.open(map,marker);
map.setCenter(infowindow.position)
$("#matjip-box").animate({
scrollTop:
$("#matjip-box").get(0).scrollTop + $(`
}, 2000);
}
});
}
3. 추가기능
- 목록에서 카드가 보이게 스크롤
- 카드 클릭했을 때 목록창에 맛집 보이기
- og 태그, favicon 삽입