- 데이터 출처: http://m.wikitree.co.kr/main/news_view.php?id=217101
- 데이터 수집: 위 기사에서
crawl.py
를 이용해 맛집 목록 수집 후 네이버 지도 API를 이용해서 좌표 정보 수집 - Author: Lucy Park
- License: Apache v2
Last active
June 9, 2020 06:09
-
-
Save e9t/ba9edd99793a5c91eaab to your computer and use it in GitHub Desktop.
식신로드 만점 식단 20선
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/python3 | |
# -*- coding: utf-8 -*- | |
from lxml import html | |
import requests | |
APIKEY = '' # 이 곳에 네이버 API 키를 입력 (http://developer.naver.com/wiki/pages/OpenAPI) | |
MAPAPI = 'http://openapi.map.naver.com/api/geocode.php?key=%s&encoding=utf-8&coord=LatLng&query=%s' | |
def get_latlon(query): | |
root = html.parse(MAPAPI % (APIKEY, query)) | |
lon, lat = root.xpath('//point/x/text()')[0], root.xpath('//point/y/text()')[0] | |
return (lat, lon) | |
def prep(item): | |
n, name = item[0].split(' ', 1) | |
lat, lon = get_latlon(item[3]) | |
return { | |
'num': n, 'name': name, | |
'lat': lat, 'lon': lon, | |
'description': item[1], | |
'phone': item[2], | |
'addr': item[3] | |
} | |
# get data from article | |
r = requests.get('http://m.wikitree.co.kr/main/news_view.php?id=217101') | |
root = html.document_fromstring(r.text) | |
string = '\n'.join(root.xpath('//div[@id="ct_size"]/div//text()')) | |
items = [] | |
for i in range(1, 21): | |
tmp = string.split('%s.' % i, 1) | |
string = tmp[1] | |
items.append([j.strip() for j in tmp[0].split('\n') if j and j!='\xa0']) | |
data = [prep(i[:4]) for i in items[1:]] | |
# save data to file | |
with open('places.csv', 'w') as f: | |
f.write('name,lat,lon\n') | |
for d in data: | |
f.write('%(name)s,%(lat)s,%(lon)s\n' % d) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<style> | |
svg circle { | |
fill: orange; | |
opacity: .5; | |
stroke: white; | |
} | |
svg circle:hover { | |
fill: red; | |
stroke: #333; | |
} | |
svg text { | |
pointer-events: none; | |
} | |
svg .municipality { | |
fill: #efefef; | |
stroke: #fff; | |
} | |
svg .municipality-label { | |
fill: #bbb; | |
font-size: 12px; | |
font-weight: 300; | |
text-anchor: middle; | |
} | |
svg #map text { | |
color: #333; | |
font-size: 10px; | |
text-anchor: middle; | |
} | |
svg #places text { | |
color: #777; | |
font: 10px sans-serif; | |
text-anchor: start; | |
} | |
#title { | |
font-family: sans-serif; | |
} | |
#title p { | |
font-size: 10pt; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="chart"></div> | |
<div id="title"> | |
<h2>식신로드 서울지역 만점식단 20선</h2> | |
<p>식신로드에서 만점을 받은 음식점을 D3.js, TopoJSON을 이용해 지도를 그렸습니다. | |
지도 만드는 법은 <a href="http://www.lucypark.kr/blog/2015/06/24/seoul-matzip-mapping/">D3를 이용한 서울시내 맛집 시각화 (Feat. 식신로드)</a>를 참고해주세요. | |
<p> | |
<a href="http://www.wikitree.co.kr/main/news_view.php?id=217101">Data</a> by Wikitree</a> | |
and <a href="https://gist.github.com/e9t/ba9edd99793a5c91eaab">code</a> | |
by <a href="http://lucypark.kr">Lucy Park</a>. | |
<br> | |
<a href="http://opensource.org/licenses/Apache-2.0">Licensed with Apache 2.0</a> | |
</p> | |
</div> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script src="http://d3js.org/topojson.v1.min.js"></script> | |
<script> | |
var width = 800, | |
height = 600; | |
var svg = d3.select("#chart").append("svg") | |
.attr("width", width) | |
.attr("height", height); | |
var map = svg.append("g").attr("id", "map"), | |
places = svg.append("g").attr("id", "places"); | |
var projection = d3.geo.mercator() | |
.center([126.9895, 37.5651]) | |
.scale(100000) | |
.translate([width/2, height/2]); | |
var path = d3.geo.path().projection(projection); | |
d3.json("seoul_municipalities_topo_simple.json", function(error, data) { | |
var features = topojson.feature(data, data.objects.seoul_municipalities_geo).features; | |
map.selectAll('path') | |
.data(features) | |
.enter().append('path') | |
.attr('class', function(d) { console.log(); return 'municipality c' + d.properties.code }) | |
.attr('d', path); | |
map.selectAll('text') | |
.data(features) | |
.enter().append("text") | |
.attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; }) | |
.attr("dy", ".35em") | |
.attr("class", "municipality-label") | |
.text(function(d) { return d.properties.name; }) | |
}); | |
d3.csv("places.csv", function(data) { | |
places.selectAll("circle") | |
.data(data) | |
.enter().append("circle") | |
.attr("cx", function(d) { return projection([d.lon, d.lat])[0]; }) | |
.attr("cy", function(d) { return projection([d.lon, d.lat])[1]; }) | |
.attr("r", 10); | |
places.selectAll("text") | |
.data(data) | |
.enter().append("text") | |
.attr("x", function(d) { return projection([d.lon, d.lat])[0]; }) | |
.attr("y", function(d) { return projection([d.lon, d.lat])[1] + 8; }) | |
.text(function(d) { return d.name }); | |
}); | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name | lat | lon | |
---|---|---|---|
다성일식 | 37.5569016 | 126.9329799 | |
봉산집 | 37.5344248 | 126.9750082 | |
창고43 | 37.5189582 | 126.9307458 | |
돕감자탕 | 37.5414873 | 127.0692836 | |
대보명가 | 37.6456867 | 127.0071573 | |
해뜨는집 | 37.5900691 | 127.0084044 | |
아이 해브어 드림 | 37.4986175 | 127.0278876 | |
아현동 간장게장 | 37.5546000 | 126.9561000 | |
왕소금구이 | 37.5204088 | 127.0361107 | |
라틀리에 모니크 | 37.5261816 | 127.0448766 | |
비스트로 딩고 | 37.5210777 | 127.0198099 | |
줄리에뜨 | 37.4947204 | 127.0009384 | |
충주집 | 37.5862178 | 127.0345490 | |
영화루 | 37.5801384 | 126.9690401 | |
일품헌 | 37.4845029 | 127.0391935 | |
립스테이크 | 37.5955682 | 126.9640695 | |
오가와 | 37.5720260 | 126.9743351 | |
까사디노아 | 37.5620845 | 126.9235561 | |
충무로 주꾸미 불고기 | 37.5617693 | 126.9921966 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
안녕하세요.
올려주신 코드보고 정말 많은 공부 되었습니다.
특히 '스시야 기행' 코드를 보고 서울시에서 세종시로 바꾸어 적용하는데 큰 도움이 되었습니다.
하지만 진행하다가 한가지 문제에 도달했는데요 ㅠ Github나 bl.ocks를 참고해도 제 내공이 부족하여 답을 얻어내지 못했습니다. 혹시 루시님이 시간되실때 도와주신다면 정말 감사하겠습니다.
우선 제가 구축한 페이지는 아래와 같습니다.
http://cshin.me/sejongmat_b...
여기서 Force Layout된 "text"에 URL을 넣어 연결하고 싶은데... 마음같이 안되네요 ㅠ
'Circle'이 겹치는 부분의 경우 링크를 타고 가는게 어려우니까요... ㅠ
혹시라도 도와주시거나 조금의 힌트라도 주신다면 정말 큰 도움이 될 것 같습니다.
감사합니다.