调试基于RCurl的身份验证&;表单提交

调试基于RCurl的身份验证&;表单提交,r,forms,authentication,web-scraping,rcurl,R,Forms,Authentication,Web Scraping,Rcurl,SourceForge研究数据档案(SRDA)是我论文研究的数据来源之一。我在调试以下与SRDA数据收集相关的问题时遇到困难 从SRDA收集数据需要身份验证,然后使用SQL查询提交Web表单。成功处理查询后,系统生成一个带有查询结果的文本文件。在为SRDA数据收集测试R代码时,我更改了SQL请求,以确保结果文件正在重新生成。但是,我发现文件内容保持不变(对应于前面的查询)。我认为文件内容缺乏刷新可能是由于身份验证或查询表单提交失败。以下是代码()的调试输出: 以下是通过跟踪手动验证和手动数据请求

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


如果您能帮我解决代码中的问题,我将不胜感激

我进一步简化了代码:

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)