导读:本期聚焦于赵景明创作的《R语言如何抓取API数据:分析XHR请求构造参数绕过前端限制》,敬请观看详情。网页上能看到的表格数据,背后往往是页面通过XHR请求从接口拿到的JSON。与其用爬虫硬解析HTML,不如直接分析浏览器开发者工具中的网络请求,找到真实接口地址和参数规律,再用R语言构造请求批量获取数据。本文从开发者工具抓包讲起,介绍如何识别关键XHR请求、分析分页与时间戳参数的构造逻辑,并用httr2与jsonlite两个包完成完整的请求、解析和数据落地流程,同时讨论请求头伪装、频率控制等注意事项,帮助绕开前端翻页和展示条数的限制,直接拿到结构化数据。

很多数据平台的网页只展示前几页或前几百条记录,想拿全量数据靠浏览器翻页几乎不现实。但如果打开浏览器开发者工具观察网络请求,会发现页面渲染的数据其实来自一个个XHR请求返回的JSON。只要找到这些接口的地址和参数规律,用R语言直接构造请求,就能绕开前端展示限制,拿到比页面上多得多的数据。下面这张示意图展示了从页面到接口的数据流向。

R语言如何抓取API数据:分析XHR请求构造参数绕过前端限制

用开发者工具定位真实的XHR接口

打开目标网页后按下F12,切换到网络面板,再刷新页面并触发一次查询或翻页操作。网络面板会列出页面发出的所有请求,其中类型为xhr或fetch的就是我们关心的异步请求。这些请求通常返回application/json格式的数据,与页面本身的HTML文档请求有明显区别。点击某个请求可以在响应预览中直接查看JSON结构,如果能看到页面表格中展示的数值,说明找对了接口。

定位接口时要重点关注三个部分:请求的URL路径、请求方法(GET还是POST)以及载荷或查询字符串中的参数。URL路径一般包含接口的功能标识,参数则决定了返回哪部分数据。例如分页参数page和pageSize控制返回第几页、每页多少条,时间范围参数控制数据区间。把一个请求的完整URL和参数抄下来,在浏览器新标签页直接访问,如果能返回同样的JSON,说明这是一个无需复杂认证的公开接口,抓取难度最低。

有些网站的接口参数看起来杂乱无章,混着时间戳、随机数和一串看不懂的编码。这时候可以多次触发同一操作,对比几次请求的参数差异。变化的部分往往就是分页序号、时间戳或签名,固定不变的则是接口版本号、平台标识等常量。把变化规律找出来,参数构造的思路就清晰了。

用httr2与jsonlite构造请求并解析数据

R语言中处理HTTP请求首选httr2包,它提供了链式语法的请求构建方式,配合jsonlite包解析JSON非常方便。以下示例演示如何请求一个典型的分页数据接口:

library(httr2)
library(jsonlite)

# 构造请求:设置地址、请求头和查询参数
resp <- request("https://api.ipipp.com/v1/market/list") |>
  req_headers(
    "User-Agent" = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
    "Referer" = "https://www.ipipp.com/data",
    "Accept" = "application/json"
  ) |>
  req_url_query(
    page = 1,
    pageSize = 500,
    sortBy = "date",
    order = "desc"
  ) |>
  req_perform()

# 解析返回的JSON为R对象
data <- resp |> resp_body_string() |> fromJSON(simplifyVector = FALSE)
str(data, max.level = 2)

这段代码里有几个关键点值得展开。首先是请求头:很多接口会校验User-Agent和Referer,直接用R默认的请求头可能被拒绝。把浏览器中看到的请求头原样复制过来,通常就能通过基本校验。其次是pageSize参数,前端页面可能固定每页20条,但接口本身往往支持更大的值。试着把pageSize调到500甚至1000,如果服务器正常返回,一次请求就能顶前端翻几十页,这正是绕过前端限制的核心技巧。

对于POST请求的接口,参数要放在请求体中传递,httr2使用req_body_json或req_body_form函数来设置。带签名的接口还会要求在请求头或参数中附带token,这个token可能来自首次访问页面时的某个请求,需要在R中先请求一次拿token,再带着token去请求数据接口:

# POST接口示例:先获取token,再携带token请求数据
token_resp <- request("https://api.ipipp.com/v1/auth/guest") |>
  req_perform()
token <- token_resp |> resp_body_string() |> fromJSON()$token

data_resp <- request("https://api.ipipp.com/v1/market/detail") |>
  req_headers("Authorization" = paste("Bearer", token)) |>
  req_body_json(list(code = "000001", start = "2024-01-01", end = "2024-12-31")) |>
  req_perform() |>
  resp_body_string() |>
  fromJSON()

# 转为数据框便于后续处理
df <- as.data.frame(do.call(rbind, data_resp$rows))

解析JSON时建议先用str函数查看结构层次,找到真正装数据的字段,通常在rows、list、data等键下面。JSON嵌套结构转数据框时可能出现列表列,用unnest或循环展平即可。

分页循环、反爬应对与数据落地

单次请求只能拿到一页数据,批量抓取需要循环构造分页参数。循环之前最好先探测总记录数:很多接口返回结果中带有total或totalCount字段,用它除以每页条数就能算出总页数,避免盲目翻页触发空请求。下面是完整的批量抓取框架:

library(httr2)
library(jsonlite)
library(dplyr)

all_rows <- list()
page <- 1

repeat {
  result <- request("https://api.ipipp.com/v1/market/list") |>
    req_headers("User-Agent" = "Mozilla/5.0", "Referer" = "https://www.ipipp.com/data") |>
    req_url_query(page = page, pageSize = 500) |>
    req_perform() |>
    resp_body_string() |>
    fromJSON(simplifyVector = FALSE)

  rows <- result$rows
  if (length(rows) == 0) break   # 没有更多数据时停止
  all_rows[[page]] <- bind_rows(lapply(rows, as.data.frame))

  message("已抓取第 ", page, " 页,累计 ", nrow(all_rows[[page]]), " 条")
  Sys.sleep(runif(1, 1, 3))      # 随机延迟,降低被封风险
  page <- page + 1
}

final_data <- bind_rows(all_rows)
write.csv(final_data, "market_data.csv", row.names = FALSE)

反爬方面有几个实用经验。第一是频率控制,请求之间加入随机延迟,比固定间隔更不容易被识别为机器行为。第二是异常处理,网络抖动或服务器限流会让某次请求失败,用httr2的req_retry或tryCatch包裹请求,失败后重试几次而不是直接中断整个流程。第三是参数签名问题,如果发现请求参数中有一个随内容变化的加密字段,这类接口的逆向成本较高,可以考虑用R的reticulate包调用现成的Python签名库,或者退而求其次减少抓取量。

还有一个容易被忽略的细节:会话保持。部分接口依赖Cookie识别会话,httr2通过req_cookie_preserve把响应中的Cookie保留并带到后续请求中,模拟浏览器行为。抓取大量数据后建议把原始JSON先存档到本地,解析和清洗放在后续步骤进行,这样即使解析逻辑有误也不必重新请求接口。

合规边界与抓取思路总结

直接请求接口本质上是访问网站已经对外开放的数据通道,但合规性仍需谨慎对待。抓取前先查看网站的robots协议和服务条款,确认目标数据是否允许批量获取;只抓取公开的、非个人隐私的数据;控制请求频率,避免对服务器造成压力。商业数据平台的付费内容不要试图绕过授权,那已经超出技术讨论的范畴。

整体思路可以总结为四步:先用开发者工具找到XHR接口,再分析参数的构造规律,然后用httr2构造请求验证可行性,最后用循环和解析逻辑完成批量落地。相比传统的HTML解析方式,接口抓取拿到的是干净的结构化数据,没有解析页面结构的麻烦,数据字段也更稳定。掌握这套方法后,无论是金融行情、公开统计数据还是舆情信息,只要页面上有的数据,基本都能通过分析接口高效获取,让R语言真正成为数据获取到分析的一体化工具。

R语言API数据抓取XHR请求修改时间:2026-09-04 17:03:46

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260904/50363.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。