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

使用R的httr包POST爬取数据时偶发失败的问题排查

解决R中httr POST请求oip.nypdonline.org的不稳定问题

问题背景

使用R的httr包向https://oip.nypdonline.org/api/reports/1/datasource/list发送POST请求抓取公开警务统计数据时,代码运行不稳定,偶发HTTP 500错误或**"Username字段必填"**错误。简化测试代码如下:

url <- "https://oip.nypdonline.org/api/reports/1/datasource/list"
payload <- '{filters: [{key: "@TAXID", label: "TAXID", values: ["940123"]}]}'
response <- httr::POST(url, content_type("application/json"), body = payload)
http_error(response)

发现先在浏览器打开对应页面(如https://oip.nypdonline.org/view/1/@TAXID=940123)后,代码常能正常运行,但仍不规律。尝试过使用handle、VPN、重启R,也尝试添加BNI_persistence、user会话cookie,但SetCookies()无效。verbose输出的"WARNING: failed to open cookie file"在成功和失败时均出现,排除其为直接原因。无法确定是cookie问题还是R/httr的隐藏存储机制导致偶发失败,需要找到模拟浏览器请求的解决方法。

模拟浏览器请求的解决方法

1. 先通过GET请求获取有效会话cookie

直接复制cookie容易过期,不如先模拟浏览器访问目标页面,让服务器生成有效会话cookie,再复用该会话发送POST请求:

library(httr)

# 初始化会话handle,用于保持cookie
session_handle <- handle("https://oip.nypdonline.org")

# 先GET访问页面,触发服务器设置会话cookie
GET("https://oip.nypdonline.org/view/1/@TAXID=940123", handle = session_handle)

# 发送POST请求,handle会自动携带已获取的cookie
url <- "https://oip.nypdonline.org/api/reports/1/datasource/list"
payload <- '{filters: [{key: "@TAXID", label: "TAXID", values: ["940123"]}]}'
response <- POST(url, content_type("application/json"), body = payload, handle = session_handle)

# 检查请求状态
http_error(response)
# 解析返回内容
content(response, "parsed")

2. 严格遵循标准JSON格式

原payload使用的是非标准JSON(键名未加双引号),部分服务器可能对格式敏感导致偶发错误,建议用jsonlite生成标准JSON:

library(httr)
library(jsonlite)

# 用R列表构造参数,再转换为标准JSON
payload_list <- list(
  filters = list(
    list(key = "@TAXID", label = "TAXID", values = list("940123"))
  )
)
payload_json <- toJSON(payload_list, auto_unbox = TRUE)

# 复用之前的会话handle发送请求
response <- POST(url, content_type("application/json"), body = payload_json, handle = session_handle)

3. 完整模拟浏览器请求头

服务器可能会验证请求头的完整性,从浏览器开发者工具(F12-网络面板)复制成功请求的所有请求头,添加到httr请求中:

library(httr)

# 从浏览器复制的请求头,替换为实际值
browser_headers <- add_headers(
  `User-Agent` = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
  `Referer` = "https://oip.nypdonline.org/view/1/@TAXID=940123",
  `Accept` = "application/json, text/plain, */*",
  `Accept-Language` = "zh-CN,zh;q=0.9",
  `Origin` = "https://oip.nypdonline.org",
  `Sec-Fetch-Dest` = "empty",
  `Sec-Fetch-Mode` = "cors",
  `Sec-Fetch-Site` = "same-origin"
)

# 结合会话handle和请求头发送请求
response <- POST(url, browser_headers, content_type("application/json"), body = payload_json, handle = session_handle)

4. 添加重试机制处理偶发错误

针对偶发的HTTP 500错误,用purrr实现自动重试逻辑:

library(httr)
library(purrr)

# 定义带重试的安全请求函数
safe_post <- safely(POST)
retry_post <- insistently(
  safe_post,
  rate_backoff(pause_base = 1, pause_cap = 5, max_times = 3)
)

# 执行带重试的请求
result <- retry_post(url, browser_headers, content_type("application/json"), body = payload_json, handle = session_handle)

# 处理结果
if (!is.null(result$result) && !http_error(result$result)) {
  data <- content(result$result, "parsed")
} else {
  message("请求失败:", result$error$message)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 01:02:11