Python 自动化实战:API 自动化——调用50+免费API

PythonAPI自动化独立开发

为什么你应该优先用 API 而不是爬虫?

上篇文章讲了 Web Scraping,结尾我留了一句话:如果网站有公开 API,优先用 API 而不是爬页面

这不是敷衍。我做独立开发这几年,在 API 和爬虫之间来回横跳过太多次,教训深刻。

说一个真实例子:2024 年我写了个币圈信息聚合器,一开始爬了三个交易所的页面。每个页面结构不一样,写解析逻辑就花了两天。上线两周后,其中一家改了 CSS class 名,数据全挂了。连夜修兼容,刚修好,另一家加了 Cloudflare 盾。那一刻我真的想砸键盘。

后来发现这些交易所都有公开 API,免费,还带文档。切过去只花了半天,之后再也没挂过。

API 和爬虫的核心区别:

API爬虫
稳定性契约保证,极少变动随时会挂
数据结构直接返回 JSON需要自己解析 HTML
反爬风险
速度快(几十ms)慢(几百ms以上)
上手门槛需要读文档需要懂 HTML/CSS 选择器

这篇文章教你用 Python 调动 50+ 免费 API,附带完整代码。更重要的是,教你建立一套通用的 API 调用框架——以后碰到任何新 API,10 分钟内就能接上。

API 调用的通用流程

API 调用流程图

不管什么 API,核心就是上面这个流程。新手最容易卡在第三步"读文档"直接跳过——拿到 API key 就开始瞎试。我吃过这个亏,所以多说一句:花 5 分钟读文档比调试 2 小时划算一万倍

基础篇:requests 三板斧

Python 调 API 的核心库就一个——requests。不需要装第三方 SDK,标准 HTTP 库足够覆盖 95% 的场景。

pip install requests

三个最常用的模式:

import requests

# 1. GET 请求(拿数据)
resp = requests.get(
    "https://api.example.com/data",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    params={"page": 1, "limit": 20}  # 查询参数
)

# 2. POST 请求(提交数据)
resp = requests.post(
    "https://api.example.com/create",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={"name": "test", "value": 42}  # JSON body
)

# 3. 解析响应
if resp.status_code == 200:
    data = resp.json()  # 直接拿到 dict
    print(data["results"])
else:
    print(f"请求失败: {resp.status_code} - {resp.text}")

就这三板斧。GET 拿数据,POST 发数据,resp.json() 解析。剩下全是业务逻辑。

实战一:天气 API(无需注册,零门槛)

Open-Meteo 是我最喜欢的免费 API——不需要注册、不需要 API Key、不限调用次数。独立开发者做天气类小工具的首选。

import requests

def get_weather(lat, lon):
    """获取指定坐标的7天天气预报"""
    url = "https://api.open-meteo.com/v1/forecast"
    params = {
        "latitude": lat,
        "longitude": lon,
        "daily": ["temperature_2m_max", "temperature_2m_min",
                   "precipitation_sum", "weathercode"],
        "timezone": "Asia/Shanghai",
        "forecast_days": 7
    }
    resp = requests.get(url, params=params)
    data = resp.json()

    print(f"📍 坐标 ({lat}, {lon}) 未来7天预报:")
    for i, date in enumerate(data["daily"]["time"]):
        high = data["daily"]["temperature_2m_max"][i]
        low = data["daily"]["temperature_2m_min"][i]
        rain = data["daily"]["precipitation_sum"][i]
        print(f"  {date} | {low}°C ~ {high}°C | 降水 {rain}mm")

# 上海坐标
get_weather(31.23, 121.47)

输出:

📍 坐标 (31.23, 121.47) 未来7天预报:
  2026-06-24 | 23°C ~ 31°C | 降水 0.0mm
  2026-06-25 | 24°C ~ 33°C | 降水 2.5mm
  ...

这个 API 还支持历史天气、空气质量、海洋数据。URL 拼参数就行,不用看半天文档。

实战二:汇率 API(同样是零门槛)

做过多币种定价的产品,一定需要实时汇率。Frankfurter 基于欧洲央行数据,免费,无需注册。

import requests
from datetime import datetime

def convert_currency(amount, from_currency, to_currency):
    """实时汇率转换"""
    url = "https://api.frankfurter.app/latest"
    params = {
        "amount": amount,
        "from": from_currency,
        "to": to_currency
    }
    resp = requests.get(url, params=params)
    data = resp.json()

    rate = data["rates"][to_currency]
    result = data["rates"][to_currency]  # amount * rate 已在响应中
    print(f"💱 {amount} {from_currency} = {result} {to_currency}")
    print(f"   汇率: 1 {from_currency} = {rate} {to_currency}")
    return result

# 100 美元换人民币
convert_currency(100, "USD", "CNY")

# 查看所有支持币种
def list_currencies():
    resp = requests.get("https://api.frankfurter.app/currencies")
    currencies = resp.json()
    print(f"支持 {len(currencies)} 种货币:")
    for code, name in list(currencies.items())[:10]:
        print(f"  {code}: {name}")

list_currencies()

这个 API 还支持历史汇率:/2025-01-01?from=USD&to=CNY 能查到任意日期的汇率。做财务报表或价格分析的时候特别有用。

实战三:GitHub API(开发者必备)

GitHub REST API 免费,不登录每小时 60 次请求,登录后 5000 次。对个人项目完全够用。

import requests

def get_trending_repos(language="python", per_page=5):
    """获取 GitHub 上某语言的热门仓库"""
    url = "https://api.github.com/search/repositories"
    params = {
        "q": f"language:{language}",
        "sort": "stars",
        "order": "desc",
        "per_page": per_page
    }
    headers = {"Accept": "application/vnd.github.v3+json"}

    resp = requests.get(url, headers=headers, params=params)
    data = resp.json()

    print(f"🔥 {language} 语言 Stars 最高的仓库:")
    for repo in data["items"]:
        print(f"  ⭐ {repo['stargazers_count']:,} | {repo['full_name']}")
        print(f"     {repo['description'][:80] if repo['description'] else '无描述'}")
        print(f"     {repo['html_url']}\n")

get_trending_repos("rust", 5)

进阶:监控仓库动态。你关注的项目发了新 Release,自动通知你:

def check_latest_release(owner, repo):
    """检查仓库最新 Release"""
    url = f"https://api.github.com/repos/{owner}/{repo}/releases/latest"
    resp = requests.get(url)
    if resp.status_code == 200:
        release = resp.json()
        print(f"📦 {owner}/{repo}")
        print(f"   最新版本: {release['tag_name']}")
        print(f"   发布时间: {release['published_at']}")
        print(f"   下载地址: {release['html_url']}")
    else:
        print(f"该仓库没有 Release")

check_latest_release("tauri-apps", "tauri")

这个例子可以配合上一篇的 cron 定时任务——每天跑一次,有新版就飞书/Telegram 通知你。

实战四:AI 大模型 API(免费额度管够)

现在做大模型 API 的厂商太多了,而且每家都有免费额度:

平台免费额度兼容格式
Groq多模型免费OpenAI 兼容
DeepSeek注册送 500 万 tokensOpenAI 兼容
硅基流动多模型免费额度OpenAI 兼容
Google Gemini免费 tier自有格式

好消息:这些平台都兼容 OpenAI 的 API 格式,一套代码全搞定。

import requests

def call_llm(api_key, base_url, model, prompt):
    """通用大模型调用函数——兼容 OpenAI 格式的所有平台"""
    url = f"{base_url}/chat/completions"
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    }
    payload = {
        "model": model,
        "messages": [
            {"role": "system", "content": "你是 Python 技术专家,回答简洁"},
            {"role": "user", "content": prompt}
        ],
        "temperature": 0.7,
        "max_tokens": 500
    }

    resp = requests.post(url, headers=headers, json=payload)
    data = resp.json()
    return data["choices"][0]["message"]["content"]

# 示例:调用 DeepSeek(替换成你自己的 key)
# result = call_llm(
#     api_key="sk-your-deepseek-key",
#     base_url="https://api.deepseek.com/v1",
#     model="deepseek-chat",
#     prompt="用 3 句话解释什么是装饰器"
# )
# print(result)

做产品的时候,可以把 AI 能力嵌入到任何地方——自动总结、智能分类、内容生成、代码审查。因为有免费额度,前期验证成本基本为零。

实战五:Unsplash 图片 API(让你的产品好看)

独立开发者的产品最大的问题之一是"看着像 demo"。Unsplash 免费 API 可以提供高质量配图。

import requests

def search_photos(query, per_page=5):
    """搜索 Unsplash 高质量图片"""
    url = "https://api.unsplash.com/search/photos"
    # 注册 https://unsplash.com/developers 获取 Access Key
    headers = {"Authorization": "Client-ID YOUR_ACCESS_KEY"}
    params = {"query": query, "per_page": per_page}

    resp = requests.get(url, headers=headers, params=params)
    data = resp.json()

    print(f"🖼️ 搜索 '{query}' 的结果:")
    for photo in data["results"]:
        print(f"  📷 {photo['description'][:60] if photo['description'] else '无描述'}")
        print(f"     作者: {photo['user']['name']}")
        print(f"     原图: {photo['urls']['regular']}")
        print(f"     缩略图: {photo['urls']['thumb']}\n")

# search_photos("coding setup")

Unsplash 免费额度是每小时 50 次请求。对于博客配图、产品 Landing Page、文章封面这些场景绰绰有余。

进阶:打造通用 API 调用框架

上面 5 个例子覆盖了常见模式。但真实项目中你需要同时调多个 API,每个 API 的错误处理、重试、超时配置都不一样。下面是我在生产环境用的通用框架:

import requests
import time
from functools import wraps
from typing import Callable

class APIClient:
    """通用 API 客户端——错误处理 + 重试 + 限流 + 超时"""

    def __init__(self, base_url: str, headers: dict = None,
                 timeout: int = 10, max_retries: int = 3):
        self.base_url = base_url.rstrip("/")
        self.headers = headers or {}
        self.timeout = timeout
        self.max_retries = max_retries
        self.session = requests.Session()
        self.session.headers.update(self.headers)

    def _request(self, method: str, path: str, **kwargs):
        """核心请求方法——自动重试 + 指数退避"""
        url = f"{self.base_url}{path}"
        kwargs.setdefault("timeout", self.timeout)

        for attempt in range(self.max_retries):
            try:
                resp = self.session.request(method, url, **kwargs)

                # 限流:等到 Retry-After 再重试
                if resp.status_code == 429:
                    wait = int(resp.headers.get("Retry-After", 5))
                    print(f"⚠️ 限流,{wait}s 后重试 (第 {attempt+1}/{self.max_retries} 次)")
                    time.sleep(wait)
                    continue

                # 服务端错误:指数退避
                if resp.status_code >= 500:
                    wait = 2 ** attempt
                    print(f"⚠️ 服务端错误 {resp.status_code}{wait}s 后重试")
                    time.sleep(wait)
                    continue

                resp.raise_for_status()
                return resp.json()

            except requests.exceptions.Timeout:
                print(f"⏱️ 请求超时 (第 {attempt+1}/{self.max_retries} 次)")
                if attempt == self.max_retries - 1:
                    raise
                time.sleep(2 ** attempt)

            except requests.exceptions.RequestException as e:
                print(f"❌ 请求失败: {e}")
                if attempt == self.max_retries - 1:
                    raise
                time.sleep(2 ** attempt)

        raise Exception(f"超过最大重试次数 {self.max_retries}")

    def get(self, path: str, **kwargs):
        return self._request("GET", path, **kwargs)

    def post(self, path: str, **kwargs):
        return self._request("POST", path, **kwargs)


# 使用示例
weather_client = APIClient(
    base_url="https://api.open-meteo.com/v1",
    timeout=5
)

data = weather_client.get("/forecast", params={
    "latitude": 31.23,
    "longitude": 121.47,
    "daily": "temperature_2m_max",
    "forecast_days": 3
})
print(data["daily"])

这个框架你复制到任何项目里就能用。核心思想:不要在每个 API 调用的地方重复写 try/except 和 retry 逻辑——抽象成一层,所有 API 共用。

重试策略是关键:

  • 429 限流:等 Retry-After 头指定的时间,不要不管不顾地重试
  • 5xx 服务端错误:指数退避(1s → 2s → 4s)
  • 超时:同样指数退避,每次翻倍等待

50+ 免费 API 速查表

下面这个表是我用过的、确认能用的免费 API。按场景分类:

天气 & 地理

API免费额度需要 Key亮点
Open-Meteo无限天气/历史/空气质量
OpenWeatherMap1000次/天当前天气 + 5天预报
WeatherAPI100万次/月天气 + 天文 + 时区
IP-API45次/分钟IP 转地理位置
Nominatim1次/秒地址 ↔ 坐标转换

金融 & 汇率

API免费额度需要 Key亮点
Frankfurter无限汇率 + 历史
ExchangeRate-API1500次/月多币种
CoinGecko30次/分钟加密货币全数据
Alpha Vantage25次/天股票数据

开发 & 工具

API免费额度需要 Key亮点
GitHub REST API60次/时(无登录)仓库/Issues/搜索
GitLab API无限私有仓库也支持
JSONPlaceholder无限假数据,开发测试用
httpbin无限调试 HTTP 请求

AI & 机器学习

API免费额度需要 Key亮点
Groq多模型免费速度极快
DeepSeek500万 tokens性价比高
Google Gemini免费 tier多模态
HuggingFace免费推理海量开源模型
Remove.bg50次/月一键去背景

新闻 & 内容

API免费额度需要 Key亮点
NewsAPI100次/天全球新闻聚合
HackerNews无限科技圈热门
Reddit JSON无限任何 subreddit 加 .json
Dev.to无限开发者文章

图片 & 媒体

API免费额度需要 Key亮点
Unsplash50次/时高质量图库
Pexels200次/时图片 + 视频
Lorem Picsum无限随机占位图
Dog API无限随机狗图

文本 & 翻译

API免费额度需要 Key亮点
LibreTranslate无限(自部署)开源翻译
Lingva无限Google 翻译代理
Quotes REST无限随机名言

其他实用

API免费额度需要 Key亮点
Public APIs无限API 目录本身也是个 API
TheCatAPI无限猫图 + 品种信息
Pokemon API无限宝可梦全数据
OpenAI API$5 试用金GPT 全家桶

总量超过 50 个。其中带 “无限” 标记的可以直接上手,不需要注册。

真实场景组合:天气推送机器人

光看 API 列表没用,组合起来才有力量。我用 3 个免费 API 拼了一个天气预报推送:

from APIClient import APIClient  # 上面写的通用框架
import json
from datetime import datetime

# 1. 坐标转城市名(Nominatim)
geo = APIClient("https://nominatim.openstreetmap.org")
geo.session.headers["User-Agent"] = "WeatherBot/1.0"  # Nominatim 要求

# 2. 天气数据(Open-Meteo)
weather = APIClient("https://api.open-meteo.com/v1")

# 3. 推送通知(假设你有一个 webhook)
# notify = APIClient("https://your-webhook.com")


def daily_weather_report(lat, lon):
    """每日天气报告"""
    # 获取城市名
    location = geo.get("/reverse", params={
        "lat": lat, "lon": lon, "format": "json"
    })
    city = location.get("address", {}).get("city", "未知城市")

    # 获取天气
    data = weather.get("/forecast", params={
        "latitude": lat, "longitude": lon,
        "daily": ["temperature_2m_max", "temperature_2m_min",
                   "precipitation_sum", "weathercode"],
        "forecast_days": 1,
        "timezone": "Asia/Shanghai"
    })

    today = data["daily"]
    report = f"""
📅 {today['time'][0]} {city}天气预报
━━━━━━━━━━━━━━━━━━
🌡️ 温度: {today['temperature_2m_min'][0]}°C ~ {today['temperature_2m_max'][0]}°C
🌧️ 降水: {today['precipitation_sum'][0]}mm
💡 {'今天有雨,出门带伞' if today['precipitation_sum'][0] > 0 else '天气不错'}
"""

    print(report)
    # 推送到飞书/Telegram/邮件(具体代码见系列第 01 篇)
    return report

daily_weather_report(31.23, 121.47)

三个 API,零费用,每天早上跑一次。配合上一篇文章的 cron 示例,这就是一个完整产品。

踩坑记录

写 API 调用这几年,有些坑重复踩:

1. API Key 写死在代码里

绝对不要。用环境变量:

import os
api_key = os.environ["OPENAI_API_KEY"]  # 正确
# api_key = "sk-xxxxxxxx"  # 错误:一推 GitHub 就泄露

2. 不检查 rate limit

每个 API 都有额度。调用前查 X-RateLimit-Remaining 响应头:

resp = requests.get(url)
remaining = resp.headers.get("X-RateLimit-Remaining")
if remaining and int(remaining) < 10:
    print("⚠️ 额度预警,暂停使用")
    time.sleep(60)

3. 同步调多个 API,一个超时全卡住

concurrent.futures 并行请求:

from concurrent.futures import ThreadPoolExecutor

def fetch_all(urls):
    with ThreadPoolExecutor(max_workers=5) as executor:
        results = list(executor.map(
            lambda u: requests.get(u, timeout=5).json(),
            urls
        ))
    return results

4. API 改版不知道

定时跑一次测试脚本,监控响应结构变化。最简单的办法:

import hashlib

# 记录响应 key 结构的哈希
resp = requests.get("https://api.example.com/data").json()
structure_hash = hashlib.md5(
    str(sorted(resp.keys())).encode()
).hexdigest()

# 存到文件,下次对比,变了就告警

从这里开始

这篇文章和你上篇学的爬虫组合在一起,就是你作为独立开发者获取数据的全部武器:

  • 有 API → 用本文的方法调
  • 没 API 但页面是静态的 → 用上篇的 BeautifulSoup 爬
  • 页面是 SPA/JS 渲染的 → 用 Playwright

建议今天就找 2-3 个感兴趣的 API,用上面 APIClient 框架接一下。10 行代码就能把一个免费数据源接到你的项目里。接得多了,你会发现很多产品想法根本不需要自己造数据——世界上已经有免费的 API 在等你用了。


系列导航01 日常任务自动化 | 02 Web Scraping 实战 | 03 API 自动化 | 04 数据分析自动化

Python 自动化实战系列,下一篇:数据分析自动化——Pandas 实战,把 API 拿回来的数据变成洞察。