如何批量爬取GBGB网站的灵缇赛事结果,无需手动指定URL?
问题
我目前通过Python代码手动指定带meeting ID和race ID的URL,从GBGB网站下载Crayford赛道的灵缇赛事结果(示例为5月25日至6月2日的数据)。但如果要下载3个月甚至9个月的数据,逐行添加URL太耗时。作为网络爬虫新手,想知道如何批量获取6个月的结果,不用手动逐个指定URL。
原代码如下:
import httpx from selectolax.parser import HTMLParser import json from urllib.request import urlopen import requests from datetime import datetime, timedelta import ndjson URLs = [ "https://api.gbgb.org.uk/api/results/meeting/411238?raceId=1040677",#25th May Sat "https://api.gbgb.org.uk/api/results/meeting/411239?raceId=1040615",#26th May Sun "https://api.gbgb.org.uk/api/results/meeting/411378?raceId=1041270",#28st May Tue "https://api.gbgb.org.uk/api/results/meeting/411461?raceId=1042006",#30rd May Thu "https://api.gbgb.org.uk/api/results/meeting/411477?raceId=1042178",#31th May Fri #June "https://api.gbgb.org.uk/api/results/meeting/411583?raceId=1042517",#01st Jun Sat "https://api.gbgb.org.uk/api/results/meeting/411452?raceId=1042214",#02nd Jun Sun ] json_list = [] for url in URLs: resp = requests.get(url) page_context = resp.text print(page_context) json_file = json.loads(page_context) json_list.extend(json_file) with open('C:/mypath/Grey_results.json', 'w') as f: ndjson.dump(json_list, f)
解决方案
核心思路是通过GBGB的赛事列表API自动获取指定日期范围、指定赛道的meeting ID和race ID,无需手动收集。具体步骤如下:
- 确定赛事列表API:GBGB提供按日期和赛道查询赛事列表的接口,请求格式为
https://api.gbgb.org.uk/api/meetings?date={日期字符串}&trackId={赛道ID}。Crayford赛道的trackId为7(可从网站页面源码或接口返回中确认)。 - 遍历目标日期范围:用
datetime模块生成6个月内的所有日期,逐个日期请求赛事列表。 - 提取必要ID:从每个日期的赛事列表响应中,提取每个赛事的
meetingId和raceId,构造结果请求URL。 - 批量获取并保存数据:遍历所有构造好的URL,请求结果数据,汇总后保存为NDJSON文件。
修改后的代码如下:
import requests import json from datetime import datetime, timedelta import ndjson import time # 配置参数 TARGET_TRACK_ID = 7 # Crayford赛道的ID START_DATE = datetime(2024, 5, 25) # 起始日期 END_DATE = datetime(2024, 11, 25) # 结束日期(6个月后) OUTPUT_PATH = 'C:/mypath/Grey_results.json' REQUEST_DELAY = 1 # 请求间隔(秒),避免触发反爬 def get_race_urls_for_date(date): """获取指定日期Crayford赛道所有赛事的结果URL""" date_str = date.strftime('%Y-%m-%d') # 请求当日赛事列表 meeting_url = f'https://api.gbgb.org.uk/api/meetings?date={date_str}&trackId={TARGET_TRACK_ID}' try: resp = requests.get(meeting_url) resp.raise_for_status() # 检查请求是否成功 meetings = resp.json() except Exception as e: print(f"获取{date_str}赛事列表失败: {e}") return [] race_urls = [] for meeting in meetings: # 遍历该场次下的所有赛事 for race in meeting.get('races', []): race_id = race.get('raceId') meeting_id = meeting.get('meetingId') if race_id and meeting_id: race_url = f'https://api.gbgb.org.uk/api/results/meeting/{meeting_id}?raceId={race_id}' race_urls.append(race_url) return race_urls def main(): json_list = [] current_date = START_DATE # 遍历日期范围 while current_date <= END_DATE: print(f"处理日期: {current_date.strftime('%Y-%m-%d')}") race_urls = get_race_urls_for_date(current_date) # 遍历当日所有赛事URL for url in race_urls: try: resp = requests.get(url) resp.raise_for_status() race_data = resp.json() json_list.extend(race_data) print(f"成功获取赛事数据: {url}") time.sleep(REQUEST_DELAY) # 添加请求间隔 except Exception as e: print(f"获取赛事数据失败{url}: {e}") # 日期加1天 current_date += timedelta(days=1) # 保存数据 with open(OUTPUT_PATH, 'w') as f: ndjson.dump(json_list, f) print(f"所有数据已保存至: {OUTPUT_PATH}") if __name__ == '__main__': main()
注意事项
- 反爬规避:加入请求间隔避免频繁请求被封禁,若仍出现问题可适当延长间隔时间。
- 参数验证:若赛道ID不确定,可访问GBGB官网的Crayford赛道页面,查看页面源码或网络请求中的trackId参数。
- 错误处理:代码包含基础异常捕获,可根据需求扩展重试机制或日志记录功能。
内容的提问来源于stack exchange,提问作者Rv02
相关产品推荐
相关产品推荐

