我正在尝试学习如何使用RCurl(或其他合适的R包,如果我错误地认为RCurl是正确的工具)来自动化将搜索词提交到Web表单并将搜索结果放入的过程一个数据文件。我正在处理的具体问题如下:
我有一个数据文件,给出了几辆汽车的车牌号码(LPN)和车辆识别号码(VIN)。加州汽车部门(DMV)有一个网页搜索表单,您可以在其中输入LPN和VIN的最后五位数字,并返回2010年或2009年的车辆牌照费(VLF)付款(有一个选择器)在输入表格上也是如此)。 (仅供参考:这是一个研究项目,用于查看车辆制造,型号和型号年份的VLF支付分布)
我可以完成为每辆车手动输入数据的繁琐过程,然后手动将结果输入电子表格。但这是21世纪,我想尝试自动化这个过程。我想编写一个脚本,将每个LPN和VIN提交到DMV Web表单,然后将结果(VLF支付)放入我的数据文件中的新VLF变量中,重复执行此操作直到它到达列表末尾LPN和VIN。 (顺便说一句,DMV网络表格在这里: https://www.dmv.ca.gov/FeeCalculatorWeb/vlfForm.do)。
我的计划是使用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和网络抓取,我不知道下一步该做什么。
首先,有人知道为什么我的getHTMLFormDescription()调用出错吗?或者,是否有另一种方法可以找出输入字段的名称?
其次,您能否建议一些示例代码来帮助我开始实际提交LPN和VIN并检索输出? getForm()或postForm()是正确的方法还是我应该做其他事情?如果要提交一些真正的LPN-VIN组合会有所帮助,这里有三个:
LPN VIN
5MXH018 30135
4TOL562 74735
5CWR968 11802
最后,因为你可以看到我是一个完整的新手,你是否有我需要学习的建议,以便熟练掌握这种网络抓取以及如何学习它(在R或用另一种语言)?对网站,书籍,列表服务器,其他StackOverflow问题等的具体建议会很棒。
感谢您的帮助。
答案 0 :(得分:5)
根据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))
答案 1 :(得分:4)
只需使用http而不是https,这应该可以解决您的问题。以下是您尝试此操作时获得的输出
forms = getHTMLFormDescription("http://www.dmv.ca.gov/wasapp/FeeCalculatorWeb/vlfForm.do",
dropButtons = TRUE)
[[1]] HTML表单:http://search.ca.gov/search 问:[搜索DMV网站]
$ feeRequestForm
HTML表单:http://www.dmv.ca.gov/wasapp/FeeCalculatorWeb/vlfFees.do
vehicleLicense:[]
vehicleTaxYear:
vehicleVin:[]
以下是如何填写表单并从雅虎体育页面获取数据表的示例。
# 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);
我将此应用于您指定的网页,但由于某种原因,表单元素VehicleTaxYear返回错误,导致错误。对HTML表单有更深入了解的人将能够指导您如何调试此错误。
希望这很有用
EDIT。我修正了一个错误。它应该是createFunction(forms[[3]])
,因为我们只对第三种形式感兴趣。
答案 2 :(得分:4)
上述评论的详细信息:
vehicleLicense
和vehicleVin
之后),readHTMLTable
调用修改后的网址,即可为您提供所需数据集的精彩数据框。所以:
library(XML)
datas <- readHTMLTable("http://www.dmv.ca.gov/wasapp/FeeCalculatorWeb/vlfFees.do?method=calculateVlf&su%C2%ADbmit=Determine%20VLF&vehicleLicense=5CWR968&vehicleTaxYear=2010&vehicleVin=11802")
并获得表格所需的值,如上所述@Rguy:
processed <- datas[[5]][[1]]
paid <- datas[[5]][[2]]
refund <- datas[[5]][[3]]
通过这个基本示例,您可以轻松地编写一个获取所有必需数据的循环,但不要贪婪,并且不要在没有睡眠调用的情况下循环(请参阅:Sys.sleep
)。我每分钟只能拿一个盘子,这肯定不会打扰服务器。
答案 3 :(得分:2)
我打算在原帖后发表此评论,但声誉不足。
我使用了@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]]
简而言之,readHTMLTable命令对格式化HTML代码非常有用 我是第二个eipi10关于daroczig如何获得网址的请求。