欧洲议会成员的相关信息分散在官方公开网页中,通过R语言的相关工具可以快速完成批量采集和结构化处理,避免手动复制粘贴的低效操作。本文将以欧洲议会官方公开成员列表页面为例,讲解完整的实现流程。

准备工作与依赖包安装
首先需要安装并加载本次爬取和整理数据需要用到的R包,主要包括网络请求、页面解析、数据清洗三类工具包,具体安装和加载代码如下:
# 安装所需依赖包
install.packages(c("httr", "rvest", "dplyr", "stringr"))
# 加载依赖包
library(httr)
library(rvest)
library(dplyr)
library(stringr)
发送网络请求获取网页内容
使用httr包的GET函数向目标网页发送请求,同时设置合理的请求头模拟浏览器访问,降低被反爬机制拦截的概率。这里以欧洲议会成员公开列表页为例,实际使用时替换为真实的目标URL即可:
# 设置请求头模拟浏览器
headers <- c(
"User-Agent" = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
)
# 发送请求获取网页内容
url <- "https://ipipp.com/meps/list"
response <- GET(url, add_headers(.headers = headers))
# 检查请求是否成功
if (status_code(response) == 200) {
page_content <- content(response, as = "text")
print("网页请求成功")
} else {
print(paste("请求失败,状态码:", status_code(response)))
}
解析网页提取成员信息
使用rvest包解析获取到的网页文本,通过CSS选择器定位成员信息所在的节点,提取姓名、党派、选区、任期等核心字段。如果页面结构有调整,只需要修改对应的选择器即可:
# 解析网页内容
page_html <- read_html(page_content)
# 提取成员列表节点
member_nodes <- page_html %>% html_nodes(".member-item")
# 循环提取每个成员的信息
member_data <- data.frame(
姓名 = character(),
党派 = character(),
选区 = character(),
任期开始时间 = character(),
stringsAsFactors = FALSE
)
for (node in member_nodes) {
name <- node %>% html_node(".member-name") %>% html_text() %>% str_trim()
party <- node %>% html_node(".member-party") %>% html_text() %>% str_trim()
constituency <- node %>% html_node(".member-constituency") %>% html_text() %>% str_trim()
term_start <- node %>% html_node(".member-term-start") %>% html_text() %>% str_trim()
# 将提取到的数据添加到数据框
member_data <- rbind(member_data, data.frame(
姓名 = name,
党派 = party,
选区 = constituency,
任期开始时间 = term_start,
stringsAsFactors = FALSE
))
}
# 查看前5条数据
head(member_data)
数据清洗与结构化整理
爬取到的原始数据可能存在缺失值、格式不统一等问题,需要使用dplyr和stringr包进行清洗,最终得到规整的结构化数据框:
# 去除重复数据
member_data <- member_data %>% distinct()
# 处理缺失值,将空字符串替换为NA
member_data[member_data == ""] <- NA
# 统一任期时间格式,去除多余字符
member_data$任期开始时间 <- member_data$任期开始时间 %>%
str_replace_all("[^0-9-]", "") %>%
str_trim()
# 按姓名排序
member_data <- member_data %>% arrange(姓名)
# 查看清洗后的数据维度
print(paste("清洗后数据共", nrow(member_data), "条,", ncol(member_data), "个字段"))
# 保存为CSV文件方便后续使用
write.csv(member_data, "european_parliament_members.csv", row.names = FALSE, fileEncoding = "UTF-8")
常见问题与优化建议
在实际爬取过程中可能会遇到一些问题,以下是常见的解决方案:
- 如果遇到请求被拦截,可以适当增加请求间隔时间,使用
Sys.sleep(runif(1, 1, 3))在每次请求之间随机暂停1到3秒 - 如果页面是动态加载的,普通的
GET请求无法获取完整内容,可以结合RSelenium包模拟浏览器渲染后再提取数据 - 如果成员信息分布在多个分页,可以提取分页链接后循环发送请求,将所有分页的数据合并后再整理
- 定期运行脚本时,可以增加增量更新逻辑,只爬取新增或变动的成员信息,减少不必要的请求
注意爬取公开数据时需要遵守目标网站的robots协议,不要频繁发送请求给服务器造成过大压力,仅将爬取的数据用于个人研究或学习用途。