python模拟新浪微博登陆功能(新浪微博爬虫)

有些网站设置了权限,只有在登录了之后才能爬取网站的内容,如何模拟登录,目前的方法主要是利用浏览器cookie模拟登录。

浏览器访问服务器的过程

在用户访问网页时,不论是通过URL输入域名或IP,还是点击链接,浏览器向WEB服务器发出了一个HTTP请求(Http Request),WEB服务器接收到客户端浏览器的请求之后,响应客户端的请求,发回相应的响应信息(Http Response),浏览器解析引擎,排版引擎分析返回的内容,呈现给用户。WEB应用程序在于服务器交互的过程中,HTTP请求和响应时发送的都是一个消息结构。

Http消息

当浏览器向服务器发送请求的时候,发出http请求消息报文,服务器返回数据时,发出http响应消息报文,这两种类型的消息都是由一个起始行,消息头,一个指示消息头结束的空行和可选的消息体组成。http请求消息中,起始行包括请求方法,请求的资源, HTTP协议的版本号,消息头包含各种属性,消息体包含数据,GET请求并没有消息主体,因此在消息头后的空白行中没有其他数据。Http响应消息中,起始行包括HTTP协议版本,http状态码和状态,消息头包含各种属性,消息体包含服务器返回的数据内容。

如下图从fiddler抓取的http请求和http响应,GET请求内容为空,故消息头之后的空行和消息体都为空。

服务器发送的响应消息如下,浏览器正常接收到服务器发回的http报文

从上可以看到,cookie在http请求和http响应的头信息中,cookie是消息头的一种很重要的属性。

什么是Cookie?

当用户通过浏览器首次访问一个域名时,访问的WEB服务器会给客户端发送数据,以保持WEB服务器与客户端之间的状态保持,这些数据就是Cookie,它是 Internet 站点创建的 ,为了辨别用户身份而储存在用户本地终端上的数据,Cookie中的信息一般都是经过加密的,Cookie存在缓存中或者硬盘中,在硬盘中的是一些小文本文件,当你访问该网站时,就会读取对应网站的Cookie信息,Cookie有效地提升了我们的上网体验。一般而言,一旦将 Cookie 保存在计算机上,则只有创建该 Cookie 的网站才能读取它。

为什么需要Cookie

Http协议是一个无状态的面向连接的协议,Http协议是基于tcp/ip协议层之上的协议,当客户端与服务器建立连接之后,它们之间的TCP连接一直都是保持的,至于保持的时间是多久,是通过服务器端来设置的,当客户端再一次访问该服务器时,会继续使用上一次建立的连接,但是,由于Http协议是无状态的,WEB服务器并不知道这两个请求是否同一个客户端,这两次请求之间是独立的。 为了解决这个问题, Web程序引入了Cookie机制来维护状态.cookie可以记录用户的登录状态,通常web服务器会在用户登录成功后下发一个签名来标记session的有效性,这样免去了用户多次认证和登录网站。记录用户的访问状态。

Cookie的种类

会话Cookie(Session Cookie):这个类型的cookie只在会话期间内有效,保存在浏览器的缓存之中,用户访问网站时,会话Cookie被创建,当关闭浏览器的时候,它会被浏览器删除。

持久Cookie(Persistent Cookie): 这个类型的cookie长期在用户会话中生效。当你设置cookie的属性Max-Age为1个月的话,那么在这个月里每个相关URL的http请求中都会带有这个cookie。所以它可以记录很多用户初始化或自定义化的信息,比如什么时候第一次登录及弱登录态等。

Secure cookie:安全cookie是在https访问下的cookie形态,以确保cookie在从客户端传递到Server的过程中始终加密的。

HttpOnly Cookie :这个类型的cookie只能在http(https)请求上传递,对客户端脚本语言无效,从而有效避免了跨站攻击。

第三方cookie: 第一方cookie是当前访问的域名或子域名下的生成的Cookie。

第三方cookie:第三方cookie是第三方域名创建的Cookie。

Cookie的构成

Cookie是http消息头中的一种属性,包括:Cookie名字(Name)Cookie的值(Value),Cookie的过期时间(Expires / Max-Age),Cookie作用路径(Path),Cookie所在域名(Domain),使用Cookie进行安全连接(Secure)。

前两个参数是Cookie应用的必要条件,另外,还包括Cookie大小(Size,不同浏览器对Cookie个数及大小限制是有差异的)。

python模拟登录

设置一个cookie处理对象,它负责 将cookie添加到http请求中,并能从http响应中得到cookie , 向网站登录页面发送一个请求Request, 包括登录url,POST请求的数据,Http header 利用urllib2.urlopen发送请求,接收WEB服务器的Response。

首先我们查看登陆页面源码

当我们使用urllib处理url的时候,实际上是通过urllib2.OpenerDirector实例进行工作,他会自己调用资源进行各种操作如通过协议、打开url、处理cookie等。而urlopen方法使用的是默认的opener来处理问题,基本的urlopen()函数不支持验证、cookie或其他的HTTP高级功能。要支持这些功能,必须使用build_opener()函数来创建自己的自定义Opener对象。

cookielib模块定义了自动处理HTTP cookies的类,用来访问那些需要cookie数据的网站,cookielib模块包括CookieJar,FileCookieJar,CookiePolicy,DefaultCookiePolicy,Cookie及FileCookieJar的子类MozillaCookieJar和LWPCookieJar,CookieJar对象可以管理HTTP cookies,将cookie添加到http请求中,并能从http响应中得到cookie,FileCookieJar对象主要是从文件中读取cookie或创建cookie,其中,MozillaCookieJar是为了创建与Mozilla浏览器cookies.txt兼容的FileCookieJar实例,LWPCookieJar是为了创建与libwww-perl的Set-Cookie3文件格式兼容的FileCookieJar实例,用LWPCookieJar保存的cookie文件易于人类阅读。默认的是FileCookieJar没有save函数,而MozillaCookieJar或LWPCookieJar都已经实现了。 所以可以用MozillaCookieJar或LWPCookieJar,去自动实现cookie的save。

[python]

  1. #! /usr/bin/env python
  2. #coding:utf-8
  3. import sys
  4. import re
  5. import urllib2
  6. import urllib
  7. import requests
  8. import cookielib
  9. ## 这段代码是用于解决中文报错的问题
  10. reload(sys)
  11. sys.setdefaultencoding("utf8")
  12. #####################################################
  13. #登录人人
  14. loginurl = 'http://www.renren.com/PLogin.do'
  15. logindomain = 'renren.com'
  16. class Login(object):
  17. def __init__(self):
  18. self.name = ''
  19. self.passwprd = ''
  20. self.domain = ''
  21. self.cj = cookielib.LWPCookieJar()
  22. self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cj))
  23. urllib2.install_opener(self.opener)
  24. def setLoginInfo(self,username,password,domain):
  25. '''''设置用户登录信息'''
  26. self.name = username
  27. self.pwd = password
  28. self.domain = domain
  29. def login(self):
  30. '''''登录网站'''
  31. loginparams = {'domain':self.domain,'email':self.name, 'password':self.pwd}
  32. headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36'}
  33. req = urllib2.Request(loginurl, urllib.urlencode(loginparams),headers=headers)
  34. response = urllib2.urlopen(req)
  35. self.operate = self.opener.open(req)
  36. thePage = response.read()
  37. if __name__ == '__main__':
  38. userlogin = Login()
  39. username = 'username'
  40. password = 'password'
  41. domain = logindomain
  42. userlogin.setLoginInfo(username,password,domain)
  43. userlogin.login()

模拟登录新浪微博(Python)

PC 登录新浪微博时, 在客户端用js预先对用户名、密码都进行了加密, 而且在POST之前会GET 一组参数,这也将作为POST_DATA 的一部分。 这样, 就不能用通常的那种简单方法来模拟POST 登录( 比如 人人网 )。 由于要用的一部分微博数据用API获取不方便, 所以还是要自己写个小爬虫, 模拟登录是必不可少的。琢磨了一下这个东西,最终登录成功。 1, 在提交POST请求之前, 需要GET 获取两个参数。 地址是:http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.3.18) 得到的数据中有 "servertime" 和 "nonce" 的值, 是随机的,其他值貌似没什么用。 2, 通过httpfox 观察POST 的数据, 参数较复杂,其中 “su" 是加密后的username, "sp"是加密后的password。"servertime" 和 ”nonce" 是上一步得到的。其他参数是不变的。 username 经过了BASE64 计算: username = base64.encodestring( urllib.quote(username) )[:-1]; password 经过了三次SHA1 加密, 且其中加入了 servertime 和 nonce 的值来干扰。 即: 两次SHA1加密后, 将结果加上 servertime 和 nonce 的值, 再SHA1 算一次。 将参数组织好, POST请求。 这之后还没有登录成功。 POST后得到的内容中包含一句 location.replace("http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack&retcode=101&reason=%B5%C7%C2%BC%C3%FB%BB%F2%C3%DC%C2%EB%B4%ED%CE%F3"); 这是登录失败时的结果, 登录成功后结果与之类似, 不过retcode 的值是0 。接下来再请求这个URL,这样就成功登录到微博了。 记得要提前build 缓存。 下面是完整代码(没加注释,凑合看吧): #! /usr/bin/env python #coding=utf8 import urllib import urllib2 import cookielib import base64 import re import json import hashlib cj = cookielib.LWPCookieJar() cookie_support = urllib2.HTTPCookieProcessor(cj) opener = urllib2.build_opener(cookie_support, urllib2.HTTPHandler) urllib2.install_opener(opener) postdata = { 'entry': 'weibo', 'gateway': '1', 'from': '', 'savestate': '7', 'userticket': '1', 'ssosimplelogin': '1', 'vsnf': '1', 'vsnval': '', 'su': '', 'service': 'miniblog', 'servertime': '', 'nonce': '', 'pwencode': 'wsse', 'sp': '', 'encoding': 'UTF-8', 'url': 'http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack', 'returntype': 'META' } def get_servertime(): url = 'http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=dW5kZWZpbmVk&client=ssologin.js(v1.3.18)&_=1329806375939' data = urllib2.urlopen(url).read() p = re.compile('\((.*)\)') try: json_data = p.search(data).group(1) data = json.loads(json_data) servertime = str(data['servertime']) nonce = data['nonce'] return servertime, nonce except: print 'Get severtime error!' return None def get_pwd(pwd, servertime, nonce): pwd1 = hashlib.sha1(pwd).hexdigest() pwd2 = hashlib.sha1(pwd1).hexdigest() pwd3_ = pwd2 + servertime + nonce pwd3 = hashlib.sha1(pwd3_).hexdigest() return pwd3 def get_user(username): username_ = urllib.quote(username) username = base64.encodestring(username_)[:-1] return username def login(): username = '你的登录邮箱' pwd = '你的密码' url = 'http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.3.18)' try: servertime, nonce = get_servertime() except: return global postdata postdata['servertime'] = servertime postdata['nonce'] = nonce postdata['su'] = get_user(username) postdata['sp'] = get_pwd(pwd, servertime, nonce) postdata = urllib.urlencode(postdata) headers = {'User-Agent':'Mozilla/5.0 (X11; Linux i686; rv:8.0) Gecko/20100101 Firefox/8.0'} req = urllib2.Request( url = url, data = postdata, headers = headers ) result = urllib2.urlopen(req) text = result.read() p = re.compile('location\.replace\(\'(.*?)\'\)') try: login_url = p.search(text).group(1) #print login_url urllib2.urlopen(login_url) print "登录成功!" except: print 'Login error!' login()

以上是采用POST 用户名/密码等参数(经过加密)并保存Cookie来模拟登录的方法。

一般情况下,为了保证安全性,网站会定期更新登录的detail,例如修改参数名、更新加密(散列)算法等。所以模拟登录的代码定期肯定会失效,但是如果网站没有进行大的更新的话,稍微改一改还是能用的。另外,碰到验证码的情况就更难办了,虽然程序可以一定程度地识别验证码字符,但目前很难找到简单的可以通用的验证码识别程序。

很多豆友反馈有模拟登录新浪微博抓取数据的需求,其实对于一般的微博数据获取,如用户信息、微博内容等,使用微博开放平台API是更明智的选择:速度更快,而且节省许多网页处理的功夫。对于API没有开放的数据,我们再采用模拟登录的方法。 熟悉Web的朋友只要定期维护模拟登录的代码就可以一直成功登录微博。如果不那么熟悉的话,其实可以采用更naive的思路来解决:直接将Cookie发送给新浪微博以实现模拟登录。 1,获取Cookie 很简单,使用Chrome浏览器的”开发者工具(Developer Tools)“或者Firefox的"HTTPFOX"等插件就可以直接查看自己新浪微博的Cookie。(注: 这个私人Cookie千万不要泄露哦!)

比如,Chrome 查看cookie (快捷键F12 可以调出chrome开发者工具)

cookie in chrome

2, 将Cookie作为访问微博的header参数提交 headers = {'cookie': 'your cookie'} req = urllib2.Request(url, headers=headers) #每次访问页面都带上 headers参数 r = urllib2.urlopen(req) 具体代码见:https://gist.github.com/ghostrong/d10c061000b7b65e5039

原文发布于微信公众号 - 大数据挖掘DT数据分析(datadw)

原文发表时间:2016-02-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏北京马哥教育

DNS高级应用之ACL和View

一、环境准备: 1、准备三台主机,要求如下 (1) DNS服务器双网卡:eth0:192.168.10.203 eth1: 172.16.2.1...

2627
来自专栏用户2442861的专栏

Cookie 和 Session 的使用简记

http://mertensming.github.io/2016/10/19/cookie-session/

532
来自专栏运维一切

正向代理访问腾讯云cos时http405的问题

当使用正向代理请求cos资源的时候,cos对http协议的支持会比较严谨,“宽容性”不够。可能对http协议更加谨慎一点反而更好吧

1967
来自专栏Youngxj

emlog评论排行榜插件

1953
来自专栏SeanCheney的专栏

Scrapy的架构一、Scrapy的Twisted引擎模型二、Scrapy的性能模型三、Scrapy架构组件数据流(Data flow)四、Scrapy架构

Scrapy的架构太重要了,单用一篇文章再总结整合下。前两张图来自《Learning Scrapy》,第三张图来自Scrapy 1.0中文官方文档(该中文文档...

3496
来自专栏coding

django2实战5.创建表单及发送邮件测试邮件发送创建表单页面业务逻辑搭建新建分享页面模板详情页添加分享入口结果展示

本篇要实现这样的功能:在文章详情页增加分享文章的入口,点击后跳到分享页面,提交要发送的email地址,程序将发送邮件到相应邮箱,邮件内容是文章的链接地址。

632
来自专栏运维一切

正向代理访问腾讯云cos时http405的问题

当使用正向代理请求cos资源的时候,cos对http协议的支持会比较严谨,“宽容性”不够。可能对http协议更加谨慎一点反而更好吧

933
来自专栏鬼谷君

Django提交表单时遇到403错误:CSRF verification failed

891
来自专栏编程

Scrapy 框架插件之 IP 免费代理池

Photo from Unsplash 现在很多网站都是对单个 IP 地址有访问次数限制,如果你在短时间内访问过于频繁。该网站会封掉你 IP,让你在一段时间内无...

3535
来自专栏蓝天

thrift使用小记

    Thrift是一个跨语言的服务部署框架,最初由Facebook于2007年开发,2008年进入Apache开源项目。Thrift通过一个中间语言(IDL...

821

扫码关注云+社区