本篇文章為大家帶來了關於python的相關知識,其中主要介紹了關於API呼叫的相關問題,包括了API的呼叫和資料介面的呼叫、請求方法、幾種常見API呼叫實例等等內容,下面一起來看一下,希望對大家有幫助。
推薦學習:python影片教學
在日常工作中,可能需要結合一些在網路上現在的API或公司提供的資料介面來得到對應的資料或實現對應的功能。
因此API的呼叫和資料介面的存取都是做資料分析的常用操作,如何快速實作API和資料介面的調用,網路上一般提供很多語言版本,但追根溯源採取的方式都是利用HTTP請求的方式來進行實現的。
API:簡單來說就是一組協定、一個工具或一組規則,定義不同應用程式之間的通訊方法,把具體實作的過程隱藏起來,只暴露必須呼叫的部分給開發者使用。
上面的定義比較官方,這裡簡單舉個例子來說明一下,比如在現在外面的麥當勞等快餐店都採取手機線上下單,前台拿餐的過程。而在這個過程,作為消費者通常在手機上選好對應的餐品然後點擊下單付款,然後等待前台叫號拿餐即可。而這個過程具體怎麼實現的我們並不知道,整個過程有對應的app或是小程式通訊到廚房數據,然後廚師製作出餐。而這個APP和小程式就可以作為對應的API功能。
舉一個簡單的例子,一個社交平台它每天收到各種語言的評論訊息,而作為對應的分析人員面對複雜的語言資料處理,是一個大難題,有人可能說開發一個模型來實現翻譯整合功能,這個方法雖然聽起來可行但是成本代價高,其次為了解決一個問題,而又去發展一個比較困難的問題。這與原本的目標偏離越來越遠,這個時候就可以藉助國內較成熟的翻譯平台API,直接處理現有的數據。這樣相對而言成本代價小,更方便也更能快速達成現有的目標。而API的作用在這裡就毋庸置疑了。
資料介面: 簡單來說就是一組封裝的資料集口令,就是依照對應的規則傳送對應的參數,然後回傳對應的相關資料資訊。 API的呼叫和資料介面的這兩個在日常呼叫時很類似的,相對而言API的範圍更寬廣,實現的功能也比較多,而資料介面日常充當的就是一個取數工具比較多。
就比如說大型電商公司公司一般用統一的SKU來管理商品,而例如這家公司是作為一個品牌商,它會在不同平台上面進行售賣,而在這些平台上面映射的商品識別ID就不同於公司的SKU。因為公司的SKU不僅基於商品而且還考慮各個地方倉庫以及產品的各個型號,而這個映射相對而言就比較複雜。
而在處理不同平台的資料人員一般也不能直接使用公司的資料庫來對商品進行分析,因為顆粒度太細,分析起來比較複雜困難,這個時候就可以根據對應功能的要求讓開發在現有系統是開發一個單獨的資料介面提供相應的公司,避免直接請求資料庫過程複雜等相應資訊。但數據介面相對即時的資料庫存在一定的延遲。
API和資料介面透過前面的舉例論述,大致理解起來也比較簡單,而具體怎麼實作API的呼叫和資料介面的呼叫這裡簡單介紹一下。
簡單來說API的呼叫和介面的呼叫都是類似一個HTTP請求,而呼叫最主要就是根據對應的規則將請求方式、請求頭、URL、以及請求體封裝好然後發送請求,就可以實現相應的調用。
但資料介面和API兩個的呼叫相比較而言來,一般資料介面比較簡單,很多情況下資料介面是在公司內網資料存取所以請求資訊比較簡單,而API大多是第三方企業開發對外的服務屬於一種商業服務,相對而言為了確保請求的安全,考慮的更為全面,加入了AK、SK、簽章、時間戳等資訊較為複雜。
而追本溯源這兩個呼叫都是類似HTTP請求,具體呼叫大致差不多,主要就是API呼叫中包含的請求參數的資訊比較多。而具體怎麼實現下面將簡單的介紹一下。
一般而言,常見的HTTP請求呼叫方式有很多,這方面的資源比較多,可以網路上自己查閱,這裡就簡單說說常見的兩種請求方法。
GET請求簡單來說就是從伺服器上取得資源,可以載入到瀏覽器的快取中。
POST請求一般而言以表單形式向伺服器發送請求,請求參數包含在請求體當中可能導致資源的建立和改變。 POST請求的資訊不能快取在瀏覽器中。
這兩個請求方法說起來很簡單,但最重要的一點就是了解這兩種請求的區別,從而為介面的設計和API的使用更加熟悉。
1.GET請求請求長度最多1024kb,POST對請求資料沒有限制。這一點原因是很多時候GET要求把對應的資訊放在URL中,而URL的長度有限,導致GET請求的長度也受到一定的限制。而POST請求對應的參數資訊放在請求體body所以一般不受長度限制。
2.POST請求比GET更安全一些,因為GET請求中URL包含了相應的信息,頁面會被瀏覽器緩存,其他人可以看到相應的信息。
3.GET產生一個TCP封包,POST產生兩個TCP封包。
GET請求的時候將header、data一起發送出去,然後伺服器回應回傳200。而POST則是先發送header,等待伺服器回應100,然後發送data,最後伺服器回應返回200.但在這裡註意,POST請求分為兩次,但是請求體body是緊跟在header之後發送的,所以這之間時間可以微乎不計。
4.GET請求只支援URL編碼,而POST相對而言有多種編碼方式。
5.GET請求參數是透過URL傳遞的,多個參數以&連接,POST請求放在request body。
6.GET請求只支援ASCII字符,而POST沒有限制。
一般而言瀏覽器輸入網址可以直接存取的一般是GET請求。
上面大篇幅的介紹了一些資料介面、API相關知識以及請求方法,使用起來比較簡單,下面可以大致熟悉一下對應的請求方式。一般直接使用Python的request函式庫就可以。
import request # GET请求发送的参数一定要是字典的形式,可以发送多个参数。 # 发送格式:{'key1':value1', 'key2':'value2', 'key3', 'value3'} # 样例不能运行 url ='http://www.xxxxx.com' params = {'user':'lixue','password':111112333} requests.get(url,data = parms)
POST請求一般有三種提交形式:application/x-www-form -urlencoded、multipart/form-data、application/json.
具體查看是三種的哪一種請求方式:Google瀏覽器檢查→ Network →選擇載入檔案→ Headers → Reuqest Headers → Content-Type
具體編碼方式為下面三種,可以了解具體的請求實現,一般公司內部的資料介面設定了區域網路所以有的可以不需要加header。
1.最常見的post提交資料以form表單為主:application/x-www-form-urlencoded
import request data={'k1':'v1','k2':'v2'} headers= {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36'} requests.post(url,headers = headers,data=data)
2.以json格式提交資料:application/json
data = {'user':'lixue','password':12233} data_json = json.dumps(params) requests.post(url,headers = headers,data = data_json)
3.一般用來傳檔案(爬蟲很少用到):multipart/form-data
files = {'files':open('c://xxx.txt','rb')} requests.post(url = url,headers = headers,files = files)
透過上面簡單的介紹,對於具體請求大致了解,這裡蒐集了一個簡單的API聚合中心,提供了很多挺好用的功能。下面以這個簡單API的作一個簡單的示範API位址。
這個小實例採取的是天氣API介面取得近15天的天氣。在使用這個API之前記得取得對應的apiKey和查看具體的使用文件。這個API網站一般對對應API提供一定的免費次數,可以充當學習使用,而且支援GET和POST請求。剛好可以適合練手。
params = { "apiKey":'换成你的apikey', "area":'武汉市', } url = 'https://api.apishop.net/common/weather/get15DaysWeatherByArea' response = requests.get(url,params) print(response.text)
這裡的POST請求也就是對應上面的最常見的post提交資料以form表單為主:application/x-www- form-urlencoded
url = 'https://api.apishop.net/common/weather/get15DaysWeatherByArea' params = { "apiKey":'换成你的apikey', "area":'武汉市武昌区', } response = requests.post(url,params) print(response.text)
在呼叫這種API介面一般都需要進行一個狀態碼等回傳資訊測試,檢查請求是否正常,可以依照下面的給予參考。
params = { "apiKey":'换成你的apikey, "area":'武汉市', } url = 'https://api.apishop.net/common/weather/get15DaysWeatherByArea' response = requests.post(url,params) print(response.text) if response.status_code != 200: raise ConnectionError(f'{url} status code is {response.status_code}.') response = json.loads(response.content) if 'desc' not in response.keys(): raise ValueError(f'{url} miss key msg.') if response['desc'] != '请求成功': print(11)
其實API的呼叫很簡單,但其中最核心的其實是傳回資訊中資料的抽取,一般而言傳回的資訊都是json形式,需要從中用字典鍵值對方式提取數據,下面這塊根據請求的數據返回相應的信息並提取出來,獲取信息後面將會展示。
import requestsimport pandas as pd import numpy as npimport jsondef get_url(area): url = 'https://api.apishop.net/common/weather/get15DaysWeatherByArea' params = { "apiKey":'换成你的apikey', "area":area, } response = requests.get(url,params) if response.status_code != 200: raise ConnectionError(f'{url} status code is {response.status_code}.') response = json.loads(response.content) if 'desc' not in response.keys(): raise ValueError(f'{url} miss key msg.') if response['desc'] != '请求成功': print(11) return responsedef extract_data(web_data): data= web_data['result']['dayList'] weather_data = pd.DataFrame(columns = ['city','daytime','day_weather','day_air_temperature','day_wind_direction','day_wind_power', 'night_weather','night_air_temperature','night_wind_direction','night_wind_power']) for i in range(len(data)): city = data[i]["area"] daytime = data[i]["daytime"] daytime = daytime[:4]+'-'+daytime[4:6]+'-'+daytime[-2:] day_weather = data[i]["day_weather"] day_air_temperature = data[i]['day_air_temperature'] day_wind_direction = data[i]["day_wind_direction"] day_wind_power = data[i]['day_wind_power'] night_weather = data[i]['night_weather'] night_air_temperature = data[i]["night_air_temperature"] night_wind_direction = data[i]['night_wind_direction'] night_wind_power = data[i]["night_wind_power"] c = {"city": city,"daytime": daytime,"day_weather":day_weather,"day_air_temperature":day_air_temperature, "day_wind_direction":day_wind_direction,"day_wind_power":day_wind_power,"night_weather":night_weather, "night_air_temperature":night_air_temperature,"night_wind_direction":night_wind_direction, "night_wind_power":night_wind_power} weather_data = weather_data.append(c,ignore_index = True) weather_data.to_excel(r"C:\Users\zhangfeng\Desktop\最近十五天天气.xlsx",index = None) return weather_dataif __name__ == '__main__': print("请输入对应的城市") web_data = get_url(input()) weather_data = extract_data(web_data)
部分結果如下圖:
在日常學習中資料介面的使用可能相對較少,資料介面的應用場景大多數情況下是應用在公司內部調取數據的情況下比較多,所以一般很少見到,這裡展示工作中遇到的兩個數據接口的使用,由於工作考慮,展示的代碼屬於樣例,並不能調用。可以參考一下呼叫實作以及規範。
# 销售状态查询def id_status(id_dir): id_data = pd.read_excel(id_dir,sheet_name="Sheet1") id_data.columns = ['shop', 'Campaign Name','Ad Group Name','Item Id'] # 方便后期处理更改列名 id_data["Item Id"] = id_data["Item Id"].astype(str) id_list = list(id_data['Item Id']) print(len(id_list)) id_list = ','.join(id_list) if isinstance(id_list, int): id_list = str(id_list) id1 = id_list.strip().replace(',', ',').replace(' ', '') request_url = "http://xxx.com" # 通过item_id查询id状态 params = { "item_id":id1, } data_json = json.dumps(params) # 属于POST第二种请求方式 response = requests.post(request_url, data = data_json) print(response.text) if response.status_code != 200: raise ConnectionError(f'{request_url} status code is {response.status_code}.') response = json.loads(response.content) if 'message' not in response.keys(): raise ValueError(f'{request_url} miss key msg.') if response['message'] != 'ok': print(11) data= response['result'] ad_data = pd.DataFrame(columns = ['Item Id','saleStatusName']) for j in range(len(data)): item_id =data[j]["item_id"] saleStatusName = data[j]['saleStatusName'] c = {"Item Id": item_id, "saleStatusName": saleStatusName, } ad_data = ad_data.append(c,ignore_index = True) total_data = pd.merge(ad_data,id_data,on ='Item Id', how ='left') df_column = ['shop', 'Campaign Name','Ad Group Name','Item Id','saleStatusName'] total_data = total_data.reindex(columns=df_column) return total_data
### 库存数据查询def Smart_investment_treasure(investment_dir): product_data = pd.read_excel(investment_dir,sheet_name="product") if len(product_data)>0: product_data['商品ID']=product_data['商品ID'].astype(str) product_list=list(product_data['商品ID']) product_id = ','.join(product_list) else: product_id='没有数据' return product_id def stock_query(investment_dir): product_data = pd.read_excel(investment_dir,sheet_name="product") if len(product_data)>0: product_data['商品ID']=product_data['商品ID'].astype(str) product_list=list(product_data['商品ID']) product_id = ','.join(product_list) else: product_id='没有数据' if isinstance(product_id, int): product_id = str(id) product_id = product_id.strip().replace(',', ',').replace(' ', '') request_url = "http://xxx.com" # 通过ali_sku查询erpsku params = { "product_id":product_id, } response = requests.get(request_url, params) #属于GET请求 if response.status_code != 200: raise ConnectionError(f'{request_url} status code is {response.status_code}.') response = json.loads(response.content) if 'msg' not in response.keys(): raise ValueError(f'{request_url} miss key msg.') if response['msg'] != 'success': print(11) data= response['data']['data'] # requestProductId = id.split(',') id_state=[] overseas_stock=[] china_stock=[] id_list=[] for j in range(len(data)): inventory_data= data[j]['list'] overseas_inventory=0 ep_sku_list=[] sea_test=0 china_inventory=0 test="paused" id_test="" id_test=data[j]['product_id'] for i in range(len(inventory_data)): if inventory_data[i]["simple_code"] in ["FR","DE","PL","CZ","RU"] and inventory_data[i]["erp_sku"] not in ep_sku_list: overseas_inventory+=inventory_data[i]["ipm_sku_stock"] ep_sku_list.append(inventory_data[i]["erp_sku"]) sea_test=1 elif inventory_data[i]["simple_code"] == 'CN': china_inventory+=int(inventory_data[i]["ipm_sku_stock"]) if overseas_inventory>30: test="open" elif overseas_inventory==0 and china_inventory>100: test="open" id_list.append(id_test) overseas_stock.append(overseas_inventory) china_stock.append(china_inventory) id_state.append(test) c={"id":id_list, "id_state":id_state, "海外仓库存":overseas_stock, "国内大仓":china_stock } ad_data=pd.DataFrame(c) return ad_data
百度API是市面上面比较成熟的API服务,在大二期间由于需要使用一些文本打标签和图像标注工作了解了百度API,避免了重复造轮子,当时百度API的使用比较复杂,参考文档很多不规范,之前也写过类似的百度API调用极其不稳定,但最近查阅了百度API参考文档,发现目前的调用非常简单。
通过安装百度开发的API第三方包,直接利用Python调包传参即可使用非常简单。这里展示一个具体使用,相应安装第三方库官方文档查阅。
''' 第三方包名称:baidu-aip 百度API """ 你的 APPID AK SK """ APP_ID = '你的 App ID' API_KEY = '你的 Api Key' SECRET_KEY = '你的 Secret Key' 参考文档:https://ai.baidu.com/ai-doc/NLP/tk6z52b9z ''' from aip import AipNlp APP_ID = 'xxxxxx' API_KEY = '换成你的apikey' SECRET_KEY = '换成你的SECRET_KEY' client = AipNlp(APP_ID, API_KEY, SECRET_KEY) text = "我还没饭吃" # 调用文本纠错 client.ecnet(text)
这个API当时为了设计一个推荐体系引入经纬度换算地址,这样为数据计算带来极大的方便,而且对于一般人来说文本地址相比经纬度信息更加直观,然后结合Python一个第三方包实现两个地址之间经纬度计算得出相对的距离。
# https://lbsyun.baidu.com/ # 计算校验SN(百度API文档说明需要此步骤) import pandas as pd import numpy as np import warnings import requests import urllib import hashlib import json from geopy.distance import geodesic location = input("输入所在的位置\n") # "广州市天河区" ak = "ak1111" # 参照自己的应用 sk = "sk111111" # 参照自己的应用 url = "http://api.map.baidu.com" query = "/geocoding/v3/?address={0}&output=json&ak={1}&callback=showLocation".format(location, ak) encodedStr = urllib.parse.quote(query, safe="/:=&?#+!$,;'@()*[]") sn = hashlib.md5(urllib.parse.quote_plus(encodedStr + sk).encode()).hexdigest() # 使用requests获取返回的json response = requests.get("{0}{1}&sn={2}".format(url, query, sn)) data1=response.text.replace("showLocation&&showLocation(","").replace(")","") data = json.loads(data1) print(data) lat = data["result"]["location"]["lat"] lon = data["result"]["location"]["lng"] print("纬度: ", lat, " 经度: ", lon) distance=geodesic((lat,lon), (39.98028,116.30495)) print("距离{0}这个位置大概{1}".format(location, distance))
在网上查阅了很多API,前面介绍的几种API,他们携带的请求参数信息相对比较简单,调用实现和基础请求没啥区别,这里找了一个相对而言比较多的请求参数的API,相对而言这种API数据付费API,它的安全性以及具体的实现都相对复杂,但是更适合商用。下面可以简单看看。
import requests import time import hashlib import uuid youdao_url = 'https://openapi.youdao.com/api' # 有道api地址 translate_text = "how are you!" input_text = "" # 当文本长度小于等于20时,取文本 if(len(translate_text) 20): input_text = translate_text[:10] + str(len(translate_text)) + translate_text[-10:] uu_id = uuid.uuid1() now_time = int(time.time()) app_id = '1111111' app_key = '11111111111' sign = hashlib.sha256((app_id + input_text + str(uu_id) + str(now_time) + app_key).encode('utf-8')).hexdigest() # sign生成 data = { 'q':translate_text, # 翻译文本 'from':"en", # 源语言 'to':"zh-CHS", # 翻译语言 'appKey':app_id, # 应用id 'salt':uu_id, # 随机生产的uuid码 'sign':sign, # 签名 'signType':"v3", # 签名类型,固定值 'curtime':now_time, # 秒级时间戳 } r = requests.get(youdao_url, params = data).json() # 获取返回的json()内容 print("翻译后的结果:" + r["translation"][0]) # 获取翻译内容
翻译后的结果:你好!
这个API调用中引用了几个真正商用中的一些为了安全性等设置的验证信息,比如uuid、sign、timestamp,这几个在API调用中也是老生常谈的几个概念,是比较全面的。下面简单介绍一下。
uuid码:UUID是一个128比特的数值,这个数值可以通过一定的算法计算出来。为了提高效率,常用的UUID可缩短至16位。UUID用来识别属性类型,在所有空间和时间上被视为唯一的标识。一般来说,可以保证这个值是真正唯一的任何地方产生的任意一个UUID都不会有相同的值。使用UUID的一个好处是可以为新的服务创建新的标识符。是一种独特的唯一标识符,python 第三方库uuid 提供对应的uuid生成方式,有以下的几种 uuid1(),uuid3(),uuid4(),uuid5()上面采用的是uuid1()生成,还可以使用uuid4()生成。
sign:一般为了防止被恶意抓包,通过数字签名等保证API接口的安全性。为了防止发送的信息被串改,发送方通过将一些字段要素按一定的规则排序后,在转化成密钥,通过加密机制发送,当接收方接受到请求后需要验证该信息是否被篡改过,也需要将对应的字段按照同样的规则生成验签sign,然后在于后台接收到的进行比对,可以发现信息是否被串改过。在上面的例子利用hashlib.sha256()来进行随机产生一段密钥,最后使用.hexdigest()返回最终的密钥。
curtime:引入一个时间戳参数,保证接口仅在一分钟内有效,需要和客户端时间保持一致。避免重复访问。
推荐学习:python视频教程
以上是python中API呼叫的詳解與範例的詳細內容。更多資訊請關注PHP中文網其他相關文章!