讲师中心 微信公众号
AI工具推荐 视频效率加速

通过Python实现API请求限速与批量地理距离计算

冬磊小哥_9493

冬磊小哥_9493

发布时间:2025-08-11 19:38:16

|

1120人浏览过

|

来源于php中文网

原创

通过Python实现API请求限速与批量地理距离计算

本教程详细介绍了如何使用Python高效且负责任地通过API计算两点间的驾驶距离。文章从基础的API调用函数出发,深入探讨了利用contextlib模块实现API请求限速的策略,以避免因请求频率过高而被服务器拒绝。此外,教程还强调了API响应错误处理的重要性,并提供了将计算结果整合到Pandas DataFrame中的实用方法,旨在帮助开发者构建稳定、高效的地理数据处理应用。

1. 理解地理距离计算与API调用基础

在地理信息处理中,计算两点间的驾驶距离是一个常见需求。通常,我们会利用第三方地图服务的api来获取这些数据。本教程以开源路由服务osrm为例,展示如何通过http请求获取驾驶距离。

一个基本的距离计算函数可能如下所示:

import requests
import json

def get_driving_distance(lat1, lon1, lat2, lon2):
    """
    通过OSRM API计算两点间的驾驶距离。
    参数:
        lat1 (float): 起点纬度
        lon1 (float): 起点经度
        lat2 (float): 终点纬度
        lon2 (float): 终点经度
    返回:
        float: 驾驶距离(英里),如果请求失败则返回None
    """
    try:
        # OSRM API的URL格式为 /route/v1/car/{lon1},{lat1};{lon2},{lat2}
        url = f"http://router.project-osrm.org/route/v1/car/{lon1},{lat1};{lon2},{lat2}?overview=false"
        r = requests.get(url)
        r.raise_for_status() # 检查HTTP状态码,如果不是200则抛出异常
        routes = json.loads(r.content)

        # 确保API返回了有效的路由数据
        if routes and "routes" in routes and len(routes["routes"]) > 0:
            route_info = routes["routes"][0]
            driving_distance_meters = route_info.get('distance')
            if driving_distance_meters is not None:
                # 将米转换为英里 (1 英里 ≈ 1609.34 米)
                return driving_distance_meters / 1609.34
            else:
                print(f"警告: API响应中未找到距离信息: {url}")
                return None
        else:
            print(f"警告: API响应中未找到有效路由: {url}")
            return None
    except requests.exceptions.RequestException as e:
        print(f"请求API时发生错误: {e}")
        return None
    except json.JSONDecodeError as e:
        print(f"解析API响应时发生错误: {e}")
        return None
    except Exception as e:
        print(f"发生未知错误: {e}")
        return None

# 示例调用
# distance = get_driving_distance(51.5074, 0.1278, 51.5000, 0.1000)
# if distance is not None:
#     print(f"驾驶距离: {distance:.2f} 英里")

在上述代码中,我们引入了requests.raise_for_status()来自动检查HTTP响应状态码,并在出现错误时抛出异常。这是一种处理网络请求错误的重要实践。

2. 实现API请求限速机制

频繁地调用API可能会导致服务器过载,或触发API提供商的速率限制,从而导致请求失败或IP被封禁。为了解决这个问题,我们需要实现一个请求限速机制。Python的contextlib模块提供了一种优雅的方式来创建上下文管理器,非常适合实现这类功能。

我们可以创建一个rate_limited上下文管理器,它会在达到一定请求次数后暂停执行一段时间。

立即学习“Python免费学习笔记(深入)”;

from contextlib import contextmanager
from time import sleep
import requests
import json

# 全局变量,用于跟踪API调用次数
api_calls_counter = 0

@contextmanager
def rate_limited(limit=500, delay=5):
    """
    一个上下文管理器,用于限制API调用频率。
    当API调用次数达到指定限制时,暂停指定延迟时间。
    参数:
        limit (int): 在暂停前允许的最大API调用次数。
        delay (int): 达到限制后暂停的秒数。
    """
    global api_calls_counter

    # 在进入上下文之前检查并更新计数器
    if api_calls_counter + 1 >= limit:
        print(f"达到 {limit} 次API调用限制,暂停 {delay} 秒...")
        sleep(delay)
        api_calls_counter = 0 # 重置计数器,或者根据需要调整重置逻辑

    api_calls_counter += 1

    try:
        yield # 执行上下文内的代码
    finally:
        # 可以在这里进行一些清理工作,例如记录日志
        pass

# 重新定义 get_driving_distance 函数,集成限速机制
def get_driving_distance_with_rate_limit(lat1, lon1, lat2, lon2):
    """
    通过OSRM API计算两点间的驾驶距离,并集成请求限速。
    """
    with rate_limited(limit=500, delay=5): # 每500次请求暂停5秒
        try:
            url = f"http://router.project-osrm.org/route/v1/car/{lon1},{lat1};{lon2},{lat2}?overview=false"
            r = requests.get(url)
            r.raise_for_status() # 检查HTTP状态码
            routes = json.loads(r.content)

            if routes and "routes" in routes and len(routes["routes"]) > 0:
                route_info = routes["routes"][0]
                driving_distance_meters = route_info.get('distance')
                if driving_distance_meters is not None:
                    return driving_distance_meters / 1609.34
                else:
                    print(f"警告: API响应中未找到距离信息: {url}")
                    return None
            else:
                print(f"警告: API响应中未找到有效路由: {url}")
                return None
        except requests.exceptions.RequestException as e:
            print(f"请求API时发生错误: {e} (URL: {url})")
            return None
        except json.JSONDecodeError as e:
            print(f"解析API响应时发生错误: {e} (URL: {url}, Response: {r.text[:200]}...)")
            return None
        except Exception as e:
            print(f"发生未知错误: {e} (URL: {url})")
            return None

注意事项:

  • 全局计数器: 示例中使用了一个简单的全局计数器api_calls_counter。在更复杂的应用中,可以考虑使用线程安全的计数器或将计数器封装在类中。
  • 重置逻辑: api_calls_counter = 0 是一个简单的重置方式。如果API有滑动窗口限制(例如,每分钟X次请求),则需要更复杂的逻辑来跟踪请求时间。
  • 错误处理: 即使使用了限速,API请求仍然可能失败(例如,网络问题、服务器内部错误)。因此,保留try-except块进行错误处理至关重要。

3. 批量处理数据并整合到DataFrame

通常,我们会有多组起点和终点坐标需要处理。Pandas库是处理表格数据的强大工具,非常适合将输入数据和计算结果整合到DataFrame中。

从 Git 仓库历史中彻底删除文件
从 Git 仓库历史中彻底删除文件

|Git删除了文件,但还会在Git 仓库历史中遗留。 - 想要从 Git 历史移除敏感信息(密码、密钥、token、私钥) - 想要删除意外提交的大文件 - 想要重写 Git 历史、移除特定文件的所有痕迹 - 提到 "force push"、"重写 commit 历史" - 需要从所有分支、所有 tag 中删除某个文件

下载

假设我们有四个列表,分别存储起点纬度、起点经度、终点纬度、终点经度:

import pandas as pd

# 示例数据
location_latitudes = [51.5074, 51.4998, 51.5123]
location_longitudes = [0.1278, 0.1749, 0.0884]
station_latitudes = [51.5000, 51.4800, 51.5200]
station_longitudes = [0.1000, 0.2000, 0.0500]

# 创建一个DataFrame来存储原始数据和结果
data = {
    'location_lat': location_latitudes,
    'location_lon': location_longitudes,
    'station_lat': station_latitudes,
    'station_lon': station_longitudes
}
df = pd.DataFrame(data)

# 初始化一个空列表来存储计算出的距离
driving_distances = []

# 遍历DataFrame的每一行,调用API计算距离
# 使用zip函数迭代多个列表,或使用df.itertuples()迭代DataFrame行
for index, row in df.iterrows():
    lat1 = row['location_lat']
    lon1 = row['location_lon']
    lat2 = row['station_lat']
    lon2 = row['station_lon']

    distance = get_driving_distance_with_rate_limit(lat1, lon1, lat2, lon2)
    driving_distances.append(distance)

# 将计算出的距离添加到DataFrame的新列中
df['driving_distance_miles'] = driving_distances

print(df)

输出示例 (实际数值会根据API返回而定):

   location_lat  location_lon  station_lat  station_lon  driving_distance_miles
0       51.5074        0.1278       51.500       0.1000                1.503456
1       51.4998        0.1749       51.480       0.2000                1.876543
2       51.5123        0.0884       51.520       0.0500                2.123456

4. 总结与最佳实践

本教程展示了如何构建一个健壮的Python应用程序,用于批量计算地理距离,同时有效地管理API请求。

关键点回顾:

  • API调用函数: 封装API请求逻辑,使其可重用。
  • 错误处理: 使用requests.raise_for_status()和try-except块处理网络请求和JSON解析错误,提高程序的鲁棒性。
  • 请求限速: 利用contextlib.contextmanager创建自定义上下文管理器,实现API请求的速率控制,避免因请求频率过高而被封禁。
  • 数据整合: 使用Pandas DataFrame高效地管理输入数据和计算结果,方便后续分析。

进一步的考虑和最佳实践:

  • 持久化: 对于大量数据,考虑将中间结果或最终结果保存到文件(如CSV、Parquet)中,以防程序中断或避免重复计算。
  • 异步请求: 对于非常大的数据集,可以考虑使用asyncio和aiohttp等库进行异步API请求,以提高效率。
  • API密钥管理: 如果使用的API需要密钥,请务必安全地管理它们,例如通过环境变量或配置文件,而不是硬编码在代码中。
  • 重试机制: 对于临时的网络问题或API服务器过载,可以实现指数退避重试机制,增加请求成功的几率。
  • 日志记录: 记录API请求、响应、错误和限速触发事件,有助于调试和监控。

通过遵循这些原则和实践,您可以构建出高效、稳定且负责任的API驱动应用程序。

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

Flowith
Flowith Hot

Flowith是一款基于画布和智能体工作流的 AI 协作工作空间。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

2255

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

3662

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

1216

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

4219

2025.09.10

Python 时间序列分析与预测
Python 时间序列分析与预测

本专题专注讲解 Python 在时间序列数据处理与预测建模中的实战技巧,涵盖时间索引处理、周期性与趋势分解、平稳性检测、ARIMA/SARIMA 模型构建、预测误差评估,以及基于实际业务场景的时间序列项目实操,帮助学习者掌握从数据预处理到模型预测的完整时序分析能力。

340

2025.12.04

Python 数据清洗与预处理实战
Python 数据清洗与预处理实战

本专题系统讲解 Python 在数据清洗与预处理中的核心技术,包括使用 Pandas 进行缺失值处理、异常值检测、数据格式化、特征工程与数据转换,结合 NumPy 高效处理大规模数据。通过实战案例,帮助学习者掌握 如何处理混乱、不完整数据,为后续数据分析与机器学习模型训练打下坚实基础。

272

2026.01.31

Python数据分析与Pandas高级实战
Python数据分析与Pandas高级实战

本专题围绕 Python 数据分析展开,系统讲解 Pandas 的高级用法,包括数据清洗、透视表、时间序列分析以及多表合并与分组操作。通过实战案例,帮助开发者掌握高效处理与分析数据的方法,提高数据处理效率与分析能力。

811

2026.04.13

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

4658

2023.08.10

DBeaver怎么导入数据
DBeaver怎么导入数据

DBeaver数据导入专题,整理Excel、CSV、SQL、TXT等常见文件的数据导入方法,涵盖目标数据库选择、数据表创建、字段映射、数据类型设置及导入参数配置等操作,帮助用户将本地文件中的数据写入数据库,并了解批量导入、重复数据处理和导入失败等常见问题的解决方法。

0

2026.11.05

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn