新浪微博自动(模拟)登陆详解及实现

最近需要爬取微博的数据进行分析,对于新浪微博,官方提供了API,但是有几个比较致命的限制(调用次数限制和授权期限限制),所以我觉得有必要研究一下爬虫直接爬去微博的方式获取微博数据的可行性。

       由于模拟登陆微博是爬虫爬取微博信息的第一步,所以在这里先介绍一下怎么模拟登陆微博(以下以新浪微博为例)。
       此过程主要分两步:
           1  脚本模拟登陆新浪微博,保存cookie;
           2  有了cookie信息后,利用cookie信息直接访问微博url。
      其中,第一步是这里讨论的重点。要想能更好的模拟这一步,一个好的网络监视工具是必须的,可以使用Firefox的Firebug和Chrome及IE自 带的开发工具(注意下,IE必须IE9以上版本才有监视网络的功能,Chrome的网络交互报文可以到network部分查看)。此外,前两天发现python支持的包比较多,用python定制自己的网络报文比较方便,所以此处我就采用python作为我的开发语言了。
 
      好了,前提工作先说到这里,下面开始分析一下用户在登陆sina微博的过程中都进行了那些操作。下面的例子中我使用的是chrome自带的开发者工具作为我的网络报文监视工具的。
      首先,打开http://weibo.com/(如果你以前设置过让浏览器自动记住密码并自动登陆,你需要清楚一下cookie),之后通过网络监视工具,我们会发现在用户登录过程中,浏览器与服务器有三次交互,分别如下:
一、第一次Get请求获取一些参数
      在用户名一栏输入你的微博账号,然后确定,这时你会发现,当你的焦点离开用户名输入框之后,浏览器会自动向 “http://login.sina.com.cn/sso/prelogin.php?entry=weibo& callback=sinaSSOController.preloginCallBack&su=&rsakt=mod& checkpin=1&client=ssologin.js(v1.4.5)&_=1362808219583”发送一个GET请求, 如下:
新浪微博自动(模拟)登陆详解及实现 - Lendfating - Lendfating新浪微博自动(模拟)登陆详解及实现 - Lendfating - Lendfating
       仔细查看这一个GET请求的响应内容,你会发现这个包含几个参数的JSON串,也许你还不了解他们的意义,不过没关系,现在你只需要知道这些参数在后续处理中我们会使用到就可以。
二、发送POST请求
       这一部分是整个登陆过程的重点。该部分用来提交用户信息给服务器并由服务器判断用户信息是否正确,从而判断是否登陆成功。
       通过Chrome自带的开发者工具,可以观察POST报文的相关信息(url、headers、data),下图是我的POST信息的截图:
        URL信息如下:
新浪微博自动(模拟)登陆详解及实现 - Lendfating - Lendfating
        报文Headers信息如下:
新浪微博自动(模拟)登陆详解及实现 - Lendfating - Lendfating
          POST的报文数据信息如下: 
新浪微博自动(模拟)登陆详解及实现 - Lendfating - Lendfating
         接下来的工作就比较简单了,我们要做的就是仿照上面的报文内容及格式,用python发送一个类似的报文即可。在自己定制类似报文之前,我觉得有必要对上面报文中DATA表单中每一项的意义进行以下简单说明。
      其中, “su" 是加密后的username,"sp"是加密后的password。"servertime"、”nonce"和"rsakv"是上一步GET请求返回的 JSON串中的内容。其他参数是不变的。然后,着重介绍一下"su"和"sp"的加密算法。
      1. "su"的加密算法
           su是username经过BASE64计算得来的:su = base64.encodestring( urllib.quote(username) )[:-1];
      2. "sp"的加密算法
           sp的加密算法可能会经常变动(考虑到网站的安全,过一段时间变动一下登陆的报文格式与加密算法是很正常的),目前新浪采用的是RSA算法(如果你js比较牛的话,可以直接去找网页源代码查找其加密方法,我是没找到,参考的网上的)。
           在这里简单介绍一下RSA算法的解密过程。
                 2.1  安装RSA模块,下载地址为:https://pypi.python.org/pypi/rsa/3.1.1
                 2.2  创建一个rsa公钥,公钥的两个参数新浪微博都给了是固定值,不过给的都是16进制的字符串,第一个是登录第一步中的pubkey,第二个是js加密文件中的‘10001’。这两个值需要先从16进制转换成10进制,不过也可以写死在代码里。我就把‘10001’直接写死为65537

rsaPublickey = int(pubkey, 16)

key = rsa.PublicKey(rsaPublickey, 65537) #创建公钥

message = str(servertime) + '\t' + str(nonce) + '\n' + str(password)#拼接明文 js加密文件中得到

passwd = rsa.encrypt(message, key)#加密

passwd = binascii.b2a_hex(passwd) #将加密信息转换为16进制。

                 

      如果以上各步你都进展的比较顺利的话,你会得到如下响应:
新浪微博自动(模拟)登陆详解及实现 - Lendfating - Lendfating
      这是一条自动跳转语句,里面包含了准备跳转的URL,如果正确登陆,则这个URL中德retcode的值为0,否则登陆错误,你需要仔细检查上面的步骤。
三、跳转到对应微博页面

      上面我们已经得到了待跳转的url,所以现在只需请求这个URL即可。在这里有一点需要注意一下,要想服务器知道你是否登陆,这一步的请求需要用到前面操 作的cookie信息(因为第二步中登陆成功与否的信息会自动记录在cookie中),所以我们在整个程序的一开始要打开cookie,保证以后的操作都 能正确的使用cookie,同时,对于python的用户,这一步就不要自己去定制header了,因为在默认情况下urllib2会自动打包 cookie信息的如果人为去定制header时可能会漏掉cookie信息。

 
下面附上我的参考代码:https://github.com/Lendfating/SinaLogin.git
 
参考文章:
来自:http://lendfating.blog.163.com/blog/static/1820743672013285253844/
posted @ 2013-11-05 10:52 chasewade 阅读(...) 评论(...) 编辑 收藏