python cairo 使用python采集api数据

本教程详细介绍了如何利用python的`requests`库与gbgb api交互,以自动化方式抓取指定日期范围和特定赛狗赛道的比赛结果。文章涵盖了api参数的理解、日期范围的程序化生成、http请求的发送、json数据的解析与筛选,以及最终数据的持久化存储,旨在提供一个结构清晰、可复用的数据抓取解决方案。
自动化抓取GBGB赛狗比赛结果在进行数据分析或建立预测模型时,从特定网站获取大量结构化数据是一项常见需求。对于GBGB(Great British Greyhound Board)的赛狗比赛结果,手动通过网站界面或逐个URL抓取是极其耗时且效率低下的。本教程将展示如何利用Python及其强大的requests库,结合GBGB提供的API接口,实现对指定日期范围和特定赛道的比赛结果进行高效、自动化的抓取。
理解GBGB API接口GBGB提供了一个API接口,允许开发者通过HTTP请求获取比赛结果数据。根据提供的信息,核心的API端点是:https://api.gbgb.org.uk/api/results
此端点支持以下关键查询参数:
page: 页码,用于分页。itemsPerPage: 每页显示的条目数。例如,200表示每页获取200条记录。date: 指定查询的日期,格式为YYYY-MM-DD。这是实现日期范围抓取的关键。race_type: 比赛类型,例如race。通过组合这些参数,我们可以构建出请求URL,例如:https://api.gbgb.org.uk/api/results?page=1&itemsPerPage=200&date=2023-11-01&race_type=race这将返回2023年11月1日的所有比赛结果中的前200条记录。
设置开发环境在开始之前,请确保您的Python环境中安装了requests库。如果尚未安装,可以通过以下命令进行安装:
pip install requests登录后复制程序化生成日期范围
为了实现指定日期范围的抓取,我们需要编写代码来迭代生成所需的日期字符串。这通常涉及到一个嵌套循环,外层循环处理月份,内层循环处理该月份中的每一天。
立即学习“Python免费学习笔记(深入)”;
from datetime import datetime, timedeltaimport requestsimport json# 定义抓取的起始和结束日期start_date = datetime(2023, 10, 1) # 例如,从2023年10月1日开始end_date = datetime(2023, 12, 31) # 到2023年12月31日结束# 存储所有抓取到的数据all_results = []# API基础URL和固定参数base_url = "https://api.gbgb.org.uk/api/results"params = { 'page': '1', 'itemsPerPage': '200', # 假设每页最多200条,根据实际情况调整或处理分页 'race_type': 'race'}# 循环生成日期current_date = start_datewhile current_date <= end_date: # 格式化日期为 YYYY-MM-DD params['date'] = current_date.strftime('%Y-%m-%d') # 打印当前正在抓取的日期,便于跟踪进度 print(f"正在抓取 {params['date']} 的数据...") # 移动到下一天 current_date += timedelta(days=1)登录后复制上述代码片段初始化了起始和结束日期,并使用datetime和timedelta对象来逐天递增,确保每个日期都能被处理。
发送API请求与错误处理在日期循环内部,我们将使用requests.get()方法向API发送请求,并处理可能出现的各种网络或API错误。
Quinvio AI AI辅助下快速创建视频,虚拟代言人
59 查看详情
# ... (前面的代码保持不变)current_date = start_datewhile current_date <= end_date: params['date'] = current_date.strftime('%Y-%m-%d') print(f"正在抓取 {params['date']} 的数据...") try: response = requests.get(base_url, params=params) response.raise_for_status() # 检查HTTP请求是否成功 (200 OK) # 将响应内容解析为JSON page_context_dict = response.json() # GBGB API的实际数据通常在 'items' 键中 items = page_context_dict.get('items', []) # 将抓取到的数据添加到总列表中 all_results.extend(items) except requests.exceptions.HTTPError as errh: print(f"HTTP错误 (日期: {params['date']}): {errh}") except requests.exceptions.ConnectionError as errc: print(f"连接错误 (日期: {params['date']}): {errc}") except requests.exceptions.Timeout as errt: print(f"请求超时 (日期: {params['date']}): {errt}") except requests.exceptions.RequestException as err: print(f"请求异常 (日期: {params['date']}): {err}") except json.JSONDecodeError as json_err: print(f"JSON解析错误 (日期: {params['date']}): {json_err} - 响应内容: {response.text[:200]}") # 打印部分响应内容辅助调试 current_date += timedelta(days=1)# ... (后续数据处理和保存)登录后复制response.raise_for_status()是一个非常有用的方法,它会在HTTP请求返回错误状态码(如4xx或5xx)时抛出HTTPError异常,从而方便我们捕获并处理这些问题。
筛选特定赛道数据API返回的数据可能包含所有赛道的信息。如果我们需要筛选出特定赛道(例如“Swindon”)的比赛结果,可以在获取到每日数据后进行过滤。
# ... (前面的代码保持不变)desired_track = "Swindon" # 定义您感兴趣的赛道名称current_date = start_datewhile current_date <= end_date: params['date'] = current_date.strftime('%Y-%m-%d') print(f"正在抓取 {params['date']} 的数据...") try: response = requests.get(base_url, params=params) response.raise_for_status() page_context_dict = response.json() items = page_context_dict.get('items', []) # 筛选特定赛道的数据 specific_track_items = [] for item in items: if "trackName" in item and item["trackName"] == desired_track: specific_track_items.append(item) all_results.extend(specific_track_items) # 将筛选后的数据添加到总列表 except Exception as e: # 捕获更广泛的异常,或者保持细致的异常捕获 print(f"处理日期 {params['date']} 时发生错误: {e}") current_date += timedelta(days=1)# ... (后续数据保存)登录后复制这里,我们遍历每天获取到的items列表,检查每个item字典中是否存在trackName键,并且其值是否与desired_track匹配。
完整代码示例将上述所有组件整合,形成一个完整的Python脚本:
from datetime import datetime, timedeltaimport requestsimport jsondef scrape_gbgb_results(start_date_str, end_date_str, desired_track_name, output_filename="gbgb_results.json"): """ 从GBGB API抓取指定日期范围和特定赛道的比赛结果。 Args: start_date_str (str): 起始日期,格式 'YYYY-MM-DD'。 end_date_str (str): 结束日期,格式 'YYYY-MM-DD'。 desired_track_name (str): 目标赛道的名称,例如 "Swindon"。 output_filename (str): 结果保存的文件名,默认为 "gbgb_results.json"。 """ try: start_date = datetime.strptime(start_date_str, '%Y-%m-%d') end_date = datetime.strptime(end_date_str, '%Y-%m-%d') except ValueError: print("日期格式不正确。请使用 'YYYY-MM-DD' 格式。") return all_results = [] base_url = "https://api.gbgb.org.uk/api/results" params = { 'page': '1', 'itemsPerPage': '200', # 根据API限制和需求调整 'race_type': 'race' } current_date = start_date while current_date <= end_date: params['date'] = current_date.strftime('%Y-%m-%d') print(f"正在抓取 {params['date']} 的数据...") try: response = requests.get(base_url, params=params, timeout=10) # 设置超时 response.raise_for_status() # 如果状态码不是200,则抛出HTTPError page_context_dict = response.json() items = page_context_dict.get('items', []) specific_track_items = [] for item in items: if "trackName" in item and item["trackName"] == desired_track_name: specific_track_items.append(item) if specific_track_items: # 仅当有筛选结果时才添加 all_results.extend(specific_track_items) except requests.exceptions.HTTPError as errh: print(f"HTTP错误 (日期: {params['date']}): {errh}") except requests.exceptions.ConnectionError as errc: print(f"连接错误 (日期: {params['date']}): {errc}") except requests.exceptions.Timeout as errt: print(f"请求超时 (日期: {params['date']}): {errt}") except requests.exceptions.RequestException as err: print(f"请求异常 (日期: {params['date']}): {err}") except json.JSONDecodeError as json_err: print(f"JSON解析错误 (日期: {params['date']}): {json_err}. 响应内容开头: {response.text[:200]}") except Exception as e: print(f"处理日期 {params['date']} 时发生未知错误: {e}") current_date += timedelta(days=1) # 将所有抓取到的数据写入JSON文件 if all_results: with open(output_filename, 'w', encoding='utf-8') as f: json.dump(all_results, f, ensure_ascii=False, indent=4) print(f"数据已成功保存到 {output_filename},共 {len(all_results)} 条记录。") else: print(f"在指定日期范围和赛道 '{desired_track_name}' 下未找到任何数据。")if __name__ == "__main__": # 示例调用 scrape_gbgb_results( start_date_str="2023-10-01", end_date_str="2023-10-31", desired_track_name="Swindon", output_filename="swindon_results_october.json" ) # 您可以根据需要更改日期范围和赛道名称 # scrape_gbgb_results( # start_date_str="2023-11-01", # end_date_str="2023-11-15", # desired_track_name="Hove", # output_filename="hove_results_early_november.json" # )登录后复制注意事项与最佳实践API速率限制 (Rate Limiting): 频繁或大量请求可能会触发API的速率限制,导致请求被拒绝。虽然GBGB API文档中未明确提及,但在实际操作中应注意。可以考虑在每次请求之间添加time.sleep()来引入延迟,例如time.sleep(0.5)。分页处理: 当前代码中itemsPerPage设置为200。如果某天的比赛结果超过200条,并且API支持多页,您可能需要在一个日期内部再增加一个循环来处理page参数,直到没有更多数据返回。数据结构变化: API返回的JSON数据结构可能会随时间变化。在编写代码时,应考虑到健壮性,例如使用.get()方法访问字典键,以避免因键不存在而引发错误。错误处理: 完善的错误处理机制对于数据抓取至关重要。上述代码已经包含了对常见requests异常和json解析错误的捕获,这有助于诊断和解决问题。目标赛道名称: desired_track_name必须与API返回数据中的trackName字段完全匹配,包括大小写。文件保存格式: 示例代码将数据保存为JSON格式,这是一种易于机器读取和解析的格式。根据需求,您也可以将其转换为CSV、数据库记录等其他格式。代码可复用性: 将抓取逻辑封装在函数中(如scrape_gbgb_results),可以提高代码的可读性和复用性。总结通过本教程,我们学习了如何利用Python的requests库与GBGB API接口进行交互,从而高效地抓取指定日期范围和特定赛道的赛狗比赛结果。这种自动化方法不仅节省了大量手动操作的时间,也为后续的数据分析和应用提供了可靠的数据源。掌握API接口的参数、程序化日期生成以及健壮的错误处理是实现此类数据抓取任务的关键。
以上就是使用Python和GBGB API高效抓取指定日期范围和赛道比赛结果教程的详细内容,更多请关注乐哥常识网其它相关文章!
相关标签: python js json app csv ai win 状态码 开发环境 持久化存储 python脚本 yy red Python json 封装 date 字符串 循环 数据结构 接口 对象 数据库 数据分析 http https 自动化 大家都在看: Python自动化抓取GBGB赛狗比赛结果:日期范围与赛道筛选教程 Python中处理嵌套字典与列表的数据提取与过滤教程 Python对象引用与属性赋值:理解链表中的行为 Python中将复杂日期时间字符串转换为Unix时间戳的指南 解决Python模块间函数依赖与循环引用问题