什麼是API(介面)
此文選自知乎大佬
https://www.zhihu.com/question/38594466/answer/122391324
https://zhuanlan.zhihu.com/p/30742302
1.知乎上優秀解釋
API(介面)是什麼?舉個常見的例子,在京東上下單付款之後,商家選用順豐發貨,然後你就可以在京東上實時檢視當前的物流資訊。京東和順豐作為兩家獨立的公司,為什麼會在京東上實時看到順豐的快遞資訊,這就要用到API,當檢視自己的快遞資訊時,京東利用順豐提供的API介面,可以實時調取資訊呈現在自己的網站上。除此,你也可以在快遞100上輸入訂單號查取到快遞資訊。只要有合作,或是有允許,別的公司都可以通過順豐提供的API介面調取到快遞資訊。既然有多方呼叫,那提供一個統一的呼叫規範會方便很多。
我們看下百度是怎麼給出API的定義的:
API(Application Programming Interface,應用程式程式設計介面)是一些預先定義的函式,目的是提供應用程式與開發人員基於某軟體或硬體得以訪問一組例程的能力,而又無需訪問原始碼,或理解內部工作機制的細節。
API翻譯成中文就是"應用程式介面",其實這樣翻譯不好,應該說是"程式溝通介面"。
翻譯為介面,顧名思義就要溝通兩個不同的東西用的,通常由一組函式庫所組成。
在一個 同一個平臺 下的 兩個不同東西(程式 or 系統),為了能取用對方的功能等等,
所以一個 X程式 寫了一組函式,讓 同一平臺的其他程式 取用 X程式 的功能
,那組函式就可以說是那個 X程式 對外開放的 API。
從百度定義中,我們先劃下重點:函式、 提供應用程式與開發人員 、無需訪問原始碼、例程 。注意這四個短語。其中,例程是某個系統對外提供的功能介面或服務的集合,本文著重說下API的資料服務功能介面。
首先,下面的文章我會先演示怎麼通過瀏覽器,不需要程式設計、不需要訪問原始碼,來呼叫免費的API介面,達到讓你怎麼使用最簡單的介面;
然後,會演示怎麼通過程式設計去呼叫介面;
最後,演示開啟WEB服務,寫一個簡單的API介面,以體現出API的函式 (y=f(x)) 功能。
你也可以複製程式碼試下。通過你自己的嘗試,你會了解到些後端、前段的東西,並加深你對API的理解。那麼我們就開始吧,先上一個圖:以API提供資訊(資料)的功能,看下資料是怎麼流動的。如果給API一個具體的位置的話,就位於下圖中央。
為了更改的理解,我穿插一個故事角色。假如,世界太大,身處非洲大陸的你想去看看,成為了一個水手,被一位著名的航海家帶去去遠航(你掌握著船上唯一一臺衛星電腦),途中不免航海家會讓確定下城市的經緯度。這時航海家讓你去確定下深圳市的經緯度。
1、你是個人肉API
這時,你能想到簡單的辦法就是去百度搜索一下。 除了航海家,船上的高階水手、大副,估計都有可能向你問,這個時候,其實你就是一個介面,大家都來向你獲取地理位置資訊,作為介面,你本身不產生資訊,你只是資訊的蒐集者、傳遞者,提供人肉資料服務。
2、使用免費的經緯度API介面
在百度搜索的過程中,眾多網友給出的經緯度不一致,你要反覆對比,去辨真偽。時間長了,你可能會覺得大家都問位置,太煩了,我這個人肉API效率太慢,有沒有更快的方式。
這時你發現了一個阿里雲的一個免費的API介面:http://gc.ditu.aliyun.com/geocoding?a=深圳。你在瀏覽器位址列輸入了這個URL,果然得到了正確的經緯度,你又把URL中的深圳改為了別的城市,發現也可以查到。這時,通個這個介面,你給大夥確定位置的效率大大提升。
3、你不滿足於此
你覺得這個介面太好了,剛好你會點Python,何不寫點程式碼,注意這個時候你的角色發生了變化:你由一個人肉API轉變了一個開發人員(注意這個是百度API定義中的關鍵詞),你現在的目標是寫程式碼,能夠自動獲取到這個某個地方的經緯度。
#python
import requests
r = requests.get("http://gc.ditu.aliyun.com/geocoding?a=深圳")
loc = r.json()
print loc
#打印出的結果:{u'alevel': 4, u'lon': 114.05786, u'level': 2, u'cityName': u'', u'address': u'', u'lat': 22.54309}
# 與在瀏覽器輸入地址的結果一致
print "深圳的經度是%s,緯度是%s" % (loc["lon"], loc["lat"])
#打印出的結果是:深圳的經度是114.05786,緯度是22.54309
到這裡,我們再來回顧下API的百度定義。目前,你作為一個開發人員, 具備通過寫了幾行程式碼訪問“阿里雲經緯度介面”的能力, 你無需訪問這個API的原始碼、不需要理解這個API是怎麼弄成的 。也就是,不管是通過瀏覽器,還是程式語言,目前你已經會用簡單的API了。
4、在會用簡單API的介面後,你進一步想知道它的內在機制是什麼
建立在會用的基礎之上,那麼API的原始碼、其內在機制是怎麼回事?目前你能呼叫經緯度的API,簡單的獲取到位置還不夠,你可能自己想寫一個API介面,不緊緊提供位置資訊,同時附加上對這個城市的介紹。
利用Python的tornado模組,搭建一個web服務。我們建一個指令碼空檔案 web_server.py,把以下程式碼複製進去
# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
import tornado.ioloop
import tornado.web
import json
import requests
lists = {u"深圳": "是經濟特區,緊鄰廣州,接壤香港,人口約1200萬",
u"青島": "旅遊城市,瀕臨黃海,特產啤酒,人口約920萬"
}
def get_loc(city):
r = requests.get("http://gc.ditu.aliyun.com/geocoding?a=%s" % city.encode('UTF-8'))
loc = r.json()
return "經度是%s,緯度是%s" % (loc["lon"], loc["lat"])
class BaseHandler(tornado.web.RequestHandler):
def get_current_user(self):
return self.get_secure_cookie("user")
class MainHandler(BaseHandler):
def get(self):
if self.request.arguments.has_key("id"):
greeting = self.get_argument('id', 'Hello')
if greeting in lists:
self.write(greeting + ": " + str(get_loc(greeting)) + "," + str(lists[greeting]))
else:
self.write("none")
settings = dict(cookie_secret="P1/V61oETzdkLmGeJJFuYh7Eo5KXQAGaYgEQnp2XdTo=", debug=True)
application = tornado.web.Application([(r"/", MainHandler), ], **settings)
if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.current().start()
執行web_server.py,執行後就會開啟一個web服務
接著,我們在瀏覽器輸入http://192.168.199.204:8888/?id=深圳
注意,我自己的電腦區域網IP是192.168.199.204,需要替換成你自己電腦(或虛擬機器)的ip
從上圖看,我們實現了,和”阿里雲經緯介面“的相同功能,並且獲取到了除經緯度,還有對城市的簡單描述。隨著航行越來越多,你讓船上的大夥不僅瞭解了地理位置資訊,也瞭解了每個城市的經濟人文情況。隨著資訊資料的增多,特別需要一個東西能先把資料先儲存起來,用到的時候,API再直接呼叫。
5、資料儲存,調我所需
上面我們模仿了阿里雲的API,自己搭建了一個web服務,提供額一個更為詳細的API地理位置資訊服務。現在想一下,我們的程式碼裡只有深圳、青島兩個城市,還有很多沒提到的城市,另外,城市還有經濟發展情況、飲食文化等。我們把深圳、青島兩個城市資訊存入到mysql裡。
存入之後,我們從mysql裡直接拿資料,通過API直接展現在到瀏覽器中。改動 web_server.py指令碼中的
# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
import tornado.ioloop
import tornado.web
import json
import requests
import MySQLdb.constants
def get_mysql(sql_string):
conn = MySQLdb.connect(host='localhost', port = 3306, user = 'root', passwd = '123456', db = 'test', charset = 'utf8')
cursor = conn.cursor()
cursor.execute(sql_string)
resultList = {}
for data in cursor.fetchall():
city_name = data[0]
city_introduce = data[1]
resultList[city_name] = city_introduce
return resultList
cursor.close()
conn1.close()
def get_loc(city):
r = requests.get("http://gc.ditu.aliyun.com/geocoding?a=%s" % city.encode('UTF-8'))
loc = r.json()
return "經度是%s,緯度是%s" % (loc["lon"], loc["lat"])
class BaseHandler(tornado.web.RequestHandler):
def get_current_user(self):
return self.get_secure_cookie("user")
class MainHandler(BaseHandler):
def get(self):
if self.request.arguments.has_key("id"):
greeting = self.get_argument('id', 'Hello')
lists = get_mysql("select name,introduce from test.city where name ='%s' " % greeting.encode('UTF-8')) #直接從mysql裡讀取城市資訊,特別注意這裡的SQL
if greeting in lists:
self.write(greeting + ": " + str(get_loc(greeting)) + "," + str(lists[greeting