开发者

Python调用API接口实现规范获取官方数据

目录
  • 一、先搞懂:什么是API接口?为什么用它?
    • 1. API接口的本质
    • 2. API接口的优势(对比爬虫)
    • 3. 核心概念:RESTful API与HTTP请求方法
    • 4. 准备工作:获取API Key(接口认证)
  • 二、实战1:调用高德天气API,获取实时天气
    • 1. 第一步:解读接口文档(关键!)
    • 2. 第二步:代码实现(获取实时天气)
    • 3. 运行结果(示例)
  • 三、实战2:调用新闻API,获取热点新闻列表
    • 1. 准备:选择公开新闻API
    • 2. 代码实现(获取新闻+保存Excel)
    • 3. 运行结果
  • 四、API调用常见问题与解决方案
    • 1. 问题1:API Key无效(错误码401/403)
    • 2. 问题2:请求参数错误(错误码400)
    • 3. 问题3:响应数据解析失败(KeyError)
  • 总结

    爬虫有个明显局限——一旦网页结构更新(比如按钮位置、标签名变化),代码就会失效。而很多平台会提供更规范的数据获取方式:API接口(Application Programming Interface,应用程序编程接口)。这篇我们就学习“API接口调用”,用python对接公开API(以天气API、新闻API为例),掌握“构造请求、解析响应、处理认证”的核心逻辑,高效获取官方数据,同时规避爬虫的不稳定问题。

    一、先搞懂:什么是API接口?为什么用它?

    1. API接口的本质

    简单说,API是平台对外开放的“数据通道”——平台将数据整理成结构化格式(如jsON),通过接口供开发者调用,开发者不用解析网页,直接按规则发送请求就能拿到干净数据。

    举个例子:你想获取北京的天气,不用爬取天气网站,直接调用“高德天气API”,发送包含“城市名”的请求,接口会返回类似这样的结构化数据(JSON格式):

    {
      "status": "1",
      "count": "1",
      "info"编程客栈: "OK",
      "infocode": "10000",
      "lives": [
        {
          "province": "北京",
          "city": "北京市",
          "adcode": "110000",
          "weather": "晴",
          "temperature": "25",
          "winddirection": "东北",
          "windpower": "2级",
          "humidity": "45",
          "reporttime": "2024-06-10 14:00:00"
        }
      ]
    }
    

    直接提取lives[0]["weather"]就能拿到“晴”,比爬虫解析html高效得多。

    2. API接口的优势(对比爬虫)

    对比维度网页爬虫API接口调用
    数据格式非结构化(HTML),需解析结构化(JSON/XML),直接提取
    稳定性依赖网页结构,易失效平台维护,结构稳定
    效率需下载完整HTML,较慢只返回目标数据,较快
    合规性可能违反网站协议官方授权,合规安全

    3. 核心概念:RESTful API与HTTP请求方法

    目前主流的API是“RESTful API”,基于HTTP协议设计,常用4种请求方法对应不同操作:

    • GET:获取数据(最常用,如“获取天气”“获取新闻列表”);
    • POST:提交数据(如“创建用户”“提交表单”);
    • PUT:更新数据(如“修改用户信息”);
    • DELETE:删除数据(如“删除一条记录”);

      我们入门阶段重点掌握GET请求(获取数据)。

    4. 准备工作:获取API Key(接口认证)

    大部分公开API需要“API Key”(类似钥匙)验证身份,避免恶意调用。我们以“高德开放平台”为例,申请免费天气API Key:

    • 注册高德开放平台账号;
    • 进入“控制台”→“应用管理”→“创建应用”(随便填名称,如“Python学习”);
    • 应用创建后,点击“添加Key”,选择“Web服务”,提交后得到API Key(后续代码会用到)。

    二、实战1:调用高德天气API,获取实时天气

    我们先从简单的“获取城市实时天气”入手,掌握API调用的核心流程:解读接口文档→构造请求URL→发送请求→解析JSON响应→提取数据

    1. 第一步:解读接口文档(关键!)

    调用API前必须看文档,明确“请求URL、参数、响应格式”。高德实时天气API文档地址:https://lbs.amap.com/api/webservice/guide/api/weatherinfo/

    核心信息整理:

    请求URLhttps://restapi.amap.com/v3/weather/weatherInfo

    必选参数

    • key:你的API Key(身份验证);
    • city:城市编码(如北京110000,可查“高德城市编码表”,或用城市名拼音);

    可选参数

    extensions:返回类型(base返回实时天气,all返回预报,默认base);

    响应格式:JSON(结构化数据)。

    2. 第二步:代码实现(获取实时天气)

    import requests
    import logging
    import json
    
    # 1. 配置日志(记录请求过程和错误)
    logging.basicConfig(
        level=logging.INFO,
        format="%(asctime)s - %(levelname)s - %(message)s"
    )
    
    def get_real_time_weather(api_key, city):
        """
        调用高德天气API,获取指定城市的实时天气
        参数:
            api_key:高德开放平台的API Key
            city:城市编码(如110000)或城市名拼音(如beijing)
        返回:
            成功返回天气字典(含天气、温度、风向等),失败返回None
        """
        try:
            logging.info(f"开始获取{city}的实时天气")
            
            # 2. 构造请求参数(必选参数+可选参数)
            params = {
                "key": api_key,
                "city": city,
                "extensions": "base"  # base=实时天气,all=预报+实时
            }
            
            # 3. 发送GET请求(API接口常用GET方法获取数据)
            api_url = "https://restapi.amap.com/v3/weather/weatherInfo"
            response = requests.get(
                url=api_url,
                params=params,  # params参数会自动拼接到URL后(如?key=xxx&city=110000)
                timeout=10  # 超时时间10秒,避免长时间等待
            )
            
            # 4. 检查请求是否成功(HTTP状态码200表示正常)
            response.raise_for_status()  # 若状态码非200(如400、403),抛出HTTPError
            
            # 5. 解析JSON响应(将JSON字符串转为Python字典)
            response_data = response.json()  # requests内置JSON解析方法,比json.loads更方便
            logging.debug(f"API响应原始数据:{json.dumps(response_data, ensure_ascii=False, indent=2)}")
            
            # 6. 检查API业务状态(非HTTP状态码,是接口自定义的状态)
            # 高德API中,status=1表示成功,0表示失败,infocode返回错误码
            if response_data.get("status") != "1":
                error_info = response_data.get("info", "未知错误")
                error_code = response_data.get("infocode", "未知错误码")
                logging.error(f"API业务失败:{error_info}(错误码:{error_code})")
                print(f"❌ 天气获取失败:{error_info}(错误码:{error_code})")
                return None
            
            # 7. 提取核心天气数据(从响应中找到需要的字段)
            lives = response_data.get("lives", [])
            if not lives:
                logging.error("API响应中未找到天气数据(lives字段为空)")
                print("❌ 天气获取失败:未找到目标城市的天气数据")
                return None
            
            # 整理需要的字段(去掉冗余信息)
            weather_info = {
                "省份": lives[0].get("province", "未知"),
                "城市": lives[0].get("city", "未知"),
                "天气": lives[0].get("weather", "未知"),
                "温度(℃)": lives[0].get("temperature", "未知"),
                "风向": lives[0].get("winddirection", "未知"),
                "风力": lives[0].get("windpower", "未知"),
                "湿度(%)": lives[0].get("humidity", "未知"),
                "更新时间": lives[0].get("reporttime", "未知")
            }
            
            logging.info(f"成功获取{weather_info['城市']}的实时天气")
            return weather_info
        
        except requests.exceptions.HTTPError as e:
            logging.error(f"HTTP请求错误:{e}")
            print(f"❌ HTTP错误:{e}(可能API Key无效或URL错误)")
            return None
        
        except requests.exceptions.Timeout as e:
            logging.error(f"请求超时:{e}")
            print(f"❌ 超时错误:{e}(请检查网络连接)")
            return None
        
        except Exception as e:
            logging.error(f"天气获取未知错误:{e}", exc_info=True)
            print(f"❌ 未知错误:{e}(请查看日志获取详情)")
            return None
    
    # 测试:获取北京的实时天气(替换为你的API Key)
    if __name__ == "__main__":
        # !!!替换为你自己的高德API Key(从控制台获取)
        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(" 实时天气信息")
            print("="*50)
            for key, value in weather_data.items():
                print(f"{key}:{value}")
            print("="*50)
    

    3. 运行结果(示例)

    若API Key有效且网络正常,会输出类似:

    ==================================================

    实时天气信息

    ==================================================

    省份:北京

    城市:北京市

    天气:晴

    温度(℃):25

    风向:东北

    风力:2级

    湿度(%):45

    更新时间:2024-06-10 14:00:00

    ==================================================

    三、实战2:调用新闻API,获取热点新闻列表

    我们再实战一个“获取新闻列表”的API,学习“分页获取数据”(一次获取多页新闻),并将结果保存到Excel,衔接第十篇的数据处理知识。

    1. 准备:选择公开新闻API

    我们用“聚合数据”的免费新闻API(需注册申请API Key):

    注册聚合数据账号(https://www.juhe.cn/);

    搜索“新闻头条”API,进入详情页点击“申请数据”,获取API Key;

    查看接口文档,核心信息:

    • 请求URLhttp://v.juhe.cn/toutiao/index
    • 必选参数key(你的API Key)、type(新闻类型,如top=头条,shehui=社会);
    • 可选参数page(页码,默认1)、page_size(每页条数,默认20);
    • 响应格式:JSON。

    2. 代码实现(获取新闻+保存Excel)

    import pandas as pd
    from datetime import datetime
    
    def get_news_list(api_key, news_type="top", page=1, page_size=20):
        """
        调用聚合新闻API,获取指定类型的新闻列表(支持分页)
        参数:
            api_key:聚合数据的API Key
            news_type:新闻类型(top=头条,shehui=社会,guonei=国内,guoji=国际)
            page:页码(默认1)
            page_size:每页条android数(默认20,最大不超过100)
        返回:
            成功返回新闻列表(每个元素为字典),失败返回None
        """
        try:
            logging.info(f"开始获取{news_type}类型新闻(第{page}页,每页{page_size}条)")
            
            # 构造请求参数
            params = {
                "key": api_key,
                "type": news_type,
                "page": page,
                "page_size": page_size
            }
            
            # 发送GET请求
            api_url = "http://v.juhe.cn/toutiao/index"
            response = requests.get(api_url, params=params, timeout=10)
            response.raise_for_status()
            
            # 解析JSON响应
            response_data = response.json()
            logging.debug(f"新闻API响应(第{page}页):{json.dumps(response_data, ensure_ascii=False, indent=2)}")
            
            # 检查API业务状态(聚合API中,error_code=0表示js成功)
            if response_data.get("error_code") != 0:
                error_info = response_data.get("reason", "未知错误")
                logging.error(f"新闻API业务失败:{error_info}(错误码:{response_data.get('error_code')})")
                print(f"❌ 新闻获取失败:{error_info}")
                return None
            
            # 提取新闻列表(response_data["result"]["data"]是新闻数据)
            news_list = response_data.get("result", {}).get("data", [])
            if not news_list:
                logging.warning(f"第{page}页未获取到新闻数据")
                print(f"⚠️  第{page}页未找到新闻数据")
                return []
            
            # 整理新闻字段(去掉冗余字段,保留核心信息)
            cleaned_news = []
            for news in news_list:
                cleaned_news.append({
                    "新闻标题": news.get("title", "未知"),
                    "新闻来源": news.get("source", "未知"),
                    "发布时间": news.get("date", "未知"),
                    "新闻链接": news.get("url", "未知"),
                    "是否热点": "是" if news.get("is_hot", 0) == 1 else "否",
                    "爬取时间": datetime.now().strftime("%Y-%m-%d %H:%M:%S")  # 记录爬取时间
                })
            
            pythonlogging.info(f"成功获取第{page}页新闻,共{len(cleaned_news)}条")
            return cleaned_news
        
        except Exception as e:
            logging.error(f"新闻获取错误(第{page}页):{e}", exc_info=True)
            print(f"❌ 第{page}页新闻获取失败:{e}")
            return None
    
    def save_news_to_excel(news_list, excel_path="热点新闻列表.xlsx"):
        """将新闻列表保存到Excel文件"""
        if not news_list:
            logging.warning("无新闻数据可保存")
            print("⚠️  无新闻数据,无需保存")
            return False
        
        try:
            logging.info(f"开始将新闻数据保存到Excel:{excel_path}")
            # 转换为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✅ 新闻数据已保存到:{excel_path}(共{len(df)}条)")
            return True
        except Exception as e:
            logging.error(f"新闻保存Excel失败:{e}", exc_info=True)
            print(f"❌ 保存Excel失败:{e}")
            return False
    
    # 完整流程:获取多页新闻+保存Excel
    if __name__ == "__main__":
        print("="*60)
        print(" 新闻API调用工具(支持分页获取)")
        print("="*60)
        
        # !!!替换为你自己的聚合数据API Key
        MY_JUHE_API_KEY = "你的jsAPI Key"
        news_type = "top"  # 新闻类型:top=头条,shehui=社会
        total_pages = 2    # 计划获取2页新闻
        
        # 1. 循环获取多页新闻
        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  # 每页10条,2页共20条
            )
            if page_news is None:
                continue  # 失败则跳过该页
            all_news.extend(page_news)  # 合并多页数据
            # 延迟1秒,避免频繁请求被限制
            import time
            time.sleep(1)
        
        # 2. 保存到Excel
        if all_news:
            save_news_to_excel(all_news)
        
        print("\n 程序执行完毕!")
    

    3. 运行结果

    项目文件夹中会生成“热点新闻列表.xlsx”,打开后可看到包含“新闻标题、来源、发布时间”等字段的结构化数据,可直接用于后续分析(如统计新闻来源分布)。

    四、API调用常见问题与解决方案

    在实战中可能遇到各种问题,这里整理3个高频问题及解决方法:

    1. 问题1:API Key无效(错误码401/403)

    原因:API Key填写错误、未激活、超过调用次数限制;

    解决:

    • 检查API Key是否与申请平台一致(如高德的Key不能用于聚合数据);
    • 登录平台控制台,确认Key已激活,且调用次数未用完;
    • 若Key过期,重新申请新Key。

    2. 问题2:请求参数错误(错误码400)

    原因:缺少必选参数、参数格式错误(如城市编码填成中文);

    解决:

    • 对照接口文档,确认所有必选参数已传入(如keycity);
    • 检查参数格式(如页码必须是整数,城市编码需符合平台规范);
    • 打印response.text查看原始响应,平台通常会返回具体错误描述(如“city参数格式错误”)。

    3. 问题3:响应数据解析失败(KeyError)

    原因:API响应结构与预期不符(如字段名变化);

    解决:

    • 打印response.json()查看完整响应,确认字段名是否正确(如预期lives字段,实际是weather);
    • dict.get()方法获取字段(如data.get("lives", [])),避免直接用data["lives"]导致KeyError;
    • 检查接口文档是否有更新,确认最新的响应结构。

    总结

    这篇我们掌握了API接口调用的核心技能,串联了前序多个知识点:

    • 核心流程:解读文档→构造参数→发送请求→解析JSON→提取数据,相比爬虫更规范高效;
    • 实用技能:处理API认证(API Key)、分页获取数据、错误码判断,应对实战常见问题;

    到此这篇关于Python调用API接口实现规范获取官方数据的文章就介绍到这了,更多相关Python调用API接口获取数据内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜