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

如何高效抓取欧盟青年志愿服务机会数据:基于官方API的结构化采集方案

阿静姑娘_5815

阿静姑娘_5815

发布时间:2026-04-13 21:54:04

|

215人浏览过

|

来源于php中文网

原创

如何高效抓取欧盟青年志愿服务机会数据:基于官方API的结构化采集方案

本文介绍一种绕过网页爬虫陷阱、直接调用欧盟青年门户(youth.europa.eu)官方搜索api的方法,以json格式批量获取志愿服务机会的标题、国家、起止日期、官网链接等结构化字段,并一键转换为pandas dataframe,安全、稳定、可扩展。

本文介绍一种绕过网页爬虫陷阱、直接调用欧盟青年门户(youth.europa.eu)官方搜索api的方法,以json格式批量获取志愿服务机会的标题、国家、起止日期、官网链接等结构化字段,并一键转换为pandas dataframe,安全、稳定、可扩展。

欧盟青年门户网站(youth.europa.eu)虽提供丰富的志愿服务机会信息,但其前端页面采用动态加载+稀疏ID编号(如 /solidarity/placement/39020_en),盲目遍历 1–100,000 ID 极不可靠:大量ID对应404页面,且关键字段(如起止日期)在部分页面缺失,导致 ValueError: not enough values to unpack 等解析异常——这正是原始代码报错的根本原因。

更优解是直接对接后端搜索API。该API由网站自身调用,返回标准JSON,字段完整、语义清晰、支持分页与过滤,完全规避HTML结构变动与反爬风险。

✅ 推荐方案:调用官方搜索API(无需Selenium/BeautifulSoup)

通过浏览器开发者工具(F12 → Network → Filter: XHR)可捕获真实请求地址。例如,访问 volunteering opportunities 页面 时,页面会发起如下API请求:

GET https://www.php.cn/link/033c253e16760c3b1de8b9c807e10bf7/d8/api/rest/eyp/v1/search_en?
  type=Opportunity
  &size=100
  &from=0
  &filters[status]=open
  &filters[date_end][operator]=>=
  &filters[date_end][value]=2024-03-14
  &filters[date_end][type]=must

该接口返回分页JSON数据,hits.hits 数组即为志愿服务机会列表,每个对象包含 title、country、date_start、date_end、website_url 等标准化字段。

?️ 完整可运行代码(含分页与错误处理)

import requests
import pandas as pd
from typing import List, Dict, Optional

def fetch_volunteer_opportunities(
    max_results: int = 1000,
    per_page: int = 100,
    end_date_from: str = "2024-03-14"
) -> pd.DataFrame:
    """
    从欧盟青年门户API批量获取志愿服务机会(结构化JSON)

    Args:
        max_results: 最大返回条目数(默认1000,可按需调整)
        per_page: 单页条目数(最大支持1000,建议≤100防超时)
        end_date_from: 筛选“截止日期 ≥ 该日期”的开放机会

    Returns:
        包含 title, country, date_start, date_end, website_url, url 等字段的DataFrame
    """
    base_url = "https://www.php.cn/link/033c253e16760c3b1de8b9c807e10bf7/d8/api/rest/eyp/v1/search_en"
    all_data = []

    for from_offset in range(0, max_results, per_page):
        params = {
            "type": "Opportunity",
            "size": per_page,
            "from": from_offset,
            "filters[status]": "open",
            "filters[date_end][operator]": ">=",
            "filters[date_end][value]": end_date_from,
            "filters[date_end][type]": "must"
        }

        try:
            response = requests.get(base_url, params=params, timeout=15)
            response.raise_for_status()
            data = response.json()

            hits = data.get("hits", {}).get("hits", [])
            if not hits:
                print(f"⚠️  第 {from_offset//per_page + 1} 页无数据,可能已达末页")
                break

            # 展平嵌套结构(_source 是实际数据载体)
            flattened = [
                {**hit.get("_source", {}), "url": f"https://www.php.cn/link/033c253e16760c3b1de8b9c807e10bf7/solidarity/placement/{hit.get('_id')}_en"}
                for hit in hits
            ]
            all_data.extend(flattened)

            print(f"✅ 已获取 {len(all_data)} 条机会(第 {from_offset//per_page + 1} 页)")

        except requests.exceptions.RequestException as e:
            print(f"❌ 请求失败(偏移量 {from_offset}): {e}")
            continue
        except KeyError as e:
            print(f"❌ 解析异常(偏移量 {from_offset}): 缺失字段 {e}")
            continue

    if not all_data:
        print("⚠️  未获取到任何有效数据,请检查网络或API是否变更")
        return pd.DataFrame()

    # 转为DataFrame并选择核心字段(兼容性更强)
    df = pd.json_normalize(all_data)
    desired_cols = [
        "title", "country", "date_start", "date_end", 
        "website_url", "url", "description"
    ]
    return df.reindex(columns=[c for c in desired_cols if c in df.columns])

# 执行采集(示例:获取最多500条当前开放机会)
df = fetch_volunteer_opportunities(max_results=500)
print(f"\n? 总计采集 {len(df)} 条志愿服务机会:")
print(df[["title", "country", "date_start", "date_end", "website_url"]].head())

⚠️ 关键注意事项

  • 尊重 robots.txt 与服务条款:该API属公开接口,但请控制请求频率(建议 ≥1秒间隔),避免对服务器造成压力。
  • 字段命名以API响应为准:country 通常为ISO代码(如 "DE"),website_url 可能为空;description 字段含HTML标签,如需纯文本可用 BeautifulSoup(description, "html.parser").get_text() 清洗。
  • 分页逻辑:from 参数表示跳过的记录数(非页码),size 为每页数量。若需全部数据,可循环直到返回空 hits。
  • 容错设计:代码已内置HTTP异常、JSON解析异常、字段缺失处理,避免单条失败中断整个流程。

✅ 输出示例(DataFrame片段)

title country date_start date_end website_url
European Voluntary Service in Greece GR 2024-06-01 2025-05-31 https://www.php.cn/link/2e5cbd954b383fc43f19deb0e2d1e3da
Youth Exchange in Spain ES 2024-09-15 2024-12-15 https://www.php.cn/link/41a555c143ddad0bc1d705b05e477867

此方法不仅解决原始问题中的404与解析崩溃,更将开发效率提升一个数量级——无需维护CSS选择器、不惧HTML重构、天然支持增量更新与数据校验。对于公益组织、教育机构或青年项目协调员而言,这是构建可持续志愿服务数据库的可靠起点。

热门AI工具

更多
Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

豆包大模型

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

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

DeepSeek

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

WorkBuddy

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

创客贴AI

创客贴AI是一款AI图像与设计工具,AI辅助的智能在线设计工具。

SkildArt
SkildArt Hot

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

讯飞绘文

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

相关专题

更多
免费爬虫工具有哪些
免费爬虫工具有哪些

免费爬虫工具有Scrapy、Beautiful Soup、ParseHub、Octoparse、Webocton Scriptly、RoboBrowser和Goutte。更多关于免费爬虫工具的问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

5293

2023.11.10

Python爬虫获取数据的方法
Python爬虫获取数据的方法

Python爬虫可以通过请求库发送HTTP请求、解析库解析HTML、正则表达式提取数据,或使用数据抓取框架来获取数据。更多关于Python爬虫相关知识。详情阅读本专题下面的文章。php中文网欢迎大家前来学习。

693

2023.11.13

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

40

2026.10.28

Vite 如何搭配 Vue.js
Vite 如何搭配 Vue.js

Vite搭配Vue.js专题汇集创建Vue 3项目、配置开发环境、路径别名、Vue插件、代理、多环境构建与调试的已审核文章,帮助读者完成从初始化到日常开发的配置。

20

2026.10.28

Vite 项目目录怎么看
Vite 项目目录怎么看

Vite项目目录专题汇集入口文件、src源码、public静态资源、路径别名、项目根目录和构建输出目录相关的已审核文章,帮助读者理解各文件夹的用途与引用方式。

0

2026.10.28

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

120

2026.10.22

Gradle Wrapper配置教程
Gradle Wrapper配置教程

本专题介绍Gradle Wrapper的基本作用,涵盖文件组成、生成方法、版本配置和任务调用,帮助你理解项目如何使用指定的Gradle版本,减少不同开发环境带来的构建差异。

80

2026.10.22

Golangci-lint检查器使用教程
Golangci-lint检查器使用教程

本专题整理Golangci-lint常用Linters的用途与配置方法,覆盖错误处理、无效代码、安全、复杂度、命名和依赖检查,帮助项目合理选规则。

60

2026.10.22

Gradle怎么构建Java项目
Gradle怎么构建Java项目

本专题介绍Gradle Java项目构建方法,涵盖Java插件配置、依赖声明、源码编译、测试执行和打包检查,帮助你理解各阶段的任务关系,逐步完成项目构建。

40

2026.10.22

热门下载

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

精品课程

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

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