You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于RSelenium提取Facebook广告库内嵌Leaflet SVG底层数据的技术问询

解决Facebook广告库数据提取与规整问题

针对你用RSelenium爬取Facebook广告库时遇到的文本杂乱、图表/SVG数据提取困难的问题,我整理了几个实用的解决方案,一步步帮你搞定:

一、把杂乱文本规整为DataFrame

你现在直接抓取整个元素的文本导致数据混乱,核心思路是精准定位每个字段的DOM元素,逐个提取后再组合成结构化数据:

  1. 避免依赖动态变化的class名(Facebook的class经常更新),改用基于文本内容的XPath定位,比如找包含"投放时间""受众"等关键词的元素及其兄弟节点。
  2. 循环遍历所有广告详情页,提取每个字段后存入列表,最后转成DataFrame。

示例代码:

library(RSelenium)
library(dplyr)
library(stringr)

# 初始化驱动(建议用chrome,稳定性更好)
rs <- rsDriver(browser = "chrome") # 若需指定Chrome版本,可添加chromever参数
remote <- rs$client
remote$navigate("https://www.facebook.com/ads/library/?active_status=all&ad_type=political_and_issue_ads&country=US&impression_search_field=has_impressions_lifetime&q=actblue&view_all_page_id=38471053686")

# 先获取所有"查看广告详情"按钮(XPath可根据页面实际调整)
ad_detail_buttons <- remote$findElements(using = "xpath", "//*[contains(text(), '查看广告详情')]")

ad_data_list <- list()

# 遍历每个广告详情
for(i in seq_along(ad_detail_buttons)){
  # 点击详情按钮
  ad_detail_buttons[[i]]$clickElement()
  Sys.sleep(2) # 等待页面加载
  
  # 提取单个广告的各个字段(用tryCatch避免元素不存在报错)
  ad_title <- tryCatch(
    remote$findElement(using = "xpath", "//*[contains(@class, '_7lq0')]")$getElementText()[[1]],
    error = function(e) NA
  )
  
  ad_run_dates <- tryCatch(
    remote$findElement(using = "xpath", "//*[contains(text(), '投放日期')]/following-sibling::div")$getElementText()[[1]],
    error = function(e) NA
  )
  
  ad_impressions <- tryCatch(
    remote$findElement(using = "xpath", "//*[contains(text(), '展示次数')]/following-sibling::div")$getElementText()[[1]] %>% str_remove_all("[^0-9]") %>% as.numeric(),
    error = function(e) NA
  )
  
  # 存入列表
  ad_data_list[[i]] <- tibble(
    title = ad_title,
    run_dates = ad_run_dates,
    impressions = ad_impressions
  )
  
  # 返回列表页
  remote$goBack()
  Sys.sleep(2)
  # 重新获取按钮(页面刷新后原元素失效)
  ad_detail_buttons <- remote$findElements(using = "xpath", "//*[contains(text(), '查看广告详情')]")
}

# 转成结构化DataFrame
ad_df <- bind_rows(ad_data_list)

二、提取图表(图片形式)的底层数据

Facebook广告库的图表看似是图片,其实大部分数据都藏在页面的script标签里的JSON中,不用OCR,直接解析即可:

  1. 找到包含图表数据的script标签(通常包含"adImpressions""demographics"等关键词)。
  2. 用正则提取出JSON片段,再用jsonlite解析成结构化数据。

示例代码:

library(jsonlite)

# 在广告详情页中,找到包含受众年龄性别数据的script
chart_script <- remote$findElement(using = "xpath", "//script[contains(text(), 'adImpressionsByAgeGender')]")$getElementText()[[1]]

# 提取JSON部分(根据实际内容调整正则匹配规则)
json_pattern <- "\\{\"adImpressionsByAgeGender\":.*?\\}"
json_str <- str_extract(chart_script, json_pattern)

# 解析JSON为结构化数据
chart_data <- fromJSON(json_str)

# 转成DataFrame
age_gender_df <- as.data.frame(chart_data$adImpressionsByAgeGender)

三、提取Leaflet SVG地图的底层数据

Leaflet地图的SVG元素会绑定数据到data-*属性,或者页面中存在对应的GeoJSON脚本,两种方式都可以提取:

方式1:从SVG元素的属性提取

library(rvest)

# 获取SVG的完整HTML
svg_html <- remote$findElement(using = "xpath", "//div[contains(@class, 'leaflet-container')]/svg")$getElementAttribute("outerHTML")[[1]]

# 用rvest解析SVG节点
svg_doc <- read_html(svg_html)
state_paths <- svg_doc %>% html_nodes("path")

# 提取每个州的展示数据
map_data <- tibble(
  state_code = html_attr(state_paths, "data-state"),
  impressions = html_attr(state_paths, "data-impressions") %>% as.numeric()
)

方式2:从页面的GeoJSON脚本提取

如果SVG的属性没有直接数据,找页面中存储地图数据的script标签:

map_script <- remote$findElement(using = "xpath", "//script[contains(text(), 'geoJsonData')]")$getElementText()[[1]]
map_json_str <- str_extract(map_script, "\\{\"geoJsonData\":.*?\\}")
map_geo_data <- fromJSON(map_json_str)

# 转成包含地理属性的DataFrame
map_df <- as.data.frame(map_geo_data$geoJsonData$features$properties)

四、实用注意事项

  • 反爬机制:Facebook会检测频繁的自动化操作,建议每次操作后加Sys.sleep(2-3),避免被限制访问。
  • 动态class名:尽量用基于文本或元素结构的XPath,不要依赖固定的class(比如_7kfh这种容易变动的命名)。
  • 元素加载延迟:用remote$waitForElement(using = "xpath", "你的XPath", timeout = 10)代替Sys.sleep(),更高效地等待元素加载完成。

内容的提问来源于stack exchange,提问作者Kim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 15:22:37