AERONET 多源数据批量抓取:Python + Selenium 实战与 CURL/WGET 高效替代方案

张开发
2026/4/18 13:21:30 15 分钟阅读

分享文章

AERONET 多源数据批量抓取:Python + Selenium 实战与 CURL/WGET 高效替代方案
1. AERONET数据抓取的核心挑战做大气污染研究的朋友应该都深有体会AERONET这个宝藏数据库虽然数据质量高但每次手动下载数据简直能让人崩溃。我去年做京津冀地区十年气溶胶分析时需要下载37个站点不同年份的AOD、SDA、FMF等数据手动操作整整花了两周时间期间还因为网络波动导致多次中断重来。AERONET数据获取主要面临三个痛点动态参数依赖下载链接需要拼接十多个参数包括站点名、时间范围、数据类型等手动构造极易出错反爬机制直接访问数据文件URL会返回404必须先在网页完成查询操作生成临时令牌数据分散不同产品AOD/SDA/TOT分布在独立子系统统一采集需要处理多个接口实测发现单纯用Requests库直接访问会触发反爬而完全依赖Selenium又太慢。后来我摸索出一套混合方案用Selenium处理动态令牌用CURL进行批量下载速度比纯浏览器方案快8倍。下面具体说说这两种方案的实现细节和优化技巧。2. Selenium自动化方案全解析2.1 环境配置与核心组件建议使用Python 3.8搭配最新版ChromeDriver这里有个坑我踩过不同版本的WebDriver对XPath解析有差异会导致元素定位失败。我的配置清单# requirements.txt selenium4.1.0 webdriver-manager3.5.3 pandas1.3.0初始化浏览器实例时务必添加这些参数能显著提升稳定性from selenium.webdriver.chrome.options import Options chrome_options Options() chrome_options.add_argument(--headless) chrome_options.add_argument(--disable-gpu) chrome_options.add_argument(--window-size1920x1080) chrome_options.add_argument(--log-level3) driver webdriver.Chrome(optionschrome_options)2.2 站点列表获取实战AERONET官网的地图界面其实暗藏玄机。通过分析网络请求我发现这个技巧先访问https://aeronet.gsfc.nasa.gov/aeronet_locations.txt 可以直接获取所有站点的经纬度信息比解析HTML高效得多。结合BeautifulSoup提取站点详情页URL的完整代码def get_station_metadata(): base_url https://aeronet.gsfc.nasa.gov/cgi-bin/type_one_station_op_v3 resp requests.get(base_url) soup BeautifulSoup(resp.text, html.parser) stations [] for tr in soup.select(tr[bgcolor#CCCCCC], tr[bgcolor#FFFFFF]): tds tr.find_all(td) if len(tds) 5: continue station { name: tds[0].text.strip(), url: tds[0].find(a)[href], lat: float(tds[1].text), lon: float(tds[2].text), elev: float(tds[3].text), active: tds[4].text.strip() Active } stations.append(station) return pd.DataFrame(stations)2.3 动态令牌获取技巧AERONET的防直连机制非常特殊必须先在页面执行这三个步骤选择年份范围触发AJAX请求勾选需要的数据类型AOD/SDA等点击Submit按钮生成临时令牌关键代码实现def generate_download_token(driver, year_range, data_types): # 设置时间范围 select1 Select(driver.find_element(By.ID, Year1)) select1.select_by_value(year_range[0]) select2 Select(driver.find_element(By.ID, Year2)) select2.select_by_value(year_range[1]) # 勾选数据类型 for dtype in data_types: checkbox driver.find_element(By.NAME, dtype) if not checkbox.is_selected(): checkbox.click() # 提交查询 submit driver.find_element(By.NAME, Submit) submit.click() # 等待令牌生成关键 WebDriverWait(driver, 30).until( EC.presence_of_element_located((By.PARTIAL_LINK_TEXT, Download)) ) return driver.current_url3. CURL/WGET高效方案详解3.1 链接构造的玄机通过抓包分析我发现AERONET的下载API遵循固定格式https://aeronet.gsfc.nasa.gov/cgi-bin/print_web_data_v3? site{站点}year{开始年}month{开始月}day{开始日} year2{结束年}month2{结束月}day2{结束日} {数据类型}1AVG{时间分辨率}参数说明表参数必选示例值说明site是Beijing站点ID区分大小写AVG是1010原始数据20日均值AOD20可选11表示需要该数据类型hour否8起始小时0-23lunar_merge否00不含月数据1包含3.2 批量下载性能对比测试100个AOD20数据文件下载单位秒方法首次运行缓存后稳定性Selenium382355高CURL4729中WGET5231中混合模式5833高混合模式实现逻辑# 先用Selenium获取令牌 python get_token.py --site Beijing --year 2020 token.txt # 使用令牌批量下载 while read url; do curl -s -k -o data/$(date %s).csv $url if (( $(jobs | wc -l) 4 )); then wait -n fi done token.txt4. 混合策略进阶技巧4.1 智能路由方案根据网络环境自动选择最优方案def download_strategy_selector(site, years): if is_campus_network(): # 教育网走CURL return curl_download(prepare_curl_params(site, years)) else: # 其他网络走Selenium with ChromeDriver() as driver: token get_selenium_token(driver, site, years) return threaded_download(token)4.2 错误处理机制针对常见问题的应对策略403 Forbidden更换User-Agent添加随机延迟404 Not Found重新获取令牌检查参数格式Timeout指数退避重试最多3次增强版下载函数def robust_download(url, retry3): for i in range(retry): try: with requests.Session() as s: s.headers.update({User-Agent: get_random_user_agent()}) resp s.get(url, timeout30) resp.raise_for_status() return resp.content except Exception as e: if i retry - 1: raise time.sleep(2 ** i random.random())5. 实战案例长三角地区数据采集最近帮某研究所搭建的自动化流程核心配置# config.yaml regions: - name: Yangtze_Delta bbox: [30.0, 119.0, 32.5, 122.0] years: [2015-2022] data_types: [AOD20, SDA20, FMF] strategy: hybrid output_dir: ./data/YRD执行效果自动识别区域内12个活跃站点按年分目录存储各站点数据失败任务自动重试并记录日志日均数据更新耗时约7分钟关键优化点使用Spatialite进行地理范围筛选采用Zstandard压缩存储原始数据集成Prometheus监控下载质量这个方案已经稳定运行6个月累计下载数据文件超过1.2TB。最大的收获是一定要为每个下载任务添加完整的元数据注释否则三个月后根本记不清某个数据文件的具体参数。我现在每个CSV文件头都自动写入这样的信息# Site: Shanghai # Period: 2020-01-01 to 2020-12-31 # DataType: AOD Level 2.0 # GeneratedAt: 2023-08-15T14:22:18Z # Checksum: sha256:9f86d08...

更多文章