一. 要实现的目标:
模拟浏览器登录帐号的过程。结合模拟登录知乎来讲解。
二. 最简单的模拟登录:(当然没法成功登录,但是最根本)
登录的过程,实际上是我们把用户名和密码给浏览器,然后浏览器把这些信息送到网站服务器,然后服务器返回看你登录成功与否。那么用python怎么模拟呢?在生产一个Requset对象的时候,request = urllib2.Request(url, data, header),其中的data参数就是浏览器给服务器的信息。
使用方法如下:
info = {'user_name' : "xxxx", 'password' : 'xxxx'} data = urllib.urlencode(info) resquest = urllib2.Request(url, data)当然,你要打开浏览器看看要模拟登录的网站的用户名和密码是用什么字符串表示的,然后写在info字典里面。
三. 存在验证码:
当然验证码要手动识别了,这里说的是如何把它显示出来。
def get_captcha(self): t = str(int(time.time()*1000)) captcha_url = 'http://www.zhihu.com/captcha.gif?r=' + t + "&type=login" html = urllib2.urlopen(captcha_url).read() fout = open("captcha.jpg", "wb") fout.write(html) fout.close() chptcha = raw_input("input the captcha: ") return chptcha拿知乎来说,就是这样。其中time.time()返回的是系统时间戳,然后自己打开图片看输入验证码,再在info['captcha'] = chptcha,然后再创建request,至于验证码的url是如何来的,看别人的代码拿来用的。其实可以爬整个登录页面,用Beautifulsoup找出验证码图片链接,然后就可以了。不过有用时间戳这么简单的方法为什么不用呢。
四. 利用cookies保存登录信息
登录进去之后,要打开别的页面,比如说要打开个人设置的页面https://www.zhihu.com/settings/profile,那么知乎网站是如何判断你是否已经登录呢?比如你不登录然后直接打开这个链接,肯定不会进去个人设置的页面的。网站判断用户状态的方法,是在用户本地存一个cookies,标明用户当前的状态,于是我们要登录,并爬取登录后的信息,就是把登录之后的cookies保存下来。
Python的实现方法:
filename = 'cookies.txt' cookies = cookielib.MozillaCookieJar(filename)这样就把cookies保存在文件中了,当然可以不保存在文件中,不过这样比较方便。(下文会说)
然后利用cookies创建一个HTTPCookieProcessor类的对象,这个对象是什么呢,就是一个handler,也就是上一节代理的handler,一样的东西,接下来都知道了,当然是可以创建一个opener了。然后这个opener就和cookies想关联了,也就是说,用这个opener打开了登录的网页并打开成功之后,再用来打开需要登录信息才可以获取信息的网页就可以直接打开了。
def get_opener(self): handler = urllib2.HTTPCookieProcessor(self.cookies) opener = urllib2.build_opener(handler) return opener如果已经保存了cookies的信息,如何加载到代码里的cookies对象呢?
cookies = cookielib.MozillaCookieJar() cookies.load(filename)先声明一个cookies对象,直接调用load方法就可以了,然后就可以创建一个opener,打开页面了。
五. 模拟登录知乎的一点说明:_xsrf
听说要加入这个参数在data里面,然而我并没有加也可以登录上去了。可以是我每次都输验证码的缘故吧。
六. 完整的模拟登录知乎代码:
几点说明:
1. 这个代码只支持手机号码登录,要改成支持2种直接改登录url。
2. 代码里面验证是否登录的方法是去https://www.zhihu.com/settings/profile页面抓取自己的真实姓名。
3. 代码在2016/8/19亲试有效。
# -*- coding: UTF-8 -*- import urllib from bs4 import BeautifulSoup import urllib2 import cookielib import time class login(object): def __init__(self, url): self.header = {'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36',} self.login_url = url self.data = None self.opener = None self.cookies = None self.account = None self.password = None def First_login(self, account, password): self.account = account self.password = password self.data = {'phone_num' : self.account, 'password' : self.password, 'rememberme':'y'} try: captcha = self.get_captcha() self.data['captcha'] = captcha except: print "no captcha" self.use_cookies() self.opener = self.get_opener() data = urllib.urlencode(self.data) request = urllib2.Request(self.login_url, data, self.header) self.opener.open(request) self.cookies.save(ignore_discard=True, ignore_expires=True) def use_cookies(self): filename = 'cookies.txt' try: cookies = cookielib.MozillaCookieJar() cookies.load(filename) isLogin = True self.cookies = cookies except: print "cookies load fail" isLogin = False self.cookies = cookielib.MozillaCookieJar(filename) return isLogin def get_opener(self): handler = urllib2.HTTPCookieProcessor(self.cookies) opener = urllib2.build_opener(handler) return opener def get_data(self): url_judge = "https://www.zhihu.com/settings/profile" isLogin = True if self.opener == None: isLogin = self.use_cookies() self.opener = self.get_opener() if isLogin == False: return False #<span class="name">(真实姓名)</span> html = self.opener.open(url_judge).read() #print html soup = BeautifulSoup(html, 'html.parser') node = soup.find("span", class_ = "name") print node.get_text() def get_captcha(self): t = str(int(time.time()*1000)) captcha_url = 'http://www.zhihu.com/captcha.gif?r=' + t + "&type=login" html = urllib2.urlopen(captcha_url).read() fout = open("captcha.jpg", "wb") fout.write(html) fout.close() chptcha = raw_input("input the captcha: ") return chptcha if __name__ == "__main__": url = "http://www.zhihu.com/login/phone_num" zhihu = login(url) while zhihu.get_data() == False: account = raw_input("input the phone number: ") password = raw_input("input the password: ") zhihu.First_login(account, password)