如何使用R自动化对web搜索表单的多个请求

如何使用R自动化对web搜索表单的多个请求,r,web-scraping,R,Web Scraping,我正在尝试学习如何使用RCurl(如果我不认为RCurl是正确的工具,那么可以使用其他合适的R包)来自动化将搜索词提交到web表单并将搜索结果放入数据文件的过程。我正在研究的具体问题如下: 我有一个数据文件,给出了几辆汽车的车牌号(LPN)和车辆识别号(VIN)。加州机动车管理局(DMV)有一个网页搜索表单,您可以在其中输入LPN和VIN的最后五位数字,然后返回2010年或2009年的车辆牌照费(VLF)付款(输入表单上也有一个选择器)。(仅供参考:这是一个研究项目,旨在研究车辆制造商、车型和车

我正在尝试学习如何使用RCurl(如果我不认为RCurl是正确的工具,那么可以使用其他合适的R包)来自动化将搜索词提交到web表单并将搜索结果放入数据文件的过程。我正在研究的具体问题如下:

我有一个数据文件,给出了几辆汽车的车牌号(LPN)和车辆识别号(VIN)。加州机动车管理局(DMV)有一个网页搜索表单,您可以在其中输入LPN和VIN的最后五位数字,然后返回2010年或2009年的车辆牌照费(VLF)付款(输入表单上也有一个选择器)。(仅供参考:这是一个研究项目,旨在研究车辆制造商、车型和车型年的VLF付款分布)

我可以经历手动输入每辆车的数据,然后手动将结果输入电子表格的繁琐过程。但现在是21世纪,我想尝试自动化这个过程。我想编写一个脚本,将每个LPN和VIN提交到DMV web表单,然后将结果(VLF付款)放入我的数据文件中的新VLF变量中,重复执行此操作,直到到达LPN和VIN列表的末尾。(顺便说一句,DMV网络表单如下: )

我的计划是使用getHTMLFormDescription()(在RHTMLForms包中)查找输入字段的名称,然后使用getForm()或postForm()(在RCurl包中)检索输出。不幸的是,我在第一步就被卡住了。下面是我使用的R命令和输出:

> forms = getHTMLFormDescription("https://www.dmv.ca.gov/FeeCalculatorWeb/vlfForm.do")
Error in htmlParse(url, ...) : 
  File https://www.dmv.ca.gov/FeeCalculatorWeb/vlfForm.do does not exist 
不幸的是,由于对R比较陌生,对HTTP和web抓取几乎完全陌生,我不知道下一步该怎么做

首先,有人知道我在getHTMLFormDescription()调用中出错的原因吗?或者,是否有其他方法来计算输入字段的名称

第二,您能推荐一些示例代码来帮助我开始实际提交LPN和VIN并检索输出吗?getForm()或postForm()是正确的方法还是我应该做其他事情?如果提交一些真实的LPN-VIN组合会有所帮助,这里有三个:
LPN VIN
5MXH018 30135
4TOL562 74735
5CWR968 11802

最后,既然你可以看到我在这方面是一个完全的新手,你有什么建议,我需要学习,以成为这种类型的网页抓取熟练,以及如何去学习它(在R或其他语言)?对网站、书籍、ListServ、其他StackOverflow问题等的具体建议将非常好


谢谢您的帮助。

只需使用http而不是https,这将解决您的问题。这是您尝试此操作时得到的输出

forms = getHTMLFormDescription("http://www.dmv.ca.gov/wasapp/FeeCalculatorWeb/vlfForm.do",  
   dropButtons = TRUE)
[[1]] HTML格式: q:[搜索DMV站点]

$feeRequestForm HTML格式: 车辆许可证:[]
车辆年度: 李文:[]

下面是一个如何填写表单并从yahoo sports页面获取数据表的示例

# get form description
url   = 'http://ca.sports.yahoo.com/nhl/stats/byteam?cat=teamstats&sort=404'
forms = getHTMLFormDescription(url);

# create a function using form description, to query the url
efun  = createFunction(forms[[3]]);

# extract webpage by passing required arguments to function
page  = efun(year = 'season_2009', conference = 'Eastern');

# parse webpage and return html tree
doc   = htmlTreeParse(page, asText = T, useInternalNodes = T);

# extract table from the html tree
tab   = readHTMLTable(doc);
我将此应用于您指定的网页,但由于某些原因,表单元素VehicleAxYear返回不正确,从而导致错误。对HTML表单有更深入了解的人将能够指导您如何调试此错误

希望这是有用的


编辑。我修正了一个错误。它应该是
createFunction(forms[[3]])
,因为我们只对第三种形式感兴趣。

我本想在最初的帖子之后发表评论,但没有足够的声誉

我使用@daroczig提供的URL通过执行以下操作获取eipi10想要的实际数据:

datas <- readHTMLTable("http://www.dmv.ca.gov/wasapp/FeeCalculatorWeb/vlfFees.do?method=calculateVlf&su%C2%ADbmit=Determine%20VLF&vehicleLicense=5CWR968&vehicleTaxYear=2010&vehicleVin=11802")
processed <- datas[[5]][[1]]
paid <- datas[[5]][[2]]
refund <- datas[[5]][[3]]

data以上我的评论的细节:

  • 使用以下命令启动Firefox:)
  • 在表格中填写一对所需的车牌号等,然后单击提交(“确定VLF”)
  • 单击Firebug中的“Net”选项卡,检查发送到服务器的请求,如(对不起,匈牙利用户界面-但我希望您能理解这一点):

  • 您可以看到发送了POST请求,但也可以通过GET请求访问数据,因此只需右键单击“POST vlfFees.do”并选择“使用所有参数复制URL”,即可获得所需的URL
  • 您可以在URL中简单地使用所需的LPN和VIN修改URL(在
    vehicleLicense
    vehicleVin
    之后)
  • 只需使用包中的
    readHTMLTable
    调用修改后的URL,它将为您提供所需数据集的良好数据框架
因此:

库(XML)

datas除了daroczig和Rguy的建议之外,下面是一段简短的代码,用于自动化将数据提取到数据帧中的整个过程

# construct sample data frame with lpn, vpn and years
lpn  = rep(c('5MXH018', '4TOL562', '5CWR968'), 2);
vpn  = rep(c('30135', '74735', '11802'), 2);
year = c(rep(2009, 3), rep(2010, 3));
mydf = data.frame(lpn, vpn, year);

# construct function to extract data for one record
get_data = function(df){

  library(XML);
  # root url
  root = 'http://www.dmv.ca.gov/wasapp/FeeCalculatorWeb/vlfFees.do?method=calculateVlf&su%C2%ADbmit=Determine%20VLF'

  # construct url by adding lpn, year and vpn
  u = paste(root, '&vehicleLicense=', df$lpn, '&vehicleTaxYear=', 
            df$year, '&vehicleVin=',
      df$vpn, sep = "");

  # encode url correctly
  url  = URLencode(u);

  # extract data from the right table
  data = readHTMLTable(url)[[5]];

}

# apply function to every row of mydf and return data frame of results
library(plyr)
mydata = adply(mydf, 1, get_data);

# remove junk from column names
names(mydata) = gsub(':\302\240\302\240', '', names(mydata))

快速提示:安装firefox的firebug,并使用网络选项卡查看发布的表单实际通过网络发送的内容。该页面为我提供了一条包含上述代码的错误消息。但有一个提示:检查
http://www.dmv.ca.gov/wasapp/FeeCalculatorWeb/vlfFees.do?method=calculateVlf&submit=Determine%20VLF&vehicleLicense=5CWR968&vehicleTaxYear=2010&vehicleVin=11802
@daroczig谢谢!作为将来的参考,你怎么知道呢?另外,如果我使用您提供的url和getURL(url),它会返回页面的html,给出我想要的输出。你能推荐一个关于如何使用R从杂乱无章的html中选择所需文本(在本例中,是支付金额的值)的好教程吗(是的,我在这方面确实是个新手)?只需搜索
readHTMLTable
或查看手册(
?readHTMLTable
)。另外,
RCurl
除了
XML
包之外,还可能非常有用,如果处理那种数据,
rsjon
。@Ranmath我尝试了这个方法,但得到了以下错误:'>efun=createFunction(forms)writeFunction中的错误(formDescription,character(),url,con,verbose=verbose,:您应该在此处提供表单说明。请参阅
processed <- datas[[5]][[1]]
paid <- datas[[5]][[2]]
refund <- datas[[5]][[3]]
# construct sample data frame with lpn, vpn and years
lpn  = rep(c('5MXH018', '4TOL562', '5CWR968'), 2);
vpn  = rep(c('30135', '74735', '11802'), 2);
year = c(rep(2009, 3), rep(2010, 3));
mydf = data.frame(lpn, vpn, year);

# construct function to extract data for one record
get_data = function(df){

  library(XML);
  # root url
  root = 'http://www.dmv.ca.gov/wasapp/FeeCalculatorWeb/vlfFees.do?method=calculateVlf&su%C2%ADbmit=Determine%20VLF'

  # construct url by adding lpn, year and vpn
  u = paste(root, '&vehicleLicense=', df$lpn, '&vehicleTaxYear=', 
            df$year, '&vehicleVin=',
      df$vpn, sep = "");

  # encode url correctly
  url  = URLencode(u);

  # extract data from the right table
  data = readHTMLTable(url)[[5]];

}

# apply function to every row of mydf and return data frame of results
library(plyr)
mydata = adply(mydf, 1, get_data);

# remove junk from column names
names(mydata) = gsub(':\302\240\302\240', '', names(mydata))