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

前言

我是一名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照片,能够将景点周边的真实面貌以高清照片的形式展现出来,让你提前预览美景之后,再决定要不要前往。

未完待续

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,911评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,014评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,129评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,283评论 1 264
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,159评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,161评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,565评论 3 382
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,251评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,531评论 1 292
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,619评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,383评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,255评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,624评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,916评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,199评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,553评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,756评论 2 335

推荐阅读更多精彩内容