目前代碼已經做了更新處理,參見:
http://www.mapboxx.cn/article/poi-pology/
下面的可以不用看啦。。。
之前寫了一篇在城市範圍内根據關鍵字爬取POI資料的部落格,由于一個城市的POI資料量太大,高德地圖接口容易傳回錯誤資料,是以有個比較好的辦法就是借助高德地圖POI搜尋中根據多邊形範圍或矩形範圍搜尋POI資料,具體分為兩個步驟:其一是将城市分為多個小矩形(得到左上和右下兩個頂點的坐标即可);二是根據得到的矩形坐标調用高德地圖WEB API得到資料解析即可。這篇文章主要是記錄根據矩形範圍搜尋POI的流程,至于如何切分城市為矩形,我也還沒弄過,可以自行百度搜尋解決。
先看下爬取到的資料吧:
高德矩形搜尋的API文檔參見這裡:https://lbs.amap.com/api/webservice/guide/api/search#polygon。這裡給出一個具體的示例:
http://restapi.amap.com/v3/place/polygon?polygon=116.80708,31.449926,117.510206,32.247823&key=c5304f29d1a11f14c4fb29854a831ef0&extensions=all&offset=25&page=1&keywords=%E5%A4%A7%E5%AD%A6
參數說明:
polygon:多邊形邊界範圍(或者是矩形左上和右下兩個頂點坐标)
key : 高德地圖web api申請的密鑰key
extensions :此項預設傳回基本位址資訊;取值為all傳回位址資訊、附近POI、道路以及道路交叉口資訊。
offset :分頁的頁大小
page:請求的頁碼
其餘的具體參數介紹詳見文檔說明。
可以在浏覽器看到示例URL傳回的資料。剩餘的就是循環擷取資料,然後解析入庫的事情了,挺簡單的。這裡就直接貼上代碼了:
from urllib import request
import json
import xlwt
import transCoordinateSystem as transCoordinateSystem
# TODO
amap_web_key = '申請的密鑰' # 高德地圖官網申請的Web API KEY
filename = r'C:\\Users\\hgvgh\\Desktop\\hehe.xls' # 爬取到的資料寫入的EXCEL路徑
# 多邊形邊界集合:
'''
規則:經度和緯度用","分割,經度在前,緯度在後,坐标對用"|"分割。
多邊形為矩形時,可傳入左上右下兩頂點坐标對;其他情況下首尾坐标對需相同。
'''
polygon_list = ['104.01991721224772,30.675517485068525|104.04335935135217,30.69685368121003|104.10490633670742,30.681154431514038|104.10713973787826,30.642336396516658|104.05432192815479,30.623029707583|104.02008888045066,30.64717739010567|104.01991721224772,30.675517485068525']
# POI分類集合, 多個類型用豎線 | 分割;
type_list = '140000' #|060402|060403|060404|060405|060406|060407|060408|060409|060411|060413|060414|060415|060100|060101|060102|060103'
# 輸出坐标系:0,預設高德坐标系,1,百度坐标系,2,WGS84坐标系
output_coordinate = 2
poi_search_url = "http://restapi.amap.com/v3/place/polygon" # URL
offset = 25 # 分頁請求資料時的單頁大小
# 根據矩形坐标擷取poi資料
def getpois(polygon, type_list):
i = 1
current_polygon_poi_list = []
while True: # 使用while循環不斷分頁擷取資料
result = getpoi_page(polygon, i, type_list)
result = json.loads(result) # 将字元串轉換為json
# print('第', str(i),'頁,結果',result)
if result['status'] is not '1': # 接口傳回的狀态不是1代表異常
print('======爬取錯誤,傳回資料:' + result)
break
pois = result['pois']
if len(pois) < offset: # 傳回的資料不足分頁頁大小,代表資料爬取完
current_polygon_poi_list.extend(pois)
break
current_polygon_poi_list.extend(pois)
i += 1
print('===========目前polygon:', polygon, ',爬取到的資料數量:', str(len(current_polygon_poi_list)))
return current_polygon_poi_list
# 單頁擷取pois
'''
http://restapi.amap.com/v3/place/polygon?polygon=116.80708,31.449926,117.510206,32.247823&key=c5304f29d1a11f14c4fb29854a831ef0&extensions=all&offset=5&page=1
'''
def getpoi_page(polygon, page, type_list):
print(polygon)
req_url = poi_search_url + "?key=" + amap_web_key + '&extensions=all&polygon=' + polygon + '&offset=' + str(
offset) + '&types=' + type_list + '&page=' + str(page) + '&output=json'
data = ''
with request.urlopen(req_url) as f:
data = f.read()
data = data.decode('utf-8')
print(data)
return data
# 資料寫入excel
def write_to_excel(poilist, filename):
# 一個Workbook對象,這就相當于建立了一個Excel檔案
book = xlwt.Workbook(encoding='utf-8', style_compression=0)
sheet = book.add_sheet('0', cell_overwrite_ok=True)
# 第一行(列标題)
sheet.write(0, 0, 'id')
sheet.write(0, 1, 'name')
sheet.write(0, 2, 'lon')
sheet.write(0, 3, 'lat')
sheet.write(0, 4, 'address')
sheet.write(0, 5, 'pname')
sheet.write(0, 6, 'cityname')
sheet.write(0, 7, 'adname')
sheet.write(0, 8, 'type')
for i in range(len(poilist)):
sheet.write(i + 1, 0, poilist[i]['id'])
sheet.write(i + 1, 1, poilist[i]['name'])
lon = float(str(poilist[i]['location']).split(",")[0])
lat = float(str(poilist[i]['location']).split(",")[1])
if output_coordinate == 1:
coordinates = transCoordinateSystem.gcj02_to_bd09(lon, lat)
lon, lat = coordinates[0], coordinates[1]
if output_coordinate == 2:
coordinates = transCoordinateSystem.gcj02_to_wgs84(lon, lat)
lon, lat = coordinates[0], coordinates[1]
sheet.write(i + 1, 2, lon)
sheet.write(i + 1, 3, lat)
sheet.write(i + 1, 4, poilist[i].get('address'))
sheet.write(i + 1, 5, poilist[i].get('pname'))
sheet.write(i + 1, 6, poilist[i].get('cityname'))
sheet.write(i + 1, 7, poilist[i].get('adname'))
sheet.write(i + 1, 8, poilist[i]['type'])
book.save(filename)
'''
#xls檔案轉換為CSV檔案:
data_xls = pd.read_excel('1.xlsx', index_col=0)
data_xls.to_csv('1.csv', encoding='utf-8')
'''
print(output_coordinate == 2)
all_poi_list = [] # 爬取到的所有資料
for polgon in polygon_list:
polygon_poi_list = getpois(polgon, type_list)
all_poi_list.extend(polygon_poi_list)
print('爬取完成,總的數量', len(all_poi_list))
write_to_excel(all_poi_list, filename)
print('寫入成功')
自己運作的話需要修改的地方都在代碼上方位置,具體的說明在代碼中已有注釋。
有問題可以加入地圖資料爬取交流群:626697156