调试基于RCurl的身份验证&;表单提交
SourceForge研究数据档案(SRDA)是我论文研究的数据来源之一。我在调试以下与SRDA数据收集相关的问题时遇到困难 从SRDA收集数据需要身份验证,然后使用SQL查询提交Web表单。成功处理查询后,系统生成一个带有查询结果的文本文件。在为SRDA数据收集测试R代码时,我更改了SQL请求,以确保结果文件正在重新生成。但是,我发现文件内容保持不变(对应于前面的查询)。我认为文件内容缺乏刷新可能是由于身份验证或查询表单提交失败。以下是代码()的调试输出: 以下是通过跟踪手动验证和手动数据请求表单提交获得的会话信息(1)在验证后和(2)在提交数据请求后: (1) “wiki_dbUserID=449;expires=Sun,2014年4月20日格林威治标准时间21:04:14; path=/wiki_dbUserName=Blekh;expires=Sun,2014年4月20日格林威治时间21:04:14; path=/wiki_dbToken=deleted;expires=Thu,2013年3月21日21:04:13 GMT” (2) wiki_db_session=aaed058f97059174a59effe44b137cbc; _ga=GA1.2.2065853334.1395410153;EDSSID=E24FF5ED891C28C61F2D1F8DEC42474;wiki_dbUserName=Blekh; wiki_dbLoggedOut=20140321210314;wiki_dbUserID=449调试基于RCurl的身份验证&;表单提交,r,forms,authentication,web-scraping,rcurl,R,Forms,Authentication,Web Scraping,Rcurl,SourceForge研究数据档案(SRDA)是我论文研究的数据来源之一。我在调试以下与SRDA数据收集相关的问题时遇到困难 从SRDA收集数据需要身份验证,然后使用SQL查询提交Web表单。成功处理查询后,系统生成一个带有查询结果的文本文件。在为SRDA数据收集测试R代码时,我更改了SQL请求,以确保结果文件正在重新生成。但是,我发现文件内容保持不变(对应于前面的查询)。我认为文件内容缺乏刷新可能是由于身份验证或查询表单提交失败。以下是代码()的调试输出: 以下是通过跟踪手动验证和手动数据请求
如果您能帮我解决代码中的问题,我将不胜感激 我进一步简化了代码:
library(httr)
base_url <- "http://srda.cse.nd.edu"
loginURL <- modify_url(
base_url,
path = "mediawiki/index.php",
query = list(
title = "Special:Userlogin",
action = "submitlogin",
type = "login",
wpName1 = USER,
wpPasswor1 = PASS
)
)
r <- POST(loginURL)
stop_for_status(r)
queryURL <- modify_url(base_url, path = "cgi-bin/form.pl")
query <- list(
uitems = "user_name",
utables = "sf1104.users a, sf1104.artifact b",
uwhere = "a.user_id = b.submitted_by AND b.artifact_id = 304727",
useparator = ":",
append_query = "1"
)
r <- POST(queryURL, body = query, multipart = FALSE)
stop_for_status(r)
库(httr)
下面对场景(错误情况)进行了说明
来自W3C RFC 2616-HTTP/1.1规范:
10.5服务器错误5xx
以数字“5”开头的响应状态代码表示
服务器知道它出错或无法执行的操作
执行请求。除非在响应HEAD请求时
服务器应该包含一个包含错误解释的实体
情况,以及它是暂时的还是永久的情况。使用者
代理应向用户显示任何包含的实体。这些反应
代码适用于任何请求方法
10.5.1 500内部服务器错误
服务器遇到意外情况,无法正常运行
满足要求
我对第10.5段的解释是,这意味着除了第10.5.1段中提供的解释之外,还应该对错误情况进行更详细的解释。然而,我认识到,状态代码500(第10.5.1段)的信息可能已经足够。欢迎任何一种解释的确认 终于,终于,终于!我已经找出了这个问题的原因,这个问题让我非常头痛(从比喻和字面上)。它迫使我花大量时间阅读各种互联网资源(包括许多问答),调试代码,与人交流。我花了很多时间,但没有白费,因为我学到了很多关于RCurl
、cookies、Web表单和HTTP
协议的知识
原因似乎比我想象的要简单得多。虽然表单提交失败的直接原因与cookie管理有关,但根本原因是使用了身份验证表单字段的错误参数名(id)。这两对非常相似,只需多出一个字符就可以触发整个问题
经验教训:当面临问题,特别是涉及身份验证的问题时,非常重要的是要多次仔细检查所有名称和ID,确保它们与应该使用的名称和ID一致。感谢所有在这个问题上帮助或试图帮助我的人 您需要显示您的R代码-如何确保在请求之间保留cookie?(默认情况下,httr会这样做,但RCurl不会)@hadley:我在GitHub提供了指向我的源代码的链接(就在输出之前)。这是很多代码。我建议把它简化为一个简单的可复制的测试用例。@hadley:我正在按照你的建议用测试用例更新我的问题。它并没有我想要的那么小,但是我尽了最大的努力来最小化和简化代码,并且没有太多偏离我的真实场景。我已经测试过了,结果是一样的。一件有趣的事情是,我发现我的SQL请求中缺少一个空格(已修复),这应该触发一个适当的SQL语法消息。对我来说,这意味着查询甚至没有达到被解析的程度。正在向您发送用户和密码,因为我不想影响对系统的访问。@请忽略我关于SQL查询语法的说明-很好。感谢您的帮助!我希望无论版本如何,结果都是一样的。但是,我理解你想孤立问题的意图。那么,在你看来,考虑到我无法直接访问系统日志,下一步该怎么办?@AleksandrBlekh正如错误消息所说,给系统管理员发电子邮件嗨,哈德利!最后,我与系统负责人取得了联系,并获得了所需的详细信息(请参见更新3)。如果您能看一看并提出建议,我们将不胜感激@AleksandrBlekh您可以尝试使用httr的开发版本中的verbose()
——它提供了有关文章正文中发送内容的更多信息。这可能就是问题所在。嗨,哈德利!谢谢你的建议。我已经解决了这个问题。请看我最后的答案——你可能会惊讶于真正的原因是什么。如果你能看看这个,那就太好了。对你来说应该是小菜一碟;-)。应该是
if (!require(RCurl)) install.packages('RCurl')
if (!require(digest)) install.packages('digest')
library(RCurl)
library(digest)
# Users must authenticate to access Query Form
SRDA_HOST_URL <- "http://zerlot.cse.nd.edu"
SRDA_LOGIN_URL <- "/mediawiki/index.php?title=Special:Userlogin"
SRDA_LOGIN_REQ <- "&action=submitlogin&type=login"
# SRDA URL that Query Form sends POST requests to
SRDA_QUERY_URL <- "/cgi-bin/form.pl"
# SRDA URL that Query Form sends POST requests to
SRDA_QRESULT_URL <- "/qresult/blekh/blekh.txt"
# Parameters for result's format
DATA_SEP <- ":" # data separator
ADD_SQL <- "1" # add SQL to file
curl <<- getCurlHandle()
srdaLogin <- function (loginURL, username, password) {
curlSetOpt(curl = curl, cookiejar = 'cookies.txt',
ssl.verifyhost = FALSE, ssl.verifypeer = FALSE,
followlocation = TRUE, verbose = TRUE)
params <- list('wpName1' = username, 'wpPassword1' = password)
if(url.exists(loginURL)) {
reply <- postForm(loginURL, .params = params, curl = curl,
style = "POST")
#if (DEBUG) print(reply)
info <- getCurlInfo(curl)
return (ifelse(info$response.code == 200, TRUE, FALSE))
}
else {
error("Can't access login URL!")
}
}
srdaConvertRequest <- function (request) {
return (list(select = "*",
from = "sf1104.users a, sf1104.artifact b",
where = "b.artifact_id = 304727"))
}
srdaRequestData <- function (requestURL, select, from, where, sep, sql) {
params <- list('uitems' = select,
'utables' = from,
'uwhere' = where,
'useparator' = sep,
'append_query' = sql)
if(url.exists(requestURL)) {
reply <- postForm(requestURL, .params = params, #.opts = opts,
curl = curl, style = "POST")
}
}
srdaGetData <- function(request) {
resultsURL <- paste(SRDA_HOST_URL, SRDA_QRESULT_URL,
collapse="", sep="")
results.query <- readLines(resultsURL, n = 1)
return (ifelse(results.query == request, TRUE, FALSE))
}
getSourceForgeData <- function (request) {
# Construct SRDA login and query URLs
loginURL <- paste(SRDA_HOST_URL, SRDA_LOGIN_URL, SRDA_LOGIN_REQ,
collapse="", sep="")
queryURL <- paste(SRDA_HOST_URL, SRDA_QUERY_URL, collapse="", sep="")
# Log into the system
if (!srdaLogin(loginURL, USER, PASS))
error("Login failed!")
rq <- srdaConvertRequest(request)
srdaRequestData(queryURL,
rq$select, rq$from, rq$where, DATA_SEP, ADD_SQL)
if (!srdaGetData(request))
error("Data collection failed!")
}
message("\nTesting SourceForge data collection...\n")
getSourceForgeData("SELECT *
FROM sf1104.users a, sf1104.artifact b
WHERE a.user_id = b.submitted_by AND b.artifact_id = 304727")
# clean up
close(curl)
if (!require(RCurl)) install.packages('RCurl')
library(RCurl)
# Users must authenticate to access Query Form
SRDA_HOST_URL <- "http://zerlot.cse.nd.edu"
SRDA_LOGIN_URL <- "/mediawiki/index.php?title=Special:Userlogin"
SRDA_LOGIN_REQ <- "&action=submitlogin&type=login"
# SRDA URL that Query Form sends POST requests to
SRDA_QUERY_URL <- "/cgi-bin/form.pl"
# SRDA URL that Query Form sends POST requests to
SRDA_QRESULT_URL <- "/qresult/blekh/blekh.txt"
# Parameters for result's format
DATA_SEP <- ":" # data separator
ADD_SQL <- "1" # add SQL to file
message("\nTesting SourceForge data collection...\n")
curl <- getCurlHandle()
curlSetOpt(curl = curl, cookiejar = 'cookies.txt',
ssl.verifyhost = FALSE, ssl.verifypeer = FALSE,
followlocation = TRUE, verbose = TRUE)
# === Authentication ===
loginParams <- list('wpName1' = USER, 'wpPassword1' = PASS)
loginURL <- paste(SRDA_HOST_URL, SRDA_LOGIN_URL, SRDA_LOGIN_REQ,
collapse="", sep="")
if (url.exists(loginURL)) {
postForm(loginURL, .params = loginParams, curl = curl, style = "POST")
info <- getCurlInfo(curl)
message("\nLogin results - HTTP status code: ", info$response.code, "\n\n")
} else {
error("\nCan't access login URL!\n\n")
}
# === Data collection ===
# Previous query was: "SELECT * FROM sf0305.users WHERE user_id < 100"
query <- list(select = "*",
from = "sf1104.users a, sf1104.artifact b",
where = "b.artifact_id = 304727")
getDataParams <- list('uitems' = query$select,
'utables' = query$from,
'uwhere' = query$where,
'useparator' = DATA_SEP,
'append_query' = ADD_SQL)
queryURL <- paste(SRDA_HOST_URL, SRDA_QUERY_URL, collapse="", sep="")
if(url.exists(queryURL)) {
postForm(queryURL, .params = getDataParams, curl = curl, style = "POST")
resultsURL <- paste(SRDA_HOST_URL, SRDA_QRESULT_URL,
collapse="", sep="")
results.query <- readLines(resultsURL, n = 1)
request <- paste(query$select, query$from, query$where)
if (results.query == request)
message("\nData request is successful, SQL query: ", request, "\n\n")
else
message("\nData request failed, SQL query: ", request, "\n\n")
} else {
error("\nCan't access data query URL!\n\n")
}
close(curl)
42 if (-e "/tmp/sess_$file") {
43 $session = PHP::Session->new($cgi->cookie("$session_name"));
44 $user_id = $session->get('wsUserID');
45 $user_name = $session->get('wsUserName');
library(httr)
base_url <- "http://srda.cse.nd.edu"
loginURL <- modify_url(
base_url,
path = "mediawiki/index.php",
query = list(
title = "Special:Userlogin",
action = "submitlogin",
type = "login",
wpName1 = USER,
wpPasswor1 = PASS
)
)
r <- POST(loginURL)
stop_for_status(r)
queryURL <- modify_url(base_url, path = "cgi-bin/form.pl")
query <- list(
uitems = "user_name",
utables = "sf1104.users a, sf1104.artifact b",
uwhere = "a.user_id = b.submitted_by AND b.artifact_id = 304727",
useparator = ":",
append_query = "1"
)
r <- POST(queryURL, body = query, multipart = FALSE)
stop_for_status(r)