# 经纬度地址转换的方法集合（Python描述）

Python 2.7
IDE Pycharm 5.0.3
Geopy 1.11

## 前言

``这只是我想做的一部分，写一块太大了，单独记录``

## 目的

``获取2015年GDP TOP100城市并获取城市对应经纬度，存入txt后续操作``

## 获取GDP TOP100城市

2015中国100大城市GDP排行榜TOP100出炉！

ok，先把TOP100城市爬下来再说

## 方法1：静态爬取

``# 采用urllib2+BS4进行静态网页解析 def getCityByBS4(url):      html = urllib2.urlopen(urllib2.Request(url)).read().decode('gbk')     soup = BeautifulSoup(html,'lxml')     x = soup.find_all('p')     t=1     cityLocationList = []     cityLocationListOnlyLatLng =[]     for i in x:         if t > 5 and t<106:             city1 = i.get_text()             city1 = city1.encode('utf-8')             # 数据清洗过程             city1 = re.split('/.',city1)[1]             city1 = re.split('（',city1)[0]             if len(city1)>13:                 city2 = city1[0:6]             else:                 city2 =city1.strip()             try:                 lat_lng = getLocation_xml(city2+"市")                 city_location = "%s %s"%(city2,str(lat_lng))                 city_locationOnlyLatLng = lat_lng                 cityLocationList.append(city_location)                 cityLocationListOnlyLatLng.append(city_locationOnlyLatLng)                 #write2txt(city_location,"City&LocationBS4.txt")                 print city_location             except:                 print "something wrong about city:",city2         t +=1      return cityLocationList,cityLocationListOnlyLatLng # 返回了一个有城市和经纬度对应的列表如：上海 31.249162,121.487899 # 还返回了一个只有经纬度的列表如 ：31.249162,121.487899    #写入txt操作子函数 def write2txt(file,txtname):          f = open(txtname,'a')         f.write(file)         f.write("/n")         f.close()         # please use this with try except/finall f.close()   # 程序入口 if __name__ == '__main__':      url = 'http://www.redsh.com/a/20160126/171501.shtml'     city_locationList,cityLocationListOnlyLatLng= getCityByBS4(url)     print city_locationList     for i in city_locationList:         write2txt(i,"city&locaionByBS4.txt")     for j in cityLocationListOnlyLatLng:         write2txt(j,"LocaionOnlyByBS4.txt")``

## 方法2：动态爬取

（这里是有趣的专题），这回没用Firefox浏览器了，也就是演示作用而已，无头PhantomJS就行了，也是直接上代码

``#采用selenium+phantomjs进行动态解析 def getCityBySelenium(url):     driver = webdriver.PhantomJS(executable_path="phantomjs.exe")     driver.get(url)     cityLocationList = []     cityLocationListOnlyLatLng =[]     for i in range(6,106):         elem_city = driver.find_element_by_xpath("//font[@id='zoom']/p[%d]"%i).text         elem_city = elem_city.encode('utf-8')         try:             city = re.split("[/.]",elem_city)[1]             city = re.split("（",city)             city1 = city[0]             # 一个中文字符占3个长度！！             if len(city1)>13:                 city2 = city1[0:6]             else:                 city2 =city1.strip()              lat_lng = getLocation_xml(city2+"市")             city_location = "%s %s"%(city2,str(lat_lng))             city_locationOnlyLatLng = lat_lng             #write2txt(city_location,"City&LocationBySelenium.txt")             print city_location              cityLocationList.append(city_location)             cityLocationListOnlyLatLng.append(city_locationOnlyLatLng)         except:             print 'something wrong with ',elem_city     # 调用完后记得关闭！！！！！不然phantomjs一直占用内存     driver.close()     driver.quit()     return cityLocationList,cityLocationListOnlyLatLng  # 返回了一个有城市和经纬度对应的列表如：上海 31.249162,121.487899 # 还返回了一个只有经纬度的列表如 ：31.249162,121.487899  #至于主程序，只要把city_locationList,cityLocationListOnlyLatLng= getCityByBS4(url)中的getCityByBS4(url)换成getCityBySelenium(url)，之后改一下txt文件名就行了，当然，这些函数都是在一个py文件里的``

## 方法1：调用API接口

``#获取json格式的url http://api.map.baidu.com/geocoder?address=城市&output=json&key=f247cdb592eb43ebac6ccd27f796e2d2``
``#返回xml格式的url http://api.map.baidu.com/geocoder?address=城市&output=xml&key=f247cdb592eb43ebac6ccd27f796e2d2``

``#调用API返回json格式  import urllib2 url= 'http://api.map.baidu.com/geocoder?address=北京&output=json&key=f247cdb592eb43ebac6ccd27f796e2d2' html = urllib2.urlopen(urllib2.Request(url)) json1 = html.read() #转化为str类型 print json1``

``    "status":"OK",     "result":{         "location":{             "lng":116.395645,             "lat":39.929986         },         "precise":0,         "confidence":10,         "level":"/u57ce/u5e02"     } }``

``def getLocation_json(addr):     url= 'http://api.map.baidu.com/geocoder?address=%s&output=json&key=f247cdb592eb43ebac6ccd27f796e2d2'%(addr)     html = urllib2.urlopen(urllib2.Request(url))     json1 = html.read() #转化为str类型      hjson =json.loads(json1) #转化为dict类型     lng = hjson['result']['location']['lng'] # 经度     lat = hjson['result']['location']['lat'] # 纬度     lng_lat = [lng, lat]     return lng_lat``
``#返回json数据格式 {     "status":"OK",     "result":{         "location":{             "lng":116.395645,             "lat":39.929986         },         "precise":0,         "confidence":10,         "level":"/u57ce/u5e02"     } }``

``#返回xml数据格式 <?xml version="1.0" encoding="utf-8" ?>  <GeocoderSearchResponse>      <status>OK</status>     <result>                     <location>                 <lat>39.929986</lat>                 <lng>116.395645</lng>             </location>                 <precise>0</precise>             <confidence>10</confidence>             <level>城市</level>             </result>     </GeocoderSearchResponse>``

``def getLocation_xml(addr):     url= 'http://api.map.baidu.com/geocoder?address=%s&output=xml&key=f247cdb592eb43ebac6ccd27f796e2d2'%(addr)     html = urllib2.urlopen(urllib2.Request(url))     xml = html.read()      bs_getDetail = BeautifulSoup(xml,'lxml')     #方法一，直接根据路径找     lng =float(bs_getDetail.result.location.lng.string)     lat = float(bs_getDetail.result.location.lat.string)      '''     #方法二，使用find方法+正则表达式     lat = bs_getDetail.find('lat')     lng = bs_getDetail.find('lng')     pattern = '/d+/./d+'     lat = re.findall(pattern,str(lat))[0]     lng = re.findall(pattern,str(lng))[0]     '''     lat_lng = "%s,%s"%(lat,lng)     return lat_lng``

## 方法2：使用Geopy包

``# 调用Geopy包进行处理-获取城市名 def getCitynameByGeo(lat_lng):     #知道经纬度获取地址     geolocator = Nominatim()     location = geolocator.reverse(lat_lng)     addr = location.address     print addr     cityname = re.split("[/,]",addr)[-5].strip()     print cityname      return addr,cityname  # 调用Geopy包进行处理-获取经纬度 def getLocationByGeo(cityname):     #知道地址获取经纬度     geolocator = Nominatim()     location2 = geolocator.geocode(cityname)     lat = location2.latitude     lng = location2.longitude     return "%s  %s,%s"%(cityname,lat,lng)  #返回形如：西安  34.2191582,109.110194631``

``import re #导入包，实例化对象 from geopy.geocoders import Nominatim  # 调用Geopy包进行处理-获取城市名 def getCitynameByGeo(lat_lng):     #知道经纬度获取地址     geolocator = Nominatim()     location = geolocator.reverse(lat_lng)     addr = location.address     print addr     cityname = re.split("[/,]",addr)[-5].strip()     return addr,cityname  f = open("LocaionOnlyByBS4.txt") lines = f.readlines() for line in lines:     getCitynameByGeo(line)``

``长治路, 虹口区, 虹口区 (Hongkou), 上海市, 200080, 中国 织染局胡同, 东城区, 北京市, 东城区, 北京市, 100010, 中国 春风路, 东山街道, 越秀区 (Yuexiu), 广州市 / Guangzhou, 广东省, 港方口岸區 Hong Kong Port Area, 510623, 中国  ...``

## 调用API VS Geopy

Geopy比较好吧，毕竟很加符合pythonic，包之间的相互使用，界限分明，而且对于不熟悉bs4，json，re的童鞋来说，这个简直遇到了亲人一样亲切！

btw–大家都要联网才能用的0.0

## Q&A

1.分割字符串的时候，竟然出现了�乱码问题，原来中文字符占三个长度，，，，好吧，用的挺长时间的len()，第一次遇到中文，额。

``str1 = "中文" print len(str1) #6 #一个中文占了三个长度！！！！！，难怪出现长度分割�乱码问题!!!``

2.个别城市调用API时出错，比如西安这个城市(使用geopy没有这个问题)

``lng_lat = getLocation_json("西安") print lng_lat  #输出以下 Traceback (most recent call last):   File "C:/Users/MrLevo/PycharmProjects/test/llll.py", line 208, in <module>     lng_lat = getLocation_json("西安")   File "C:/Users/MrLevo/PycharmProjects/test/llll.py", line 203, in getLocation_json     lng = hjson['result']['location']['lng'] # 经度 TypeError: list indices must be integers, not str``

``lng_lat = getLocation_json("西安市") print lng_lat  #[108.953098, 34.2778]``