美文网首页深度生活学习工具API
Python 小白的入门实战——利用百度API自动获取数据

Python 小白的入门实战——利用百度API自动获取数据

作者: Maphy | 来源:发表于2016-06-17 21:06 被阅读3459次

    前言

    我是一名Python小白,两个礼拜之前还对Python一无所知,上次我利用举办社团活动的契机,请学校老师做了一次Python入门讲座。听闻Python功能强大,对初学者也很友好,于是抱着初生牛犊不怕虎的精神,尝试尝试用Python来解决一个复杂的难题。

    问题

    旅游爱好者小龙有钱又有时间,她决定制定一个详尽的旅行计划,游遍目前中国的热门景区。目前手边仅有的资料就是一份想要游览的景区的名单(如下图,总共有两百多个景点),其中主要是国家评定的5A级景区,制定怎样的旅行计划,才能最高效的游遍所有的景区呢?

    问题解决的思路

    首先这是一个非常具有现实意义的问题,它的核心是旅行商问题(Traveling Salesman Problem),也就是已知地点和地点之间的距离,找出游遍所有地点的最短路线。这是一个计算机领域的NP完全问题。TSP问题的核心算法有很多人已经研究过了。然而我们要解决的并不是一个纯数学的问题,而是一个实际问题。难点其实在于数据的搜集和整理。
    经过一番艰难的思索和尝试,我列出了下图所示的程序设计思路。其主要思想在于利用百度提供的免费API接口,获取各个景点的地理位置、地址,附件机场、车站以及景点之间的路线等各种信息,再将获得的json文件进一步处理,得到格式化的数据,导入TSP路径求解器,获得最优路径,再将最优路径在地图中表示出来,并给出详细的形式指南。


    这是一个尚在进行中的浩大工程,尤其对于一个Python新手来说。

    学习Web API的调用

    Web API是一种应用程序接口,通过一定的设置之后,程序可以通过发送不同网址查询所需的数据。API的使用需要申请密钥,本文中使用的到的密钥均可以免费获取。
    地理服务相关的API有不少,比较成熟的是百度和谷歌两家。虽然很多时候谷歌的服务都显得高大上许多,但是经过一番尝试,在地图服务,尤其是国内的地图服务上,百度有很多优势。除去连接的稳定性之外,百度的所有Web API共享一个密钥,而谷歌需要为不同的API分别申请密钥,而且百度对中文支持完善,所以这里主要使用了百度地图的Web API服务。用户可以到这个地址申请:http://lbsyun.baidu.com/ 除了地图之外,百度还有一个API商店,提供了很多免费的API服务,网址:http://apistore.baidu.com/

    Python程序

    调用Web API的程序其实相当简单,笔者作为一个小白没花多长时间就捣鼓出了一段代码。

    # -*- coding: utf-8 -*-
    '''
    Created on 17-June-2016 @Jerry
    用于调用百度地图和去哪儿网的web api。
    '''
    
    import sys,urllib2,urllib,os
    
    #===============================================================================
    #读取API Key--------------------------------------------
    f_key = open("API Key.txt",mode='r')
    key = []
    for line in f_key.readlines():
        line = line.strip('\n')
        key += [line.split(",")]
    apikey = dict(key)
    f_key.close()
    #------------------------------------------------------
    #读取API Url--------------------------------------------
    f_url = open("API Url.txt",mode='r')
    url = []
    for line in f_url.readlines():
        line = line.strip('\n')
        url += [line.split(",")]
    apiurl = dict(url)
    f_url.close()
    #------------------------------------------------------
    #===============================================================================
    
    #===============================================================================
    #查询百度地图API-------------------------------------------
    class BaiduQuery:
        def __init__(self,api,args,name):
            self.api = api          #调用的API名称
            self.args = args        #查询变量
            self.name = name        #查询结果的命名方式
    
        def getjson(self):
            baseurl = apiurl[self.api]
            self.args["ak"] = apikey["BaiduMap"]
            self.args["output"] = "json"
            encodeargs = urllib.urlencode(self.args)
            url = urllib.unquote(baseurl + encodeargs)
            routeDir = "Data/"+self.name+'/'+self.api+'.json'
            urllib.urlretrieve(url, routeDir)
            print self.name,self.api," -> Success"
    
        def makedir(self):          #文件夹是否已创建
            if not os.path.exists("Data/"+self.name+"/"):
                os.makedirs('Data/'+self.name+'/')
                print "Make Dir Successfully!"
                return 1
            else:
                return 0
    #------------------------------------------------------
    #===============================================================================
    #查询百度API商店中去哪儿网火车票、景点门票--------------------------------------
    class QunarQuery:
        def __init__(self,api,args,name):
            self.api = api          #调用的API名称
            self.args = args        #查询变量
            self.name = name        #查询结果的命名方式
    
        def getjson(self):
            baseurl = apiurl[self.api]
            encodeargs = urllib.urlencode(self.args)
            url = urllib.unquote(baseurl + encodeargs)
            routeDir = "Data/"+self.name+'/'+self.api+'.json'
            req = urllib2.Request(url)
            req.add_header("apikey", apikey["Qunar"])
            resp = urllib2.urlopen(req)
            content = resp.read()
            if(content):
                with open(routeDir, "wb") as code:
                    code.write(content)
            print self.name,self.api," -> Success"
    
        def makedir(self):          #文件夹是否已创建
            if not os.path.exists("Data/"+self.name+"/"):
                os.makedirs('Data/'+self.name+'/')
                print self.name," -> Make Dir"
                return 1
            else:
                return 0
    #------------------------------------------------------
    #===============================================================================
    #使用示例-----------------------------------------------
    # values={
    #     "version":"1.0",
    #     "from":"上海",
    #     "to":"南京",
    #     "date":"2016-06-18"
    # }
    # ID23 = QunarQuery("QunarTrain",values,"23")
    # ID23.makedir()
    # ID23.getjson()
    #===============================================================================
    

    这段代码将需要查询的信息编码到网址中,其中两个本地txt文件中存放的是申请的API Key和各种不同的Web服务的网址。网址在官网都可以查询到,需要注意的是网址后面要手动加上一个“?”。
    由于百度地图的API和百度API商店中的API调用略有不同,因此写了两个class,不知道大牛能不能将两个class合并成一个。
    在调用不同的服务的时候,输入相关参数,将返回的json文件存储到本地相应景点编号下的文件夹中。

    json文件的处理

    本文中用到的API返回的都是json格式的文件(如下图)。看起来密密麻麻,作为小白的我当然是没听说过这是个啥啦。一番百度之后,找到了一个很好的在线工具json在线编辑器,可以将json文件重新排版,并且给出文件结构树,相当方便。


    格式化之后的文件就好看了许多,可以看到里面包含了两地之间的火车票信息,这是通过qunar的接口获得的数据。

    json文件的处理笔者还没有摸索出最优的方法,等搞清楚了再来写一写。

    中国的景点分布图

    在我之前的尝试中,我试着用Python的Basemap和GeoPy包解析处理这两百多个景点的具体经纬度信息,当然后来发现还是百度地图的API最直接最方便。获取的这些数据直接绘制出来就是下面的效果,图中的深蓝色小点就是中国5A景区所在地:



    在通过flight100网站获得全世界所有机场和航线的数据之后,我又将其中中国的数据筛选出来,绘制出了中国的机场和航线分布图。



    当然用Basemap只能绘制出简单的静态图,有没有办法让辛辛苦苦获得的这些地理数据发挥更大的用处呢,当然是可以的。

    将地理数据导入Google Earth

    输出上,你可以将地理位置数据导入到Google Earth中。只是在导入之前还需要一番处理。Google Earth使用的是一种特殊格式的kml文件,你可以在这个网站将可以在Excel中打开的csv格式文件在线转换成kml文件,然后直接拖入Google Earth软件,谷歌地球会帮你自动标注出来,效果就像下面这张图,里面的各个景点都用小图钉标注了出来。


    为什么说这些数据能在谷歌地球中发挥更大价值呢?这是因为谷歌地球自带了很多图片。尤其是其中的Panoramio照片,能够将景点周边的真实面貌以高清照片的形式展现出来,让你提前预览美景之后,再决定要不要前往。

    未完待续

    相关文章

      网友评论

      本文标题:Python 小白的入门实战——利用百度API自动获取数据

      本文链接:https://www.haomeiwen.com/subject/mqvvdttx.html