使用BeautifulSoup爬取Strava网页时遇到问题
从Strava活动页面提取轨迹数据生成GPX文件
问题描述
我想把Strava上的活动转换成GPX文件,需要爬取页面里的海拔、经纬度等数据。这些数据存在带<div data-react-class=属性的标签里,重点是从{"activity":{"name"开始的那段数据。但我写的代码里,找到目标div转成字符串后用.index('altitude')会报ValueError: substring not found错误,而且我希望只用BeautifulSoup来实现数据提取,不知道该怎么做。
原代码:
import requests from bs4 import BeautifulSoup import csv url = 'https://www.strava.com/activities/7487240518' urlr = requests.get(url) soup = BeautifulSoup(urlr.content, 'html.parser') divdata = soup.find('div', {'data-react-class':'ActivityPublic'}) strdata = str(divdata) print(strdata.index('altitude'))
问题原因
- 直接把div转字符串查找
altitude失败,核心原因是Strava页面的轨迹数据依赖动态渲染,用requests.get仅能拿到初始HTML框架,没有包含完整的轨迹字段(比如altitude)。 - 目标数据实际存储在div的
data-react-props属性里,而非div的文本内容,直接转字符串切片的方式既不可靠也容易出错。
基于BeautifulSoup的解决方案
步骤1:模拟浏览器请求获取完整页面
Strava会检测请求的User-Agent,必须添加浏览器头才能拿到包含数据的页面:
import requests from bs4 import BeautifulSoup import json import gpxpy import gpxpy.gpx url = 'https://www.strava.com/activities/7487240518' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' } urlr = requests.get(url, headers=headers)
步骤2:提取data-react-props中的JSON数据
目标div的data-react-props属性存储着包含活动轨迹的JSON字符串,解析后可直接提取所需数据:
soup = BeautifulSoup(urlr.content, 'html.parser') divdata = soup.find('div', {'data-react-class':'ActivityPublic'}) if divdata and 'data-react-props' in divdata.attrs: # 解析JSON数据 props_data = json.loads(divdata['data-react-props']) activity = props_data.get('activity', {}) streams = activity.get('streams', {}) # 提取经纬度、海拔轨迹流 latlng_stream = streams.get('latlng') altitude_stream = streams.get('altitude') if latlng_stream and altitude_stream: # 创建GPX文件结构 gpx = gpxpy.gpx.GPX() gpx_track = gpxpy.gpx.GPXTrack() gpx.tracks.append(gpx_track) gpx_segment = gpxpy.gpx.GPXTrackSegment() gpx_track.segments.append(gpx_segment) # 遍历轨迹点写入GPX for latlng, altitude in zip(latlng_stream['data'], altitude_stream['data']): lat, lng = latlng gpx_segment.points.append(gpxpy.gpx.GPXTrackPoint(lat, lng, elevation=altitude)) # 保存GPX文件 with open('strava_activity.gpx', 'w') as f: f.write(gpx.to_xml()) print("GPX文件生成成功!") else: print("未找到轨迹数据,需用动态渲染工具加载页面") else: print("未找到目标div或数据属性")
动态渲染 fallback(若静态请求仍无数据)
如果上述代码拿不到数据,说明轨迹数据是JS动态加载的,需用selenium启动浏览器加载页面后提取:
from selenium import webdriver from selenium.webdriver.common.by import By import time import json driver = webdriver.Chrome() driver.get(url) time.sleep(3) # 等待页面加载完成 divdata = driver.find_element(By.CSS_SELECTOR, 'div[data-react-class="ActivityPublic"]') props_data = json.loads(divdata.get_attribute('data-react-props')) # 后续轨迹提取、GPX生成逻辑同上述代码 driver.quit()
内容的提问来源于stack exchange,提问作者duncant
相关产品推荐
相关产品推荐

