使用R语言爬取加拿大人口金字塔各年份性别年龄分布数据
如何用R获取加拿大统计局人口金字塔页面1851-2043全年份性别-年龄分布数据?
我正在使用R编程语言,需要从加拿大统计局的加拿大历史人口金字塔页面获取下拉菜单中1851-2043所有年份的性别-年龄分布数据,期望输出格式如下:
year gender age percent_of_population 1 1975 Male 25 3% 2 1975 Female 25 2% 3 1975 Male 26 1% 4 1975 Female 26 2% 5 .... .... ... ... 6 1976 Male 25 4% 7 1976 Female 25 3% 8 1976 Male 26 2% 9 1976 Female 26 1% 10 ... ... .... ...
目前未找到可直接下载全年份数据的按钮,查看网页源码也未发现可用的直接数据标签,请问如何解决该问题?是否可以使用Selenium实现?
解决方案:使用R结合Selenium实现数据抓取
完全可以用Selenium解决这个问题——因为页面数据是动态加载的,需要模拟用户选择年份的交互操作来获取对应数据。以下是具体实现步骤:
1. 安装并加载所需包
先确保安装并加载RSelenium(用于模拟浏览器操作)和tidyverse(用于数据整理):
install.packages(c("RSelenium", "tidyverse")) library(RSelenium) library(tidyverse)
2. 初始化Selenium浏览器驱动
启动Chrome浏览器(如需用Firefox,可调整对应驱动参数):
# 启动浏览器驱动 rD <- rsDriver(browser = "chrome", port = 4567L) remDr <- rD[["client"]] # 访问目标页面 url <- "https://www12.statcan.gc.ca/census-recensement/2021/dp-pd/dv-vd/pyramid/index-en.htm" remDr$navigate(url)
3. 循环遍历年份并抓取数据
定位年份下拉菜单,提取所有目标年份,逐个选择后抓取对应性别-年龄数据:
# 定位年份下拉菜单元素 year_select <- remDr$findElement(using = "id", value = "yearSelect") # 获取所有年份选项文本 year_options <- year_select$findChildElements(using = "tag name", value = "option") %>% sapply(function(x) x$getElementText()) %>% unlist() # 筛选1851-2043的目标年份 target_years <- year_options[year_options >= "1851" & year_options <= "2043"] # 初始化空数据框存储结果 final_data <- data.frame() # 循环处理每个年份 for (year in target_years) { # 选择当前年份 year_select$sendKeysToElement(list(year)) # 等待页面加载数据(可根据网络速度调整等待时间) Sys.sleep(2) # 提取男性年龄组和占比数据 male_ages <- remDr$findElements(using = "css selector", value = ".male .age-group") %>% sapply(function(x) x$getElementText()) %>% unlist() male_percents <- remDr$findElements(using = "css selector", value = ".male .percent") %>% sapply(function(x) x$getElementText()) %>% unlist() # 提取女性年龄组和占比数据 female_ages <- remDr$findElements(using = "css selector", value = ".female .age-group") %>% sapply(function(x) x$getElementText()) %>% unlist() female_percents <- remDr$findElements(using = "css selector", value = ".female .percent") %>% sapply(function(x) x$getElementText()) %>% unlist() # 整理男性数据为数据框 male_df <- data.frame( year = year, gender = "Male", age = male_ages, percent_of_population = male_percents, stringsAsFactors = FALSE ) # 整理女性数据为数据框 female_df <- data.frame( year = year, gender = "Female", age = female_ages, percent_of_population = female_percents, stringsAsFactors = FALSE ) # 合并当前年份数据到总结果 final_data <- rbind(final_data, male_df, female_df) # 打印进度 cat("已完成年份:", year, "\n") }
4. 数据格式调整(可选)
如果需要将年龄范围(如"0-4")转为单年龄数值,可添加以下处理:
# 示例:提取年龄范围的起始值作为年龄列数值 final_data <- final_data %>% mutate(age = str_extract(age, "^\\d+") %>% as.integer())
5. 保存数据并关闭浏览器
# 保存为CSV文件 write.csv(final_data, "canada_population_pyramid_data.csv", row.names = FALSE) # 关闭浏览器和驱动 remDr$close() rD$server$stop()
注意事项
- 页面元素的CSS选择器可能随网站更新变化,若运行出错,需用浏览器开发者工具重新定位元素。
- 可根据网络速度调整
Sys.sleep()的等待时间,确保数据完全加载后再提取。 - 频繁请求可能触发反爬机制,建议适当增加等待间隔,避免被限制访问。
内容的提问来源于stack exchange,提问作者stats_noob
相关产品推荐
相关产品推荐

