2010-08-06 70 views

回答

7

点击下载链接上执行这段JavaScript代码:

__doPostBack('ctl00$MainPageLeft$MainPageContent$ExportHoldings1$LinkButton1','') 

__doPostBack功能似乎只是在一对夫妇的网页上隐藏的表单字段填写然后提交一个POST请求。

一个快速的搜索结果显示RCurl能够提交POST请求。因此,您需要做的是查看该页面的源代码,找到名称为“aspnetForm”的表单,从该表单中获取所有字段,并创建您自己的POST请求,将这些字段提交到操作URL(http://www.invescopowershares.com/products/holdings.aspx?ticker=PGX )。

不能保证这将工作,但。似乎有一个隐藏的表单域名为__VIEWSTATE,似乎编码的一些信息,我不知道这个因素如何。

+0

很好 - 您在哪里找到了关于如何使用RCurl提交Javascript POST请求的文档? – 2010-08-06 19:11:05

+0

http://www.omegahat.org/RCurl/installed/RCurl/html/postForm.html – Jeff 2010-08-06 19:27:21

1

这绝对是在RCurl中获得.csv文件的方式,但我可以'弄清楚我想在getForm中使用哪些表单域来使其工作。我应该使用附加到页面上“下载”链接的doPostBack命令中的字段,还是应该在源页面上使用aspnetForm中的字段。仅供参考,我们感兴趣的aspnetForm字段是:

“ form name =”aspnetForm“method =”post“action =”holdings.aspx?ticker = PGX“id =”aspnetForm“style =”保证金:0像素 “ ”

...和postForm请求,我只是想,没有工作是

postForm(“ http://www.invescopowershares.com/products/holdings.aspx?ticker=PGX”, “表单名称”= “aspnetForm”, “方法”=“发表评论发表评论您还没有登录,无法进行此操作,请重试。

+0

您将从aspnetForm表单中的字段开始,然后用doPostBack函数插入的值覆盖那里的内容隐藏的领域。因为doPostBack所做的基本上是采用现有的表单并填写两个隐藏的字段,然后提交表单。 – Jeff 2010-08-06 20:33:41

10

我会给你一个快速和肮脏的方式来获取数据。首先,您可以使用Fiddler2 http://www.fiddler2.com/fiddler2/来检查您的浏览器发送的POST。这将导致下面的帖子:

POST http://www.invescopowershares.com/products/holdings.aspx?ticker=PGX HTTP/1.1 
Host: www.invescopowershares.com 
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
Accept-Language: en-us,en;q=0.5 
Accept-Encoding: gzip, deflate 
DNT: 1 
Connection: keep-alive 
Referer: http://www.invescopowershares.com/products/holdings.aspx?ticker=PGX 
Content-Type: application/x-www-form-urlencoded 
Content-Length: 70669 

__EVENTTARGET=ctl00%24MainPageLeft%24MainPageContent%24ExportHoldings1%24LinkButton1&__EVENTARGUMENT=&__VIEWSTATE=%2FwEPDwUKLTE1OTcxNjYzNw9kFgJmD2QWBAIDD2QWBAIDD2QWCAIBDw9kFgQeC2........ 

所以我们可以看到,3个参数被贴即__EVENTTARGET,__EVENTVALIDATION和__VIEWSTATE。

为postForm调用所需的形式是:

postForm(ftarget, "form name" = "aspnetForm", "method" = "POST", "action" = "holdings.aspx?ticker=PGX", "id" = "aspnetForm","__EVENTTARGET"=event.target,"__EVENTVALIDATION"=event.val,"__VIEWSTATE"=view.state) 

现在到了快速和脏位。我只需打开浏览器,并得到它临危如下的相关参数:

library(rcom) 
ie = comCreateObject('InternetExplorer.Application') 
ie[["visible"]]=T # true for debugging 
ie$Navigate2("http://www.invescopowershares.com/products/holdings.aspx?ticker=PGX") 
while(comGetProperty(ie,"busy")||comGetProperty(ie,"ReadyState")<4){ 
Sys.sleep(1) 
print(comGetProperty(ie,"ReadyState")) 
} 
myDoc<-comGetProperty(ie,"Document") 
myPW<-comGetProperty(myDoc,"parentWindow") 
comInvoke(myPW,"execScript","var dumVar1=theForm.__EVENTVALIDATION.value;var dumVar2=theForm.__VIEWSTATE.value;","JavaScript") 
event.val<-myPW[["dumVar1"]] 
view.state<-myPW[["dumVar2"]] 
event.target<-"ctl00$MainPageLeft$MainPageContent$ExportHoldings1$LinkButton1" 
ie$Quit() 
ftarget<-"http://www.invescopowershares.com/products/holdings.aspx?ticker=PGX" 
web.data<-postForm(ftarget, "form name" = "aspnetForm", "method" = "POST", "action" = "holdings.aspx?ticker=PGX", "id" = "aspnetForm","__EVENTTARGET"=event.target,"__EVENTVALIDATION"=event.val,"__VIEWSTATE"=view.state) 
write(web.data[1],'temp.csv') 
fin.data<-read.csv('temp.csv') 


> fin.data[1,] 
    ticker SecurityNum      Name CouponRate maturitydate 
1 PGX 949746879 WELLS FARGO & COMPANY PFD  0.08    
    rating Shares PercentageOfFund PositionDate 
1 BBB+/Baa3 2538656  0.04442112 06/11/2012 

__EVENTVALIDATION,__VIEWSTATE也许总是相同的,或者它们可能会话cookie。你可能可以使用RCurl来获取它们,但正如我所说这是一个快速和肮脏的解决方案,我们只是采用Internet Explorer所提供的解决方案。注意事项:

1)。这需要安装IE的窗口才能使用rcom位。 2)。如果您正在运行ie9,则可能需要将invescopowershares.com添加到兼容性视图设置(因为Microsoft似乎已阻止event.val < -myPW [[“dumVar1”]] com com calls)

编辑(更新)

通过更详细地查看网站__EVENTVALIDATION,__VIEWSTATE被设置为初始页面上的JavaScript变量。我们可以按照下面的方式快速,肮脏地解析这些内容,而不必通过调用浏览器。

dum<-getURL("http://www.invescopowershares.com/products/holdings.aspx?ticker=PGX") 
event.target<-"ctl00$MainPageLeft$MainPageContent$ExportHoldings1$LinkButton1" 
event.val<-unlist(strsplit(dum,"__EVENTVALIDATION\" value=\""))[2] 
event.val<-unlist(strsplit(event.val,"\" />\r\n\r\n<script"))[1] 
view.state<-unlist(strsplit(dum,"id=\"__VIEWSTATE\" value=\""))[2] 
view.state<-unlist(strsplit(view.state,"\" />\r\n\r\n\r\n<script"))[1] 
ftarget<-"http://www.invescopowershares.com/products/holdings.aspx?ticker=PGX" 
web.data<-postForm(ftarget, "form name" = "aspnetForm", "method" = "POST", "action" = "holdings.aspx?ticker=PGX", "id" = "aspnetForm","__EVENTTARGET"=event.target,"__EVENTVALIDATION"=event.val,"__VIEWSTATE"=view.state) 
write(web.data[1],'temp.csv') 
fin.data<-read.csv('temp.csv') 

以上应该可以跨平台工作。

+0

Bravo!好样的!非常感谢你! – GSee 2012-06-12 22:37:08

1

qmao package现在有一个功能,可以为你做到这一点。 (这是从现在删除了这个问题的答案基于代码)。

可以使用dlPowerShares 功能是这样的:

require("qmao") 
Symbol <- "PGX" 
dat <- qmao:::dlPowerShares(event.target = "ctl00$MainPageLeft$MainPageContent$ExportHoldings1$LinkButton1", 
          action = paste0("holdings.aspx?ticker=", Symbol)) 
> head(dat) 
    ticker SecurityNum       Name CouponRate maturitydate rating Shares PercentageOfFund PositionDate 
1 PGX 173080201   CITIGROUP CAPITAL XIII 0.07875 10/30/2040 BB/Ba2 2998647  0.04274939 08/31/2012 
2 PGX 949746879  WELLS FARGO & COMPANY PFD 0.08000    BBB+/Baa3 2549992  0.03935854 08/31/2012 
3 PGX 06739H362  BARCLAYS BK PLC    0.08125    A-/Baa3 2757635  0.03644835 08/31/2012 
4 PGX 46625H621  JPMORGAN CHASE    0.08625    BBB+/Baa1 2416021  0.03310707 08/31/2012 
5 PGX 060505765 BANK OF AMERICA CORP PFD 8.2 0.08200     BB+/B1 2345508  0.03128002 08/31/2012 
6 PGX 060505559 BANC OF AMERICA CORP PFD 8.625 0.08625     BB+/B1 2259484  0.03001599 08/31/2012 

在上面的代码,event.target是里面的第一个字符串javascript:__ doPostBack() 函数,当您右键单击“下载”链接和“复制链接地址”时,您将获得该函数。

action是动作url的产品特定部分。

在内部,代码如下在他 answerJeff's建议和搜索页面的源代码的值为“aspnetForm”字段 。然后,它在到postForm 呼叫使用这些值(从RCurl包。)

qmao packagedlPowerShares是通过使用getHoldings.powershares 。另外,getHoldings将调用getHoldings.powershares 如果其中一个Symbols传递给它是PowerShares ETF的象征。


p.s.如果qmao:::dlPowerShares被默认值调用,它将从 下载PowerShares产品列表