Python調(diào)用API接口實(shí)現(xiàn)規(guī)范獲取官方數(shù)據(jù)
爬蟲有個(gè)明顯局限——一旦網(wǎng)頁(yè)結(jié)構(gòu)更新(比如按鈕位置、標(biāo)簽名變化),代碼就會(huì)失效。而很多平臺(tái)會(huì)提供更規(guī)范的數(shù)據(jù)獲取方式:API接口(Application Programming Interface,應(yīng)用程序編程接口)。這篇我們就學(xué)習(xí)“API接口調(diào)用”,用Python對(duì)接公開API(以天氣API、新聞API為例),掌握“構(gòu)造請(qǐng)求、解析響應(yīng)、處理認(rèn)證”的核心邏輯,高效獲取官方數(shù)據(jù),同時(shí)規(guī)避爬蟲的不穩(wěn)定問題。
一、先搞懂:什么是API接口?為什么用它?
1. API接口的本質(zhì)
簡(jiǎn)單說,API是平臺(tái)對(duì)外開放的“數(shù)據(jù)通道”——平臺(tái)將數(shù)據(jù)整理成結(jié)構(gòu)化格式(如JSON),通過接口供開發(fā)者調(diào)用,開發(fā)者不用解析網(wǎng)頁(yè),直接按規(guī)則發(fā)送請(qǐng)求就能拿到干凈數(shù)據(jù)。
舉個(gè)例子:你想獲取北京的天氣,不用爬取天氣網(wǎng)站,直接調(diào)用“高德天氣API”,發(fā)送包含“城市名”的請(qǐng)求,接口會(huì)返回類似這樣的結(jié)構(gòu)化數(shù)據(jù)(JSON格式):
{
"status": "1",
"count": "1",
"info": "OK",
"infocode": "10000",
"lives": [
{
"province": "北京",
"city": "北京市",
"adcode": "110000",
"weather": "晴",
"temperature": "25",
"winddirection": "東北",
"windpower": "2級(jí)",
"humidity": "45",
"reporttime": "2024-06-10 14:00:00"
}
]
}
直接提取lives[0]["weather"]就能拿到“晴”,比爬蟲解析HTML高效得多。
2. API接口的優(yōu)勢(shì)(對(duì)比爬蟲)
| 對(duì)比維度 | 網(wǎng)頁(yè)爬蟲 | API接口調(diào)用 |
|---|---|---|
| 數(shù)據(jù)格式 | 非結(jié)構(gòu)化(HTML),需解析 | 結(jié)構(gòu)化(JSON/XML),直接提取 |
| 穩(wěn)定性 | 依賴網(wǎng)頁(yè)結(jié)構(gòu),易失效 | 平臺(tái)維護(hù),結(jié)構(gòu)穩(wěn)定 |
| 效率 | 需下載完整HTML,較慢 | 只返回目標(biāo)數(shù)據(jù),較快 |
| 合規(guī)性 | 可能違反網(wǎng)站協(xié)議 | 官方授權(quán),合規(guī)安全 |
3. 核心概念:RESTful API與HTTP請(qǐng)求方法
目前主流的API是“RESTful API”,基于HTTP協(xié)議設(shè)計(jì),常用4種請(qǐng)求方法對(duì)應(yīng)不同操作:
- GET:獲取數(shù)據(jù)(最常用,如“獲取天氣”“獲取新聞列表”);
- POST:提交數(shù)據(jù)(如“創(chuàng)建用戶”“提交表單”);
- PUT:更新數(shù)據(jù)(如“修改用戶信息”);
- DELETE:刪除數(shù)據(jù)(如“刪除一條記錄”);
我們?nèi)腴T階段重點(diǎn)掌握GET請(qǐng)求(獲取數(shù)據(jù))。
4. 準(zhǔn)備工作:獲取API Key(接口認(rèn)證)
大部分公開API需要“API Key”(類似鑰匙)驗(yàn)證身份,避免惡意調(diào)用。我們以“高德開放平臺(tái)”為例,申請(qǐng)免費(fèi)天氣API Key:
- 注冊(cè)高德開放平臺(tái)賬號(hào);
- 進(jìn)入“控制臺(tái)”→“應(yīng)用管理”→“創(chuàng)建應(yīng)用”(隨便填名稱,如“Python學(xué)習(xí)”);
- 應(yīng)用創(chuàng)建后,點(diǎn)擊“添加Key”,選擇“Web服務(wù)”,提交后得到API Key(后續(xù)代碼會(huì)用到)。
二、實(shí)戰(zhàn)1:調(diào)用高德天氣API,獲取實(shí)時(shí)天氣
我們先從簡(jiǎn)單的“獲取城市實(shí)時(shí)天氣”入手,掌握API調(diào)用的核心流程:解讀接口文檔→構(gòu)造請(qǐng)求URL→發(fā)送請(qǐng)求→解析JSON響應(yīng)→提取數(shù)據(jù)。
1. 第一步:解讀接口文檔(關(guān)鍵?。?/h3>
調(diào)用API前必須看文檔,明確“請(qǐng)求URL、參數(shù)、響應(yīng)格式”。高德實(shí)時(shí)天氣API文檔地址:https://lbs.amap.com/api/webservice/guide/api/weatherinfo/
核心信息整理:
請(qǐng)求URL:https://restapi.amap.com/v3/weather/weatherInfo
必選參數(shù):
key:你的API Key(身份驗(yàn)證);city:城市編碼(如北京110000,可查“高德城市編碼表”,或用城市名拼音);
可選參數(shù):
extensions:返回類型(base返回實(shí)時(shí)天氣,all返回預(yù)報(bào),默認(rèn)base);
響應(yīng)格式:JSON(結(jié)構(gòu)化數(shù)據(jù))。
2. 第二步:代碼實(shí)現(xiàn)(獲取實(shí)時(shí)天氣)
import requests
import logging
import json
# 1. 配置日志(記錄請(qǐng)求過程和錯(cuò)誤)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
)
def get_real_time_weather(api_key, city):
"""
調(diào)用高德天氣API,獲取指定城市的實(shí)時(shí)天氣
參數(shù):
api_key:高德開放平臺(tái)的API Key
city:城市編碼(如110000)或城市名拼音(如beijing)
返回:
成功返回天氣字典(含天氣、溫度、風(fēng)向等),失敗返回None
"""
try:
logging.info(f"開始獲取{city}的實(shí)時(shí)天氣")
# 2. 構(gòu)造請(qǐng)求參數(shù)(必選參數(shù)+可選參數(shù))
params = {
"key": api_key,
"city": city,
"extensions": "base" # base=實(shí)時(shí)天氣,all=預(yù)報(bào)+實(shí)時(shí)
}
# 3. 發(fā)送GET請(qǐng)求(API接口常用GET方法獲取數(shù)據(jù))
api_url = "https://restapi.amap.com/v3/weather/weatherInfo"
response = requests.get(
url=api_url,
params=params, # params參數(shù)會(huì)自動(dòng)拼接到URL后(如?key=xxx&city=110000)
timeout=10 # 超時(shí)時(shí)間10秒,避免長(zhǎng)時(shí)間等待
)
# 4. 檢查請(qǐng)求是否成功(HTTP狀態(tài)碼200表示正常)
response.raise_for_status() # 若狀態(tài)碼非200(如400、403),拋出HTTPError
# 5. 解析JSON響應(yīng)(將JSON字符串轉(zhuǎn)為Python字典)
response_data = response.json() # requests內(nèi)置JSON解析方法,比json.loads更方便
logging.debug(f"API響應(yīng)原始數(shù)據(jù):{json.dumps(response_data, ensure_ascii=False, indent=2)}")
# 6. 檢查API業(yè)務(wù)狀態(tài)(非HTTP狀態(tài)碼,是接口自定義的狀態(tài))
# 高德API中,status=1表示成功,0表示失敗,infocode返回錯(cuò)誤碼
if response_data.get("status") != "1":
error_info = response_data.get("info", "未知錯(cuò)誤")
error_code = response_data.get("infocode", "未知錯(cuò)誤碼")
logging.error(f"API業(yè)務(wù)失敗:{error_info}(錯(cuò)誤碼:{error_code})")
print(f"? 天氣獲取失?。簕error_info}(錯(cuò)誤碼:{error_code})")
return None
# 7. 提取核心天氣數(shù)據(jù)(從響應(yīng)中找到需要的字段)
lives = response_data.get("lives", [])
if not lives:
logging.error("API響應(yīng)中未找到天氣數(shù)據(jù)(lives字段為空)")
print("? 天氣獲取失?。何凑业侥繕?biāo)城市的天氣數(shù)據(jù)")
return None
# 整理需要的字段(去掉冗余信息)
weather_info = {
"省份": lives[0].get("province", "未知"),
"城市": lives[0].get("city", "未知"),
"天氣": lives[0].get("weather", "未知"),
"溫度(℃)": lives[0].get("temperature", "未知"),
"風(fēng)向": lives[0].get("winddirection", "未知"),
"風(fēng)力": lives[0].get("windpower", "未知"),
"濕度(%)": lives[0].get("humidity", "未知"),
"更新時(shí)間": lives[0].get("reporttime", "未知")
}
logging.info(f"成功獲取{weather_info['城市']}的實(shí)時(shí)天氣")
return weather_info
except requests.exceptions.HTTPError as e:
logging.error(f"HTTP請(qǐng)求錯(cuò)誤:{e}")
print(f"? HTTP錯(cuò)誤:{e}(可能API Key無效或URL錯(cuò)誤)")
return None
except requests.exceptions.Timeout as e:
logging.error(f"請(qǐng)求超時(shí):{e}")
print(f"? 超時(shí)錯(cuò)誤:{e}(請(qǐng)檢查網(wǎng)絡(luò)連接)")
return None
except Exception as e:
logging.error(f"天氣獲取未知錯(cuò)誤:{e}", exc_info=True)
print(f"? 未知錯(cuò)誤:{e}(請(qǐng)查看日志獲取詳情)")
return None
# 測(cè)試:獲取北京的實(shí)時(shí)天氣(替換為你的API Key)
if __name__ == "__main__":
# ?。。√鎿Q為你自己的高德API Key(從控制臺(tái)獲?。?
MY_AMAP_API_KEY = "你的API Key"
city_code = "110000" # 北京的城市編碼,也可嘗試"shanghai"(上海拼音)
weather_data = get_real_time_weather(MY_AMAP_API_KEY, city_code)
if weather_data:
print("\n" + "="*50)
print("?? 實(shí)時(shí)天氣信息")
print("="*50)
for key, value in weather_data.items():
print(f"{key}:{value}")
print("="*50)
3. 運(yùn)行結(jié)果(示例)
若API Key有效且網(wǎng)絡(luò)正常,會(huì)輸出類似:
==================================================
?? 實(shí)時(shí)天氣信息
==================================================
省份:北京
城市:北京市
天氣:晴
溫度(℃):25
風(fēng)向:東北
風(fēng)力:2級(jí)
濕度(%):45
更新時(shí)間:2024-06-10 14:00:00
==================================================
三、實(shí)戰(zhàn)2:調(diào)用新聞API,獲取熱點(diǎn)新聞列表
我們?cè)賹?shí)戰(zhàn)一個(gè)“獲取新聞列表”的API,學(xué)習(xí)“分頁(yè)獲取數(shù)據(jù)”(一次獲取多頁(yè)新聞),并將結(jié)果保存到Excel,銜接第十篇的數(shù)據(jù)處理知識(shí)。
1. 準(zhǔn)備:選擇公開新聞API
我們用“聚合數(shù)據(jù)”的免費(fèi)新聞API(需注冊(cè)申請(qǐng)API Key):
注冊(cè)聚合數(shù)據(jù)賬號(hào)(https://www.juhe.cn/);
搜索“新聞?lì)^條”API,進(jìn)入詳情頁(yè)點(diǎn)擊“申請(qǐng)數(shù)據(jù)”,獲取API Key;
查看接口文檔,核心信息:
- 請(qǐng)求URL:
http://v.juhe.cn/toutiao/index - 必選參數(shù):
key(你的API Key)、type(新聞?lì)愋?,?code>top=頭條,shehui=社會(huì)); - 可選參數(shù):
page(頁(yè)碼,默認(rèn)1)、page_size(每頁(yè)條數(shù),默認(rèn)20); - 響應(yīng)格式:JSON。
2. 代碼實(shí)現(xiàn)(獲取新聞+保存Excel)
import pandas as pd
from datetime import datetime
def get_news_list(api_key, news_type="top", page=1, page_size=20):
"""
調(diào)用聚合新聞API,獲取指定類型的新聞列表(支持分頁(yè))
參數(shù):
api_key:聚合數(shù)據(jù)的API Key
news_type:新聞?lì)愋停╰op=頭條,shehui=社會(huì),guonei=國(guó)內(nèi),guoji=國(guó)際)
page:頁(yè)碼(默認(rèn)1)
page_size:每頁(yè)條數(shù)(默認(rèn)20,最大不超過100)
返回:
成功返回新聞列表(每個(gè)元素為字典),失敗返回None
"""
try:
logging.info(f"開始獲取{news_type}類型新聞(第{page}頁(yè),每頁(yè){page_size}條)")
# 構(gòu)造請(qǐng)求參數(shù)
params = {
"key": api_key,
"type": news_type,
"page": page,
"page_size": page_size
}
# 發(fā)送GET請(qǐng)求
api_url = "http://v.juhe.cn/toutiao/index"
response = requests.get(api_url, params=params, timeout=10)
response.raise_for_status()
# 解析JSON響應(yīng)
response_data = response.json()
logging.debug(f"新聞API響應(yīng)(第{page}頁(yè)):{json.dumps(response_data, ensure_ascii=False, indent=2)}")
# 檢查API業(yè)務(wù)狀態(tài)(聚合API中,error_code=0表示成功)
if response_data.get("error_code") != 0:
error_info = response_data.get("reason", "未知錯(cuò)誤")
logging.error(f"新聞API業(yè)務(wù)失?。簕error_info}(錯(cuò)誤碼:{response_data.get('error_code')})")
print(f"? 新聞獲取失?。簕error_info}")
return None
# 提取新聞列表(response_data["result"]["data"]是新聞數(shù)據(jù))
news_list = response_data.get("result", {}).get("data", [])
if not news_list:
logging.warning(f"第{page}頁(yè)未獲取到新聞數(shù)據(jù)")
print(f"?? 第{page}頁(yè)未找到新聞數(shù)據(jù)")
return []
# 整理新聞字段(去掉冗余字段,保留核心信息)
cleaned_news = []
for news in news_list:
cleaned_news.append({
"新聞標(biāo)題": news.get("title", "未知"),
"新聞來源": news.get("source", "未知"),
"發(fā)布時(shí)間": news.get("date", "未知"),
"新聞鏈接": news.get("url", "未知"),
"是否熱點(diǎn)": "是" if news.get("is_hot", 0) == 1 else "否",
"爬取時(shí)間": datetime.now().strftime("%Y-%m-%d %H:%M:%S") # 記錄爬取時(shí)間
})
logging.info(f"成功獲取第{page}頁(yè)新聞,共{len(cleaned_news)}條")
return cleaned_news
except Exception as e:
logging.error(f"新聞獲取錯(cuò)誤(第{page}頁(yè)):{e}", exc_info=True)
print(f"? 第{page}頁(yè)新聞獲取失?。簕e}")
return None
def save_news_to_excel(news_list, excel_path="熱點(diǎn)新聞列表.xlsx"):
"""將新聞列表保存到Excel文件"""
if not news_list:
logging.warning("無新聞數(shù)據(jù)可保存")
print("?? 無新聞數(shù)據(jù),無需保存")
return False
try:
logging.info(f"開始將新聞數(shù)據(jù)保存到Excel:{excel_path}")
# 轉(zhuǎn)換為DataFrame
df = pd.DataFrame(news_list)
# 保存到Excel(index=False:不保存行索引)
df.to_excel(excel_path, index=False, engine="openpyxl")
logging.info(f"成功保存{len(df)}條新聞到Excel:{excel_path}")
print(f"\n? 新聞數(shù)據(jù)已保存到:{excel_path}(共{len(df)}條)")
return True
except Exception as e:
logging.error(f"新聞保存Excel失?。簕e}", exc_info=True)
print(f"? 保存Excel失敗:{e}")
return False
# 完整流程:獲取多頁(yè)新聞+保存Excel
if __name__ == "__main__":
print("="*60)
print("?? 新聞API調(diào)用工具(支持分頁(yè)獲?。?)
print("="*60)
# ?。。√鎿Q為你自己的聚合數(shù)據(jù)API Key
MY_JUHE_API_KEY = "你的API Key"
news_type = "top" # 新聞?lì)愋停簍op=頭條,shehui=社會(huì)
total_pages = 2 # 計(jì)劃獲取2頁(yè)新聞
# 1. 循環(huán)獲取多頁(yè)新聞
all_news = []
for page in range(1, total_pages + 1):
page_news = get_news_list(
api_key=MY_JUHE_API_KEY,
news_type=news_type,
page=page,
page_size=10 # 每頁(yè)10條,2頁(yè)共20條
)
if page_news is None:
continue # 失敗則跳過該頁(yè)
all_news.extend(page_news) # 合并多頁(yè)數(shù)據(jù)
# 延遲1秒,避免頻繁請(qǐng)求被限制
import time
time.sleep(1)
# 2. 保存到Excel
if all_news:
save_news_to_excel(all_news)
print("\n?? 程序執(zhí)行完畢!")
3. 運(yùn)行結(jié)果
項(xiàng)目文件夾中會(huì)生成“熱點(diǎn)新聞列表.xlsx”,打開后可看到包含“新聞標(biāo)題、來源、發(fā)布時(shí)間”等字段的結(jié)構(gòu)化數(shù)據(jù),可直接用于后續(xù)分析(如統(tǒng)計(jì)新聞來源分布)。
四、API調(diào)用常見問題與解決方案
在實(shí)戰(zhàn)中可能遇到各種問題,這里整理3個(gè)高頻問題及解決方法:
1. 問題1:API Key無效(錯(cuò)誤碼401/403)
原因:API Key填寫錯(cuò)誤、未激活、超過調(diào)用次數(shù)限制;
解決:
- 檢查API Key是否與申請(qǐng)平臺(tái)一致(如高德的Key不能用于聚合數(shù)據(jù));
- 登錄平臺(tái)控制臺(tái),確認(rèn)Key已激活,且調(diào)用次數(shù)未用完;
- 若Key過期,重新申請(qǐng)新Key。
2. 問題2:請(qǐng)求參數(shù)錯(cuò)誤(錯(cuò)誤碼400)
原因:缺少必選參數(shù)、參數(shù)格式錯(cuò)誤(如城市編碼填成中文);
解決:
- 對(duì)照接口文檔,確認(rèn)所有必選參數(shù)已傳入(如
key、city); - 檢查參數(shù)格式(如頁(yè)碼必須是整數(shù),城市編碼需符合平臺(tái)規(guī)范);
- 打印
response.text查看原始響應(yīng),平臺(tái)通常會(huì)返回具體錯(cuò)誤描述(如“city參數(shù)格式錯(cuò)誤”)。
3. 問題3:響應(yīng)數(shù)據(jù)解析失敗(KeyError)
原因:API響應(yīng)結(jié)構(gòu)與預(yù)期不符(如字段名變化);
解決:
- 打印
response.json()查看完整響應(yīng),確認(rèn)字段名是否正確(如預(yù)期lives字段,實(shí)際是weather); - 用
dict.get()方法獲取字段(如data.get("lives", [])),避免直接用data["lives"]導(dǎo)致KeyError; - 檢查接口文檔是否有更新,確認(rèn)最新的響應(yīng)結(jié)構(gòu)。
總結(jié)
這篇我們掌握了API接口調(diào)用的核心技能,串聯(lián)了前序多個(gè)知識(shí)點(diǎn):
- 核心流程:解讀文檔→構(gòu)造參數(shù)→發(fā)送請(qǐng)求→解析JSON→提取數(shù)據(jù),相比爬蟲更規(guī)范高效;
- 實(shí)用技能:處理API認(rèn)證(API Key)、分頁(yè)獲取數(shù)據(jù)、錯(cuò)誤碼判斷,應(yīng)對(duì)實(shí)戰(zhàn)常見問題;
到此這篇關(guān)于Python調(diào)用API接口實(shí)現(xiàn)規(guī)范獲取官方數(shù)據(jù)的文章就介紹到這了,更多相關(guān)Python調(diào)用API接口獲取數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 使用Python的requests庫(kù)調(diào)用API接口的詳細(xì)步驟
- Python使用Flask調(diào)用API接口的方法
- Python調(diào)用訊飛語音合成API接口來實(shí)現(xiàn)文字轉(zhuǎn)語音
- Python調(diào)用API接口實(shí)現(xiàn)人臉識(shí)別
- Python調(diào)用REST API接口的幾種方式匯總
- python 調(diào)用API接口 獲取和解析 Json數(shù)據(jù)
- python調(diào)用API接口實(shí)現(xiàn)登陸短信驗(yàn)證
- python 調(diào)用有道api接口的方法
相關(guān)文章
Flaks基礎(chǔ)之在URL中添加變量的實(shí)現(xiàn)詳解
這篇文章主要介紹了在python開發(fā)中,F(xiàn)laks框架之上在URL鏈接中添加變量的實(shí)現(xiàn)方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-09-09
從入門到實(shí)戰(zhàn)詳解Python Streamlit如何快速將腳本變成交互式網(wǎng)頁(yè)應(yīng)用
這篇文章主要為大家詳細(xì)介紹了如何使用Python Streamlit實(shí)現(xiàn)快速將腳本變成交互式網(wǎng)頁(yè)應(yīng)用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2025-12-12
Python設(shè)計(jì)實(shí)現(xiàn)的計(jì)算器功能完整實(shí)例
這篇文章主要介紹了Python設(shè)計(jì)實(shí)現(xiàn)的計(jì)算器功能,結(jié)合完整實(shí)例形式分析了Python3.5實(shí)現(xiàn)計(jì)算器功能的正則、字符串及數(shù)值運(yùn)算等相關(guān)操作技巧,需要的朋友可以參考下2017-08-08
Python有關(guān)Unicode UTF-8 GBK編碼問題詳解
本文主要介紹了Python有關(guān)Unicode UTF-8 GBK編碼問題詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
python 實(shí)現(xiàn)二維字典的鍵值合并等函數(shù)
今天小編就為大家分享一篇python 實(shí)現(xiàn)二維字典的鍵值合并等函數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-12-12
django template 模板渲染的實(shí)現(xiàn)
Django 的模板系統(tǒng)旨在使設(shè)計(jì)人員能夠編寫 HTML,同時(shí)以一種安全和靈活的方式動(dòng)態(tài)顯示數(shù)據(jù),本文主要介紹了django template模板渲染的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2025-01-01
Python實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Python實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01

