• R语言
  • Rcurl模拟登入新浪微博

前些日,利用手动登入后浏览器获取cookie的方法登入发现诸多弊端。其中,追严重的是将cookie复制到另一ip下的设备时,一定概率会被封号。所以最稳妥的还是,在对应主机上模拟登陆。

我在网上查阅了大量资料:
参考了Python使用Curl模拟登入新浪微博的方法后,我写了一个可行的R语言登入微博脚本。
希望能对正在研究的提供帮助。

参考文献:
http://www.phperz.com/article/14/1010/14635.html
http://www.cnblogs.com/loveyouyou616/p/4238230.html

特别感谢:
新浪客服妹子:感谢您适当的回答让我多花费不少时间,研究新浪的发爬虫机制。也感谢您,在无数次帮我解封帐号

源码如下:
######加载必要的工具#####
library(RCurl) 
library(rjson)
library(stringr)
library(XML)
library(PKI)

#########进入新浪登入页面########
####h用于获取反馈头信息########
h <- basicHeaderGatherer()
####基本头信息,向服务器说明当前浏览网页的设备信息,可以根据自己情况设置#######
header <- c(
  "Connection" = "keep-alive",
  "Host" = "login.sina.com.cn",
  "User-Agent" = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36",
  "Accept" = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
  "Content-Length"=523,
  "Content-Type"="application/x-www-form-urlencoded",
  "Origin" = "http://login.sina.com.cn",
  "Referer"="http://login.sina.com.cn/?r=/member/my.php?entry=sso"
)
#########输入账号密码登入##############
######下面的url用于获得预登入信息(服务器时间戳,RSA公钥,等加密信息),并生成一个时间戳跟在需要get的url后面
prelogin_url<-paste("http://login.sina.com.cn/sso/prelogin.php?entry=account&callback=sinaSSOController.preloginCallBack&su=&rsakt=mod&client=ssologin.js(v1.4.15)&_=",floor(as.numeric(Sys.time())*1000),sep="")
text<-getURL(prelogin_url)
########获取预登入信息后,解析信息##########
tmp <- fromJSON(gsub("sinaSSOController.preloginCallBack\\(\\{(.*)\\}\\)","\\{\\1\\}",text))
########引入用户名、密码#########
######注意用户名中'@'等特殊符号,应转化为对应码值('@'对应'% 40'中间的空格是多余的)########
#########所以我的邮箱libingfei@sina.com,应转为如下#######
########请将邮箱密码换为自己的
u<-"libingfei% 40sina.com"#########中间的空格是多余的
##########密码请换成自己帐号的
pw<-"sad*****"
##########对用户名进行编码
su<-base64Encode(u)
###############下面是一套通过新浪js抽取出的加密算法,目前(2015/6/28)测试依然可用######
key_p<-tmp$pubkey
key_p_p<-""
for(i in 1:(str_length(key_p)/2)){
  key_p_p[i]<-unclass(as.hexmode(tolower(str_sub(key_p,(2*i-1),(2*i)))))
}
as.raw(key_p_p)
pubkey_p<-PKI.mkRSApubkey(as.raw(key_p_p), exponent=65537L,format = "key")#c("DER", "PEM", "key")
keyword<-paste(tmp$servertime,"\t",tmp$nonce,"\n",pw,sep="")
passwd<-PKI.encrypt(charToRaw(keyword),pubkey_p)
passwd<-paste(as.character(passwd),sep="",collapse="")

############生成登入url##############
loginurl<-paste("http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)&_=",floor(as.numeric(Sys.time())*1000),sep="")
######################生成登入post参数#########
loginData<-c(
  "entry"<-"sso",
  "gateway"<-"1",
  'from' = "null",
  "savestate" = "30",
  "useticket" = "0",
  "pagerefer" = "",
  "vsnf" = "1",
  "su" = su,
  "service" = "sso",
  "servertime"=tmp$servertime,
  "nonce"=tmp$nonce,
  "pwencode"="rsa2",
  "rsakv"=tmp$rsakv,
  "sp" = passwd,
  "sr" = "1366*768",
  "encoding" = "UTF-8",
  "cdult" = "3",
  "domain" = "sina.com.cn",
  "prelt" = "100",
  "returntype" = "TEXT"
)
##设定post规则
#verbose:输出连接信息
#headerfunction:更新反馈头信息
ch1<-getCurlHandle(verbose = TRUE, headerfunction = h$update)
####post获取认证url#########
text2<-postForm(loginurl,.params = loginData,.encoding = "utf-8",style = "post",curl=ch1)#,curl=ch1
######抽取认证url#########
text3<-fromJSON(text2)
#############通过认证url更新头信息#########
text4<-getURL(text3$crossDomainUrlList[1], headerfunction = h$update,.encoding="utf-8")
############获取登入cookie###########
rhead<-h$value()
cookies<-rhead[names(rhead)=="Set-Cookie"]
cookie<-paste(lapply(str_split(cookies,pattern = ";"),function(v) v[1]),collapse = ";",sep = ";")




:cry: :cry: :cry:
4 天 后
好厉害呀,这个以前做过,但是没有成功。您可以试试怎么登陆QQ,抓取QQ的数据更有意思 :-)
试了一下,第36行报错,可以解决吗?
passwd <- PKI.encrypt(charToRaw(keyword), pubkey_p)
Error in PKI.encrypt(charToRaw(keyword), pubkey_p) :
error:04068065:lib(4):func(104):reason(101)
另外登陆js版本已经更新了js(v1.4.18),之前是js(v1.4.15)
现在prelogin_url是这样的http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=&rsakt=mod&client=ssologin.js(v1.4.18)&_=1435891268849,您的代码中是这样的
prelogin_url <- paste("http://login.sina.com.cn/sso/prelogin.php?entry=account&callback=sinaSSOController.preloginCallBack&su=&rsakt=mod&client=ssologin.js(v1.4.15)&_=", 
    floor(as.numeric(Sys.time()) * 1000), sep = "")
您好,请问获取cookie之后,在RCurl里如何使用它登陆呢
4楼,如果前面生成公钥没错请关注一下keyword格式是否错误。
5楼,我刚成1.4.18也可登入,加密方式未变
6楼,你可以把cookie写在头里,cookie是服务器对你的识别。
用它就相当于登入了。

myHttpheader1 <- c(
"Connection" = "keep-alive",
"Host" = "weibo.com",
"User-Agent" = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36",
"Accept" = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"#,
#"Accept-Language"="zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3",
#"Accept-Encoding"="gzip,deflate",
#例如:上文获得的cookie可以这样写在头里
"Cookie" = cookie,
#,
#"Referer"="http://roll.news.qq.com/"
)

不过相对的会有账号被封的风险。

我是参照前人的经验,另外,获取cookie的方法还有一些,新浪反爬机制也不止这些,我也在继续研究学习中。
如您所言,但是结果还是返回错误
head <- c(Connection = "keep-alive",
          Host = "login.sina.com.cn", 
          "User-Agent" = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0", 
          Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 
          "Content-Length" = 523, "Content-Type" = "application/x-www-form-urlencoded", 
          Host = "weibo.com", 
          Referer = "http://login.sina.com.cn/member/my.php?entry=sso", 
          "Cookie" = cookie)
d2 =debugGatherer()
cHandle2<- getCurlHandle(httpheader=head, followlocation=1,
                         debugfunction=d2$update,verbose=TRUE,
                         cookiefile= "cookie.txt")

page <- getURL("http://weibo.com/at/weibo?topnav=1&wvr=5", curl = cHandle2)
page


[1] "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<html>\r\n<head><title>403 Forbidden</title></head>\r\n<body bgcolor=\"white\">\r\n<h1>403 Forbidden</h1>\r\n<p>You don't have permission to access the URL on this server. Sorry for the inconvenience.<br/>\r\nPlease report this message and include the following information to us.<br/>\r\nThank you very much!</p>\r\n<table>\r\n<tr>\r\n<td>URL:</td>\r\n<td>http://login.sina.com.cn/at/weibo?topnav=1&wvr=5</td>\r\n</tr>\r\n<tr>\r\n<td>Server:</td>\r\n<td>venus50</td>\r\n</tr>\r\n<tr>\r\n<td>Date:</td>\r\n<td>2015/07/03 23:00:03</td>\r\n</tr>\r\n</table>\r\n<hr/>Powered by WeiBo</body>\r\n</html>\r\n"
你写了两个host,第一个错了。
cookiefile删掉,你没有用这个文件。
善用浏览器调试工具,比照先哪里和你浏览时不一样。
附送您一些资料,自学能力很重要,剩余的自己看吧。
参考学习内容:XPATH\JSON
您自己边调边学把:
我给公司写的文档都没给你写得多。。。。

涉及技术:
XPATH
JSON
1、爬去后默认GBK编码
涉及编码转换:iconv
2、文本htmlParse格式化后,所有信息存在js脚本中
提示:getNodeSet(tmp1,"/html/script")
3、解析js脚本提取json串,正常微博30多个js标签
gsub(".*FM.view\\(\\{(.*)\\}\\)","\\{\\1\\}",tmp3[flag])
4、30多个json串中含有domid值:
有效的json值:
Pl_Official_Headerv6 (名称相关)
Pl_Core_UserInfo (用户信息)
Pl_Official_MyProfileFeed (单次加载微博10+条)
Pl_Core_T8CustomTriColumn (粉丝,关注等)
5、抽取就JSON字符串后,需再次使用htmlParse格式化
您说的附送给我的资料,指的是什么呢?
您说的这些东西我基本都掌握了,昨天学了一天正则表达式,综合来看,对于新浪微博的数据正则表达式更方便,数据基本都提取出来了。在写S4类的时候出了一点小问题
2 个月 后
回复 1 楼libingfei

http://bbs.pinggu.org/thread-3875103-1-1.html[未知用户]

这是啥一回事儿呢? :?:
> head <- c(Connection='keep-alive',
+           'User-Agent'='Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0',
+           Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 
+           'Content-Length'=523, 'Content-Type'='application/x-www-form-urlencoded',
+           Host='weibo.com', Referer='http://login.sina.com.cn/member/my.php?entry=sso') #, 'Cookie'=cookie)
> d2 <- debugGatherer()
> cHandle2 <- getCurlHandle(httpheader=head, followlocation=1, debugfunction=d2$update,verbose=TRUE)#, cookiefile='cookie.txt')
> page <- getURL('http://weibo.com/at/weibo?topnav=1&wvr=5', curl = cHandle2)
Error in function (type, msg, asError = TRUE)  : Empty reply from server
> page
function (x, method = c("dput", "print"), ...) 
{
    local.file.show <- function(file, title = subx, delete.file = TRUE, 
        pager = getOption("pager"), ...) file.show(file, title = title, 
        delete.file = delete.file, pager = pager)
    local.dput <- function(x, file, title, delete.file, pager, 
        ...) dput(x, file, ...)
    local.print <- function(x, title, delete.file, pager, ...) print(x, 
        ...)
    if (is.character(x) && length(x) == 1L) {
        subx <- x
        parent <- parent.frame()
        if (exists(subx, envir = parent)) 
            x <- get(subx, envir = parent)
        else stop(gettextf("no object named '%s' to show", x), 
            domain = NA)
    }
    else {
        subx <- deparse(substitute(x))
    }
    file <- tempfile("Rpage.")
    if (match.arg(method) == "dput") 
        local.dput(x, file, ...)
    else {
        sink(file)
        local.print(x, ...)
        sink()
    }
    local.file.show(file, ...)
}
<bytecode: 0x75b8508>
<environment: namespace:utils>
16 天 后
5 天 后
楼主,pubkey_p<-PKI.mkRSApubkey(as.raw(key_p_p), exponent=65537L,format = "key") 运行这段代码的时候一直报错。
Error in PKI.encrypt(charToRaw(keyword), pubkey_p) :
error:04068065:rsa routines:RSA_EAY_PUBLIC_ENCRYPT:bad e value
请问有解决办法吗?