【问题标题】:Use R to fill html form and download the resulting file使用 R 填写 html 表单并下载生成的文件
【发布时间】:2026-01-27 00:45:01
【问题描述】:

我花了一天时间在互联网上搜索有关如何执行此操作的示例,但是我仍在绕圈子,可以使用一点方向。我对 html 很陌生,有基本的 R 编码经验,对任何其他编码语言的经验很少。

我有 500 多个(可能更多)气象站的列表,我想从这个网站 (https://fam.nwcg.gov/fam-web/kcfast/html/wxhmenu.htm) 下载 FW13 格式的数据。在浏览器中,您填写表单并提交,它会开始将 FW13 文件下载到我的默认下载文件夹中。

我的目标是使用 R 填写 html 表单,提交它,然后接受将生成的文件下载到定义的位置。表单本身由文本和单选按钮组成。以下是单个查询的示例:

站号:020207

开始日期:2000-01-01

结束日期:2017-12-31

观察类型:每小时

计划选项:立即运行

我钻了 RCurl 和 rvest 包的兔子洞,甚至开始尝试 rSelenium。我看到的大多数示例都是直接从网站上抓取信息,但我只想接受下载生成的文件。

如果我可以只提交一个请求并下载一个文件,我相信我可以弄清楚如何使用站点 ID 列表循环来实现我所需要的。

对于此处没有任何示例代码,我深表歉意。我所有的试验都是在黑暗中盲目拍摄,我什至不确定我是否为这项任务使用了正确的软件包。非常感谢任何帮助或指导!

【问题讨论】:

    标签: r rvest rcurl rselenium


    【解决方案1】:
    library(httr)
    library(tidyverse)
    
    POST(
      url = "https://fam.nwcg.gov/FAMCognosRESTServices/rest/cognos/anonymous/reports/FW13",
      encode = "json",
      body = list(
        p_end_date = "2017-12-31",
        p_obs_type = "Hourly",
        p_start_date = "2000-01-01",
        p_station_id = "170701",
        reportName = "",
        reportSched = FALSE,
        reportTime = ""
      )
    ) -> res
    
    out <- content(res)
    
    readr::read_fwf(
      file = out$report, 
      fwf_widths(
        widths = c(3, 6, 8, 4, 1, 1, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 5, 1, 2, 2, 1, 1, 1, 4, 3, 3, 1),
        col_names = c("w13", "sta_id", "obs_dt", "obs_tm", "obs_type", "sow", "dry_temp", "rh", 
                      "wind_dir", "wind_sp", "fuel_10hr", "temp_max", "temp_min", "rh_max", 
                      "rh_min", "pp_dur", "pp_amt", "wet", "grn_gr", "grn_sh", "moist_tpe", 
                      "meas_type", "season_cd", "solar_radiation", "wind_dir_peak",
                      "wind_speed_peak", "snow_flg")
      ),
      skip = 1
    ) %>% 
      glimpse()
    ## Observations: 1,059
    ## Variables: 27
    ## $ w13             <chr> "W13", "W13", "W13", "W...
    ## $ sta_id          <int> 170701, 170701, 170701,...
    ## $ obs_dt          <int> 20000102, 20000103, 200...
    ## $ obs_tm          <int> 1300, 1300, 1300, 1300,...
    ## $ obs_type        <chr> "O", "O", "O", "O", "O"...
    ## $ sow             <int> 3, 1, 4, 0, 1, 5, 1, 7,...
    ## $ dry_temp        <int> 44, 40, 48, 26, 25, 37,...
    ## $ rh              <int> 66, 50, 100, 51, 53, 93...
    ## $ wind_dir        <int> 230, 360, 230, 360, 120...
    ## $ wind_sp         <int> 2, 10, 13, 14, 5, 0, 9,...
    ## $ fuel_10hr       <int> NA, NA, NA, NA, NA, NA,...
    ## $ temp_max        <int> 48, 52, 51, 54, 29, 37,...
    ## $ temp_min        <int> 10, 36, 28, 23, 8, 22, ...
    ## $ rh_max          <int> 100, 100, 100, 100, 80,...
    ## $ rh_min          <int> 60, 50, 100, 51, 38, 93...
    ## $ pp_dur          <int> 0, 0, 13, 8, 0, 8, 0, 0...
    ## $ pp_amt          <int> 0, 0, 150, 1020, 0, 100...
    ## $ wet             <chr> "N", "N", "Y", "Y", "N"...
    ## $ grn_gr          <chr> NA, NA, NA, NA, NA, NA,...
    ## $ grn_sh          <chr> NA, NA, NA, NA, NA, NA,...
    ## $ moist_tpe       <int> 2, 2, 2, 2, 2, 2, 2, 2,...
    ## $ meas_type       <int> 1, 1, 1, 1, 1, 1, 1, 1,...
    ## $ season_cd       <chr> NA, NA, NA, NA, NA, NA,...
    ## $ solar_radiation <chr> NA, NA, NA, NA, NA, NA,...
    ## $ wind_dir_peak   <chr> NA, NA, NA, NA, NA, NA,...
    ## $ wind_speed_peak <chr> NA, NA, NA, NA, NA, NA,...
    ## $ snow_flg        <chr> "N", "N", "N", "N", "N"...
    

    【讨论】:

    • 这很棒,完全符合我的需要。谢谢!
    • 我正在尝试挑选一些代码来真正理解它,我有几个问题(如果我的任何假设有误,请纠正我): - POST 函数是用于向服务器发送请求,类似于在 Web 浏览器中单击“提交”按钮? - 你如何确定在 POST 函数中使用的 url? - 在正文中,不同的名称(例如“p_end_date”)是通过检查网站的 html 并找出用户可以设置的每个查询的名称来确定的?
    • 在您选择的浏览器中打开开发者工具(如果不是全部的话,大多数都有)。重新加载主表单页面。输入数据并提交。查看网络标签。
    • 这也是另一种方式youtube.com/watch?v=thr0vFRtK5g