新浪微博爬虫:模拟登陆+爬取原始页面
来源:互联网 发布:mac哪个国家的缩写 编辑:程序博客网 时间:2024/05/20 12:25
最近搞科研,总要有数据,奈何新浪API限制太多。。。。。
网上的新浪爬虫教程太杂乱,就不能简单点让大家都看懂吗????
主要参考:
http://blog.csdn.net/bcj296050240/article/details/46685947
http://www.jianshu.com/p/36a39ea71bfd
用爬虫爬取新浪数据的两个大步骤:
模拟浏览器登录;
爬取数据;
解析数据;
模拟浏览器登录必不可少,像新浪这种动态反扒网站,大致登录流程是:
1)客户端向服务器发送预登陆申请,又服务器动态的为客户端生成servertime, nonce, pubkey等信息。
2)用户名、密码配合返回的servertime, nonce, pubkey等动态信息,生成动态秘钥,并且和其他参数一起POST给服务器。
3)服务器验证用户名、密码正确后,给客户端发送一个真正的登录地址。
4)客户端登录该真正的地址,才算登陆成功。。。。。。。。
1)如何获取服务器为客户端生成servertime, nonce, pubkey等动态的信息:
笼统地说,使用Fiddler抓包分析。具体的:
1)下载Fiddler,安装后打开即可。
2)使用(IE)浏览器登录一次微博,发现Fiddler抓包的记录如下:
右边,五个椭圆信息是动态生成的,具体的,实在请求【server_URL = "http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=&rsakt=mod&client=ssologin.js(v1.4.18)"】时生成的;所以代码应该如下:
server_URL = "http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=&rsakt=mod&client=ssologin.js(v1.4.18)"
response = urllib2.urlopen(server_URL).read() # 获取网页内容
print 'response', response
解析response就可以得到servertime, nonce, pubkey, rsakv这四个信息了。
2)用户名、密码配合返回的servertime, nonce, pubkey等动态信息,生成动态秘钥,并且和其他参数一起POST给服务器:
具体的,post给服务器的参数包括(就是Fiddler左上角的所有参数):
post_param = { "entry": "weibo", "gateway": "1", "from": "", "savestate": "7", "useticket": "1", "pagerefer": "", "vsnf": "1", "su": s_username, "service": "miniblog", "servertime": servertime, "nonce": nonce, "pwencode": "rsa2", "rsakv": rsakv, "sp": s_password, "sr": "1920*1080", "encoding": "UTF-8", "prelt": "119", "url": "http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack", "returntype": "META", }其中s_username和s_password是加过密的。
那么加密过程如何呢?
首先我们要在未登录状态到http://login.sina.com.cn/signup/signin.php?entry=sso 这个页面,并得到http://login.sina.com.cn/js/sso/ssologin.js 这个js文件.
查看ssologin.js的makeRequest函数, 原型如下:
var makeRequest = function(username, password, savestate) { var request = { entry: me.getEntry(), gateway: 1, from: me.from, savestate: savestate, useticket: me.useTicket ? 1 : 0 }; if (me.failRedirect) { me.loginExtraQuery.frd = 1 } request = objMerge(request, { pagerefer: document.referrer || "" }); request = objMerge(request, me.loginExtraFlag); request = objMerge(request, me.loginExtraQuery); request.su = sinaSSOEncoder.base64.encode(urlencode(username)); if (me.service) { request.service = me.service } if ((me.loginType & rsa) && me.servertime && sinaSSOEncoder && sinaSSOEncoder.RSAKey) { request.servertime = me.servertime; request.nonce = me.nonce; request.pwencode = "rsa2"; request.rsakv = me.rsakv; var RSAKey = new sinaSSOEncoder.RSAKey(); RSAKey.setPublic(me.rsaPubkey, "10001"); password = RSAKey.encrypt([me.servertime, me.nonce].join("\t") + "\n" + password) } else { if ((me.loginType & wsse) && me.servertime && sinaSSOEncoder && sinaSSOEncoder.hex_sha1) { request.servertime = me.servertime; request.nonce = me.nonce; request.pwencode = "wsse"; password = sinaSSOEncoder.hex_sha1("" + sinaSSOEncoder.hex_sha1(sinaSSOEncoder.hex_sha1(password)) + me.servertime + me.nonce) } } request.sp = password; try { request.sr = window.screen.width + "*" + window.screen.height } catch (e) {} return request };其中我们关心的是:
request.su = sinaSSOEncoder.base64.encode(urlencode(username));if ((me.loginType & rsa) && me.servertime && sinaSSOEncoder && sinaSSOEncoder.RSAKey) { request.servertime = me.servertime; request.nonce = me.nonce; request.pwencode = "rsa2"; request.rsakv = me.rsakv; var RSAKey = new sinaSSOEncoder.RSAKey(); RSAKey.setPublic(me.rsaPubkey, "10001"); password = RSAKey.encrypt([me.servertime, me.nonce].join("\t") + "\n" + password)}
从代码中我们可以知道su就是经过html字符转义再转成base64编码。
weibo登录对密码有两种加密方式:rsa2与wsse,从上面的截图的pwnencode=rsa2可知, js处理走的是这一部分逻辑。
我们只要把这部分js在python中转义就行了。
加密代码如下:# 根据明文的用户名信息获取加密后的用户名def get_su(username): s_username = urllib.quote(username) # html字符转义 s_username = base64.encodestring(s_username) # return s_username[:-1] # 根据明文的密码信息以及rsa加密算法的规则生成密码的密文def get_sp(password, servertime, nonce, pubkey): message = str(servertime) + '\t' + str(nonce) + '\n' + str(password) # 拼接明文加密文件中得到 rsaPublickey = int(pubkey, 16) key = rsa.PublicKey(rsaPublickey, 65537) #创建公钥,10001对应的10进制 s_password = rsa.encrypt(message, key) #加密 s_password = binascii.b2a_hex(s_password) #将加密信息转换为16进制。 return s_password
知道POST参数后,还需要向服务器提交,这次的提交地址是:login_URL = "http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.18)"
所以,代码应该如下:
request = urllib2.Request(url=login_URL, data=post_data, headers=post_Header) result = urllib2.urlopen(request) text = result.read() # 读取内容 print "text==>", text如果成功,text打印出来的信息如下(就是Fiddler的右下角信息):
<html><head><meta http-equiv="Content-Type" content="text/html; charset=GBK" /><title>新浪通行证</title><script charset="utf-8" src="http://i.sso.sina.com.cn/js/ssologin.js"></script></head><body>正在登录 ...<script>try{sinaSSOController.setCrossDomainUrlList({"retcode":0,"arrURL":["http:\/\/passport.97973.com\/sso\/crossdomain?action=login&savestate=1509095303","http:\/\/passport.weibo.cn\/sso\/crossdomain?action=login&savestate=1"]});}catch(e){var msg = e.message;var img = new Image();var type = 1;img.src = 'http://login.sina.com.cn/sso/debuglog?msg=' + msg +'&type=' + type;}try{sinaSSOController.crossDomainAction('login',function(){location.replace('http://passport.weibo.com/wbsso/login?ssosavestate=154553454503&url=http%3A%2F%2Fweibo.com%2Fajaxlogin.php%3Fframelogin%234543D1%43543callback%243Dparent.sinaSSOController.feedBackUrlCallBack%334sudaref%3Dweibo.com&ticket=ST-NjA0MgaewMjQ1MA==-1343359303-xd-7FdfarwtD0D1FBA2634A18BC615D8419&retcode=0');});}catch(e){var msg = e.message;var img = new Image();var type = 2;img.src = 'http://login.sina.com.cn/sso/debuglog?msg=' + msg +'&type=' + type;}</script></body></html>
3)服务器验证用户名、密码正确后,给客户端发送一个真正的登录地址。
如果上一步返回的retcode=0,那么text打印出来的内容中,
sinaSSOController.crossDomainAction('login',function(){location.replace
后面的那个地址就是我们真正想要的登录地址。。。。。。。获取它,并登陆。
4)客户端登录该真正的地址,才算登陆成功。。。。。。。。
第3)步不抛异常,就说明真的登陆成功了,然后请求你要的网页吧。记住,不要太频繁,最好换账号,多个机器一起抓。。。。。
数据解析不讲了,不同页面方法不同。。。。。。。
源码不给了,其实上面已经写了全部的关键代码。有问题的留言,等我这个工作做完了,一并把所有代码放出来。
- 新浪微博爬虫:模拟登陆+爬取原始页面
- [Javascript] 爬虫 模拟新浪微博登陆
- Python爬虫——模拟登陆爬取csdn页面
- python爬虫之新浪微博模拟登陆
- python模拟新浪微博登陆功能(新浪微博爬虫)
- python模拟新浪微博登陆功能(新浪微博爬虫)
- 模拟新浪微博登陆
- 模拟登陆新浪微博
- java 使用htmlunit模拟登录爬取新浪微博页面
- Python爬虫 -- 登陆新浪微博
- 模拟新浪微博页面
- 新浪微博爬虫模拟登录(爬手机版)
- 新浪微博模拟登陆的加密算法
- 模拟新浪微博自动登陆
- snoopy模拟登陆新浪微博
- snoopy 模拟新浪微博登陆
- 新浪微博JAVA代码模拟登陆
- 2015_3G新浪微博模拟登陆
- SlidingPaneLayout和DrawerLayout的区别
- 增量排序(未)
- IO密集型vs计算密集型
- Android Genymotion模拟器连接不上10.0.2.2:8080的解决办法
- mysql慢查询相当
- 新浪微博爬虫:模拟登陆+爬取原始页面
- spring基于java配置@Configuration和@Bean用法【代码示例】
- 程序员面试以及工作中真实问题汇编!
- 1-100中6的倍数有多少个
- win10系统,安装Photoshop_CS6并且无需序列号破解
- function源码分析 前言
- JavaMail发送失败的可能原因总结
- 浅谈java中的数学运算
- 随机森林(random forest)