好,現在進入進階篇教程。
1.獲取昆明市的bounds值
看到下面這個東西了吧?在文本框里寫入昆明市,或者其他的行政區划地名,北京市、朝陽區、大河溝子村什么的。
這也是通過調用百度地圖開放平台API實現的。
實現起來很簡單,把下面這段代碼復制到一個txt文件中,然后把txt文件的拓展名改成html,用瀏覽器打開,就可以查詢行政區划的范圍了。
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> <style type="text/css"> body, html,#allmap {width: 100%;height: 100%;overflow: hidden;margin:0;font-family:"微軟雅黑";} #panel{ position:absolute; left:5px; top:5px; } #result{ background: #fff; padding:5px; } </style> <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=1XjLLEhZhQNUzd93EjU5nOGQ"></script> <title>添加行政區划</title> </head> <body> <div id="allmap"></div> <div id="panel"> <div> <input type="text" id="keyword" value="昆明市"/> <input type="button" value="查看范圍" id="commitBtn"/> 邊界經緯度坐標 <textarea id="pathStr"></textarea> 邊界墨卡托坐標 <textarea id="pathMc"></textarea> </div> <div id="result"> </div> </div> </body> </html> <script type="text/javascript"> // 百度地圖API功能 var map = new BMap.Map("allmap"); map.centerAndZoom(new BMap.Point(116.403765, 39.914850), 5); map.enableScrollWheelZoom(); var mercatorProjection = map.getMapType().getProjection(); $("#commitBtn").bind('click', function(){ getBoundary($("#keyword").val()); }); function getBoundary(city){ var bdary = new BMap.Boundary(); bdary.get(city, function(rs){ //獲取行政區域 map.clearOverlays(); //清除地圖覆蓋物 var count = rs.boundaries.length; //行政區域的點有多少個 if (count === 0) { alert('未能獲取當前輸入行政區域'); return ; } var pointArray = []; for (var i = 0; i < count; i++) { var ply = new BMap.Polygon(rs.boundaries[i], {strokeWeight: 2, strokeColor: "#ff0000"}); //建立多邊形覆蓋物 map.addOverlay(ply); //添加覆蓋物 pointArray = pointArray.concat(ply.getPath()); } var pathStr = ""; var pathMc = ""; for (var i = 0; i < pointArray.length; i++) { var mc = mercatorProjection.lngLatToPoint(pointArray[i]); pathStr += pointArray[i].lng + "," + pointArray[i].lat + ";"; pathMc += mc.x + "," + mc.y + ";"; } $('#pathStr').html(pathStr); $('#pathMc').html(pathMc); var ply = new BMap.Polygon(pointArray , {strokeWeight: 2, strokeColor: "#ff0000"}); //建立多邊形覆蓋物 var bounds = ply.getBounds(); var ne = bounds.getNorthEast(); var sw = bounds.getSouthWest(); var neMc = mercatorProjection.lngLatToPoint(ne); var swMc = mercatorProjection.lngLatToPoint(sw); var str = "經緯度:左下角,右上角:" + sw.lng + "," + sw.lat + ";" + ne.lng + "," + ne.lat + "<br/>墨卡托坐標:左下角,右上角:" + swMc.x + "," + swMc.y + ";" + neMc.x + "," + neMc.y; $('#result').html(str); console.log(bounds); map.setViewport(pointArray); //調整視野 }); } //getBoundary('北京'); </script>
HTML是一個很神奇的格式,代碼可以在文本文檔里寫,不過應該很少有人用文本文檔寫代碼吧。
這段代碼可以直接拿來用,也是我從網上找的,就不分析了。
2.更合理的對查詢范圍進行切分。
這是一個很常見的問題,我們要采集昆明市的中學興趣點,然后就把矩形等分了六份,遍歷一遍(其實要不遺漏的獲取興趣點,只切六個絕對不夠用)。
這種切分方式其實並不完美,分析一下,中心城區興趣點肯定分布更密集,而郊區會稀疏一些,而且一個城市的邊界不可能是矩形的,我們用一個大矩形切分,會爬取到一些其他城市的興趣點。
有相關從業經驗的人應該能想到,如果有這個城市的分幅格網,遍歷分幅格網來爬取興趣點會更好一些,當然分幅格網我們也可以自己生成,根據預估的興趣點疏密程度,中心城區格網加密一些,外圍合並一些。
arcgis有一個工具fishnet(創建漁網),可以生成格網。
四至坐標可以在字段計算器里計算,選用python語言
minX=!shape.extent.xmin! maxX=!shape.extent.xmax! minY=!shape.extent.ymin! maxY=!shape.extent.ymax!
之前寫過一篇畫分幅格網的教程:http://blog.sina.com.cn/s/blog_4c6ee7230102v590.html
把arcgis屬性表導出,可以用excel打開。
用這個坐標列表去生成url列表,主要就是open和write語句的運用,其實都可以直接在excel里用函數去生成url列表。
python逐行讀入:
f=open(路徑,’a’)
f.readlines()
3.python中文亂碼問題解決
其實這是一個很棘手的問題。對於初學者來說,遇到亂碼問題,如何解決是一個幸運度的問題。有可能運氣不好,就解決不了了,有可能運氣夠好,根本遇不上。
在亂碼問題上,python2.7要多於python3
我精心挑選了幾個我覺得講得比較好的文章,大家可以參考一下,網上相關的文章太多了,容易懵。
這篇中文亂碼的解決方式:
http://www.jb51.net/article/42707.htm
用sys.getfilesystemencoding()獲取文件系統的編碼方式。
import sys type = sys.getfilesystemencoding() print mystr.decode('utf-8').encode(type)
這篇文章寫得比較細:
http://blog.csdn.net/ggggiqnypgjg/article/details/53271541
我的經驗是,如果遇到亂碼,怎么都調試不成功,那么可以換一個編譯環境,從python2.7換到python3,或者用別的函數,例如不用urllib2,用beautiful soul,或者requests等,有可能莫名其妙亂碼的問題就不出現了呢!
4.並發量限制與延時功能
import time time.sleep(10)
這兩行代碼的意思是,延時10秒中,它解決的是一分鍾內並發量限制的問題,如果我們沒有做認證,那么一分鍾能訪問API服務的次數不超過幾次,超過了就會提示訪問超過並發量,就爬不到數據了。
解決這個問題的方法就是用time.sleep(10),每次循環都先休眠10秒,就不會訪問超過並發量了。
我覺得10秒夠用了,所以就設定了10秒,不過如果認證過的開發者,應該不會遇到並發量限制的問題。
這段代碼示例一下:
import time time.sleep(10) print time.time()
休眠十秒,打印當前時間,結果是一個浮點秒數。
5.把代碼移植到python3中。
python2.7和python3略微有些差異,python3版本有一個好處就是中文亂碼的情況沒那么多,而且很多功能和第三方庫都被整合了。
下面這段代碼是python3中的,可以看出比較於python2.7版本,進行了幾處改變,requests、webbrowser、列表的引用等。
#-*-coding:UTF-8-*- import json import sys import requests #導入requests庫,這是一個第三方庫,把網頁上的內容爬下來用的 ty=sys.getfilesystemencoding() #這個可以獲取文件系統的編碼形式 import time lat_1=24.390894 lon_1=102.174112 lat_2=26.548645 lon_2=103.678942 #坐標范圍 las=1 #給las一個值1 ak='9s5GSYZsWbMaFU8Ps2V2VWvDlDlqGaaO' push=r'D:\python\zwzwlast.txt' #我們把變量都放在前面,后面就不涉及到變量了,如果要爬取別的POI,修改這幾個變量就可以了,不用改代碼了。 print (time.time()) #相較於python2.7,,python3print 需要加括號。 print ('開始') urls=[] 聲明一個數組列表 lat_count=int((lat_2-lat_1)/las+1) lon_count=int((lon_2-lon_1)/las+1) for lat_c in range(0,lat_count): lat_b1=lat_1+las*lat_c for lon_c in range(0,lon_count): lon_b1=lon_1+las*lon_c for i in range(0,20): page_num=str(i) url='http://api.map.baidu.com/place/v2/search?query=中學& bounds='+str(lat_b1)+','+str(lon_b1)+','+str(lat_b1+las)+','+str(lon_b1+las)+'&page_size=20&page_num='+str(page_num)+'&output=json&ak='+ak urls.append(url) #urls.append(url)的意思是,將url添加入urls這個列表中。 f=open(r'D:\python\kunmingxuexiao.txt','a',encoding='utf-8') print ('url列表讀取完成') for url in urls: time.sleep(10) #為了防止並發量報警,設置了一個10秒的休眠。 html=requests.get(url)#獲取網頁信息 data=html.json()#獲取網頁信息的json格式數據 for item in data['results']: jname=item['name'] jlat=item['location']['lat'] jlon=item['location']['lng'] jadd=item['address'] j_str=jname+','+str(jlat)+','+str(jlon)+','+jadd+'\n' f.write(j_str) print (time.time()) f.close() print ('完成')
6.代碼簡化問題。
可以通過分析json數據提煉一下簡化方式。
網頁打開之后,看一下。
{
“status”:0,
“message”:”ok”,
“total”:400,
“results”:[
{
“name”:”北大附中雲南實驗學校”,
“location”:{
“lat”:25.009573,
“lng”:102.723208
},
“address”:”昆明市日新中路北大附中雲南實驗學校”,
“street_id”:”beabdbf4ac3394997069d3c7”,
“detail”:1,
“uid”:”beabdbf4ac3394997069d3c7”
主要看results上面那三行,其中total,是這個矩形范圍內有多少個興趣點,有400個,說明我矩形畫大了,應該再細分一下,這個數應該小於400,因為我們之前已經說過20頁網址最多爬400個poi,total是400,說明實際的poi數量是大於400個的。
提取某一坐標范圍中第一頁數據的時候,我們可以先獲取total值,這樣就可以計算出page_num的值了,如果total是100,那么只循環到第五頁,page_num=4的時候就可以了。
這是代碼的一個簡化方式。
當然應該還有很多,有待我們發覺。
7.過程參考資料匯總
因為使用python的人很多,所以網上的資料也很多,不過要找到比較合適的,也沒那么容易。但是說實話,走彎路、排除錯誤答案也是學習收獲的一個過程,實踐過錯的,才知道什么是對的嘛!
最有用的參考資料,應該是還算是官網。
https://www.python.org/
學好英語很必要。
這個網址,講的是requests的用法。
http://docs.python-requests.org/zh_CN/latest/user/quickstart.html
當然,買本書應該也不錯。
然后腳本之家和CSDN都有很好的教程,不過也不是所有教程都是對的,多看多試多思考多練習,就會有多獲得。
最后會再來一篇python安裝和第三方庫安裝篇,這個python的零基礎教程就先告一段落吧!
轉自----------------http://blog.csdn.net/sinat_41310868/article/details/78746251