3

我想使用 RCurl 作为礼貌的网络爬虫从网站下载数据。显然我需要科学研究的数据。虽然我有权通过我的大学访问网站的内容,但网站的使用条款禁止使用网络爬虫。

我试图直接向网站管理员询问数据,但他们只是以非常模糊的方式回答。好吧,无论如何,他们似乎不会简单地将底层数据库发送给我。

我现在想要做的是正式要求他们获得一次性许可,以便使用基于 RCurl 的 R 代码从他们的站点下载特定的纯文本内容,其中包括在每个请求执行后延迟三秒。

我想从这样的工作中下载数据的站点的地址: http ://plants.jstor.org/specimen/站点的 ID

我尝试使用 RCurl 对其进行编程,但无法完成。有几件事使事情变得复杂:

  1. 只有在允许cookie的情况下才能访问该网站(我在 RCurl 中使用 cookiefile-argument 进行了访问)。

  2. 下一步按钮仅在用户通过在普通浏览器中单击不同链接实际访问该站点时才会出现在源代码中。在源代码中,Next-button 用一个表达式编码,包括

    <a href="/.../***ID of next site***">Next &gt; &gt; </a>
    

    当尝试直接访问该站点时(之前没有在同一个浏览器中单击过),它将无法正常工作,带有链接的行根本不在源代码中。

  3. 站点的 ID 是字母和数字的组合(例如“goe0003746”或“cord00002203”),所以我不能简单地在 R 中编写一个 for 循环来尝试从 1 到 1,000,000 的每个数字。

所以我的程序应该模仿一个人通过下一步按钮点击所有网站,每次都保存文本内容。

每次保存站点内容后,它应该等待三秒钟,然后单击下一步按钮(它必须是一个礼貌的爬虫)。我也使用 Sys.sleep 函数在 R 中工作。

我也想过用一个自动化的程序,但是这样的程序好像很多,不知道用哪个。

我也不完全是程序编写者(除了一点点 R),所以我真的很感激一个不包括 Python、C++、PHP 等编程的解决方案。

任何想法将不胜感激!非常感谢您提前提出意见和建议!

4

2 回答 2

2

尝试不同的策略。

 ##########################
 ####
 ####            Scrape http://plants.jstor.org/specimen/
 ####        Idea:: Gather links from http://plants.jstor.org/search?t=2076
 ####            Then follow links:
 ####
 #########################

 library(RCurl)
 library(XML)

 ### get search page::

 cookie = 'cookiefile.txt'
 curl  =  getCurlHandle ( cookiefile = cookie , 
     useragent =  "Mozilla/5.0 (Windows; U; Windows NT 5.1; en - US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6",
     header = F,
     verbose = TRUE,
     netrc = TRUE,
     maxredirs = as.integer(20),
     followlocation = TRUE)

 querry.jstor <- getURL('http://plants.jstor.org/search?t=2076', curl = curl)

 ## remove white spaces:
 querry.jstor2 <- gsub('\r','', gsub('\t','', gsub('\n','', querry.jstor)))

 ### get links from search page
  getLinks = function() {
        links = character()
        list(a = function(node, ...) {
                    links <<- c(links, xmlGetAttr(node, "href"))
                    node
                 },
             links = function()links)
      }

 ## retrieve links
  querry.jstor.xml.parsed <- htmlTreeParse(querry.jstor2, useInt=T, handlers = h1)

 ## cleanup links to keep only the one we want. 
  querry.jstor.links = NULL
  querry.jstor.links <- c(querry.jstor.links, querry.jstor.xml.parsed$links()[-grep('http', querry.jstor.xml.parsed$links())]) ## remove all links starting with http
  querry.jstor.links <- querry.jstor.links[-grep('search', querry.jstor.links)] ## remove all search links
  querry.jstor.links <- querry.jstor.links[-grep('#', querry.jstor.links)] ## remove all # links
  querry.jstor.links <- querry.jstor.links[-grep('javascript', querry.jstor.links)] ## remove all javascript links
  querry.jstor.links <- querry.jstor.links[-grep('action', querry.jstor.links)] ## remove all action links
  querry.jstor.links <- querry.jstor.links[-grep('page', querry.jstor.links)] ## remove all page links

 ## number of results
  jstor.article <- getNodeSet(htmlTreeParse(querry.jstor2, useInt=T), "//article")
  NumOfRes <- strsplit(gsub(',', '', gsub(' ', '' ,xmlValue(jstor.article[[1]][[1]]))), split='')[[1]]
  NumOfRes <- as.numeric(paste(NumOfRes[1:min(grep('R', NumOfRes))-1], collapse = ''))

  for(i in 2:ceiling(NumOfRes/20)){
    querry.jstor <- getURL('http://plants.jstor.org/search?t=2076&p=',i, curl = curl)
    ## remove white spaces:
    querry.jstor2 <- gsub('\r','', gsub('\t','', gsub('\n','', querry.jstor)))
    querry.jstor.xml.parsed <- htmlTreeParse(querry.jstor2, useInt=T, handlers = h1)
    querry.jstor.links <- c(querry.jstor.links, querry.jstor.xml.parsed$links()[-grep('http', querry.jstor.xml.parsed$links())]) ## remove all links starting with http
    querry.jstor.links <- querry.jstor.links[-grep('search', querry.jstor.links)] ## remove all search links
    querry.jstor.links <- querry.jstor.links[-grep('#', querry.jstor.links)] ## remove all # links
    querry.jstor.links <- querry.jstor.links[-grep('javascript', querry.jstor.links)] ## remove all javascript links
    querry.jstor.links <- querry.jstor.links[-grep('action', querry.jstor.links)] ## remove all action links
    querry.jstor.links <- querry.jstor.links[-grep('page', querry.jstor.links)] ## remove all page links

    Sys.sleep(abs(rnorm(1, mean=3.0, sd=0.5))) 
  }

  ## make directory for saving data: 
  dir.create('./jstorQuery/')

  ## Now we have all the links, so we can retrieve all the info
  for(j in 1:length(querry.jstor.links)){
    if(nchar(querry.jstor.links[j]) != 1){
       querry.jstor <- getURL('http://plants.jstor.org',querry.jstor.links[j], curl = curl)
       ## remove white spaces:
       querry.jstor2 <- gsub('\r','', gsub('\t','', gsub('\n','', querry.jstor)))

       ## contruct name:
       filename = querry.jstor.links[j][grep( '/', querry.jstor.links[j])+1 : nchar( querry.jstor.links[j])]

       ## save in directory: 
       write(querry.jstor2, file = paste('./jstorQuery/', filename, '.html', sep = '' ))

       Sys.sleep(abs(rnorm(1, mean=3.0, sd=0.5))) 
    }
  }
于 2011-12-02T13:07:47.880 回答
1

我可能完全错过了你挂断的那一点,但听起来你快到了。

看来您可以请求带有 cookie 的第 1 页。然后解析搜索下一个站点 ID 的内容,然后通过构建具有下一个站点 ID 的 URL 来请求该页面。然后抓取您想要的任何数据。

听起来您的代码几乎可以完成所有这些工作。问题是解析第1页以获得下一步的ID吗?如果是这样,你应该制定一个可重现的例子,我怀疑你会很快得到你的语法问题的答案。

如果您在查看该站点的操作时遇到问题,我建议您使用 Firefox 的Tamper Data插件。它将让您查看每次鼠标单击时发出的请求。我发现它对这种类型的东西非常有用。

于 2011-10-25T15:04:55.010 回答