python爬虫模拟登录是什么意思

Python028

python爬虫模拟登录是什么意思,第1张

有些网站需要登录后才能爬取所需要的信息,此时可以设计爬虫进行模拟登录,原理是利用浏览器cookie。

一、浏览器访问服务器的过程:

(1)浏览器(客户端)向Web服务器发出一个HTTP请求(Http request);

(2)Web服务器收到请求,发回响应信息(Http Response);

(3)浏览器解析内容呈现给用户。

二、利用Fiddler查看浏览器行为信息:

Http请求消息

(1)起始行:包括请求方法、请求的资源、HTTP协议的版本号

这里GET请求没有消息主体,因此消息头后的空白行中没有其他数据。

(2)消息头:包含各种属性

(3)消息头结束后的空白行

(4)可选的消息体:包含数据

Http响应消息:

(1)起始行:包括HTTP协议版本,http状态码和状态

(2)消息头:包含各种属性

(3)消息体:包含数据

从上面可见,cookie在Http请求和Http响应的头消息中是很重要的属性。

三、什么是cookie:

当用户通过浏览器首次访问一个域名时,访问的Web服务器会给客户端发送数据,以保持Web服务器与客户端之间的状态,这些数据就是Cookie。

它是站点创建的,为了辨别用户身份而储存在用户本地终端上的数据,其中的信息一般都是经过加密的,存在缓存或硬盘中,在硬盘中是一些小文本文件。

当访问该网站时,就会读取对应网站的Cookie信息。

作用:记录不同用户的访问状态。

四、操作过程:

在知乎登录界面输入用户名和密码,然后登录。

利用Fiddler来查看这期间浏览器和知乎服务器之间的信息交互。

(1)浏览器给服务器发送了一个POST,携带帐号和密码等信息;

从起始行可见,POST是发送给http://www.zhihu.com/login/email这个网址,内容在最下面消息体里,

也可以在Fiddler的Webforms标签下查看POST的内容,如下:

可以发现,信息里不仅有帐号(email)和密码(password),其实还有_xsrf(具体作用往后看)和remember_me(登录界面的“记住我”)两个值。

那么,在python爬虫中将这些信息同样发送,就可以模拟登录。

在发送的信息里出现了一个项:_xsrf,值为2fc4ab0f0f144c2e478c436fe3160443

这个项其实是在访问知乎登录网页https://www.zhihu.com/#signin时,网页发送过来的信息,在浏览器源码中可见:

所以需要先从登录网址https://www.zhihu.com/#signin获取这个_xsrf的值,

并连同帐号、密码等信息再POST到真正接收请求的http://www.zhihu.com/login/email网址。

(2)获取_xsrf的值:

爬取登录网址https://www.zhihu.com/#signin,从内容中获取_xsrf的值。

正则表达式。

(3)发送请求:

xsrf = 获取的_xsrf的值

data = {"email":"xxx","password":"xxx","_xsrf":xsrf}

login = s.post(loginURL, data = data, headers = headers)

loginURL:是真正POST到的网址,不一定等同于登录页面的网址;

(4)爬取登录后的网页:

response = s.get(getURL, cookies = login.cookies, headers = headers)

getURL:要爬取的登陆后的网页;

login.cookies:登陆时获取的cookie信息,存储在login中。

(5)输出内容:

print response.content

五、具体代码:

[python] view plain copy

# -*- coding:utf-8 -*-

# author:Simon

# updatetime:2016年3月17日 17:35:35

# 功能:爬虫之模拟登录,urllib和requests都用了...

import urllib

import urllib2

import requests

import re

headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.2) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.12 Safari/535.11'}

def get_xsrf():

firstURL = "http://www.zhihu.com/#signin"

request = urllib2.Request(firstURL,headers = headers)

response = urllib2.urlopen(request)

content = response.read()

pattern = re.compile(r'name="_xsrf" value="(.*?)"/>',re.S)

_xsrf = re.findall(pattern,content)

return _xsrf[0]

def login(par1):

s = requests.session()

afterURL = "https://www.zhihu.com/explore"        # 想要爬取的登录后的页面

loginURL = "http://www.zhihu.com/login/email"     # POST发送到的网址

login = s.post(loginURL, data = par1, headers = headers)                  # 发送登录信息,返回响应信息(包含cookie)

response = s.get(afterURL, cookies = login.cookies, headers = headers)    # 获得登陆后的响应信息,使用之前的cookie

return response.content

xsrf = get_xsrf()

print "_xsrf的值是:" + xsrf

data = {"email":"xxx","password":"xxx","_xsrf":xsrf}

print login(data)

六、补充:

用知乎网做完试验,发现这里好像并不需要发送_xsrf这个值。

不过有的网站在登陆时确实需要发送类似这样的一个值,可以用上述方法。

给你一个例子,可以看看:

import requests

import time

import json

import os

import re

import sys

import subprocess

from bs4 import BeautifulSoup as BS

class ZhiHuClient(object):

"""连接知乎的工具类,维护一个Session

2015.11.11

用法:

client = ZhiHuClient()

# 第一次使用时需要调用此方法登录一次,生成cookie文件

# 以后可以跳过这一步

client.login("username", "password")

# 用这个session进行其他网络操作,详见requests库

session = client.getSession()

"""

# 网址参数是账号类型

TYPE_PHONE_NUM = "phone_num"

TYPE_EMAIL = "email"

loginURL = r"http://www.zhihu.com/login/{0}"

homeURL = r"http://www.zhihu.com"

captchaURL = r"http://www.zhihu.com/captcha.gif"

headers = {

"User-Agent": "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36",

"Accept": "text/html,application/xhtml+xml,application/xmlq=0.9,image/webp,*/*q=0.8",

"Accept-Encoding": "gzip, deflate",

"Host": "www.zhihu.com",

"Upgrade-Insecure-Requests": "1",

}

captchaFile = os.path.join(sys.path[0], "captcha.gif")

cookieFile = os.path.join(sys.path[0], "cookie")

def __init__(self):

os.chdir(sys.path[0]) # 设置脚本所在目录为当前工作目录

self.__session = requests.Session()

self.__session.headers = self.headers # 用self调用类变量是防止将来类改名

# 若已经有 cookie 则直接登录

self.__cookie = self.__loadCookie()

if self.__cookie:

print("检测到cookie文件,直接使用cookie登录")

self.__session.cookies.update(self.__cookie)

soup = BS(self.open(r"http://www.zhihu.com/").text, "html.parser")

print("已登陆账号: %s" % soup.find("span", class_="name").getText())

else:

print("没有找到cookie文件,请调用login方法登录一次!")

# 登录

def login(self, username, password):

"""

验证码错误返回:

{'errcode': 1991829, 'r': 1, 'data': {'captcha': '请提交正确的验证码 :('}, 'msg': '请提交正确的验证码 :('}

登录成功返回:

{'r': 0, 'msg': '登陆成功'}

"""

self.__username = username

self.__password = password

self.__loginURL = self.loginURL.format(self.__getUsernameType())

# 随便开个网页,获取登陆所需的_xsrf

html = self.open(self.homeURL).text

soup = BS(html, "html.parser")

_xsrf = soup.find("input", {"name": "_xsrf"})["value"]

# 下载验证码图片

while True:

captcha = self.open(self.captchaURL).content

with open(self.captchaFile, "wb") as output:

output.write(captcha)

# 人眼识别

print("=" * 50)

print("已打开验证码图片,请识别!")

subprocess.call(self.captchaFile, shell=True)

captcha = input("请输入验证码:")

os.remove(self.captchaFile)

# 发送POST请求

data = {

"_xsrf": _xsrf,

"password": self.__password,

"remember_me": "true",

self.__getUsernameType(): self.__username,

"captcha": captcha

}

res = self.__session.post(self.__loginURL, data=data)

print("=" * 50)

# print(res.text) # 输出脚本信息,调试用

if res.json()["r"] == 0:

print("登录成功")

self.__saveCookie()

break

else:

print("登录失败")

print("错误信息 --->", res.json()["msg"])

def __getUsernameType(self):

"""判断用户名类型

经测试,网页的判断规则是纯数字为phone_num,其他为email

"""

if self.__username.isdigit():

return self.TYPE_PHONE_NUM

return self.TYPE_EMAIL

def __saveCookie(self):

"""cookies 序列化到文件

即把dict对象转化成字符串保存

"""

with open(self.cookieFile, "w") as output:

cookies = self.__session.cookies.get_dict()

json.dump(cookies, output)

print("=" * 50)

print("已在同目录下生成cookie文件:", self.cookieFile)

def __loadCookie(self):

"""读取cookie文件,返回反序列化后的dict对象,没有则返回None"""

if os.path.exists(self.cookieFile):

print("=" * 50)

with open(self.cookieFile, "r") as f:

cookie = json.load(f)

return cookie

return None

def open(self, url, delay=0, timeout=10):

"""打开网页,返回Response对象"""

if delay:

time.sleep(delay)

return self.__session.get(url, timeout=timeout)

def getSession(self):

return self.__session

if __name__ == '__main__':

client = ZhiHuClient()

# 第一次使用时需要调用此方法登录一次,生成cookie文件

# 以后可以跳过这一步

# client.login("username", "password")

# 用这个session进行其他网络操作,详见requests库

session = client.getSession()

1.这要看个家APP具体实现登录逻辑

2.大部分登录方法都是post方法,就用urllib包足以

3.模拟一个请求头,因为大部分公司都会过滤掉非真实用户请求

4.拦截抓包,看他们家的协议组成,推荐用

Charles

5.如果他们做了通信签名,反编译他们的apk包,寻找对应的加密密钥。如果做了混淆,我暂时没做过这块破解,抱歉。