【Python模拟登录】py2模拟登陆CSDN(人工识别验证码)

来源:互联网 发布:淘宝哪家裤子好看 编辑:程序博客网 时间:2024/06/05 08:27
  • 思路描述:

浏览器打开CSDN登陆页,使用浏览器的右键检查功能(F12)来监控HTTP请求,先通过错误的账号密码登陆CSDN,然后在“Network”中查看第一个请求的内容,如果是请求方式post那一般就对了,如果不是那就往下一个一个找,如图一:

图一 图一

把requests URL复制出来作为登录的url(分号后面的不要),右边的上下滑动杆拉到最下面查看需要提交哪些数据,如图二:

表单数据
图二

红框中的数据就是需要提交的数据,只要正确模拟出这些数据就能登录了,通过查看登录页的源码后,可以发现除了‘username’和‘password’两项需要填写外,其他的项都在网页源码中可以提取,现在登录基本没有什么问题,接下来说验证码。
通过分析可以知道csdn的验证码只在‘账号正确,密码错误一次或以上的情况下’出现,且错误五次会提示等10分钟再登录(是针对账号的,换个账号不用等),现在我们可以故意输错密码让验证码弹出来,然后分析页面源码找到验证码图片的url,下载到本地,在程序中自动打开图片,人工识别输入即可。

以上就是整个模拟登录的大概思路,具体分析细节无闲暇详述(=。=),如果刚接触模拟登录,可以看下这篇文章,Python使用requests库模拟登陆网站的方式–以豆瓣为例
它的前期分析可以学习一下。我使用requests库的session模块来维持前期获取post参数的会话,以保证多次获取url时的post表单中的一些参数(lt,execution,还有验证码图片)不变;当然,也可以使用urllib2中的opener来实现,有兴趣的话你可以试试。

在写代码时,需要注意的是,最好按照一定的格式来写,这样写出来的代码可读性佳,看起来也优雅。

代码如下:

# -*- coding: utf-8 -*-# @Time     : 2017/12/16 8:46# @Author   : ELI# @IDE      : PyCharm# @PJ_NAME  : Login_csdnimport requestsimport reimport jsonimport os, sysimport subprocessclass CSDN:    '''    编写主类    '''    def __init__(self, acount, passwd):        '''        初始化各种变量以供类中的其他方法调用,代入用户名和密码参数        :param acount:        :param passwd:        '''        self.url = 'https://passport.csdn.net/account/verify'        header = {'User-Agent': 'Safari/537.36'}        self.current_dir = os.path.join(sys.path[0], 'cookies.txt')  # 定义一个变量存放cookies的保存路径        self.acount = acount        self.passwd = passwd        self.session = requests.session()  # 定义核心变量 session,用于携带headers/cookies参数访问url        self.session.headers = header  # 添加headers        self.cookie_exists = self.load_cookie()        self.captchaFile = os.path.join(sys.path[0], "captcha.jpg")        # 判断本地有无cookie文件        if self.cookie_exists:            print '=' * 50            print '已检测到cookie文件,直接从本地加载cookie...'            self.session.cookies.update(self.cookie_exists)  # 添加cookies        else:            print '=' * 50            print '未检测到cookies文件存在,此次为第一次登录,登录成功后将保存cookies文件!'            print '=' * 50    def get_login_data(self):        '''        获取并返回post表单        :return:        '''        # 如果存在cookie,就不运行这个方法        self.cookie_exists = self.load_cookie()        if self.cookie_exists:            print '<#提示#:当前为‘已登录’状态!勿需运行get_login_data方法>\n'            pass        else:            html = self.session.post(self.url).text            # print html  #调试用            lt = re.search('LT-\w+-\w+', html).group()  # 正则获取指定字符串,此处相对于使用bs更快更简便            execution = re.search('execution?.*value=.(\w+)', html).group(1)  # 正则获取指定字符串            self.lt = lt;            self.exe = execution            postdata = {                'gps': '',                'username': self.acount,                'password': self.passwd,                'validateCode': '',  #第一次登录时可能不需要这个参数,值可以留空                'lt': lt,                'execution': execution,                '_eventId': 'submit',            }  # 第一次登录需要提交的表单            # print postdata   #调试用            # print html            return postdata    def check_captcha(self, postdata, check_img_url, html):        '''        写一个方法来解决验证码        :param postdata:        :param check_img_url        :return:        '''        # 写两个正则作为判断错误类型的依据        check_captcha_pat = u'验证码错误'        check_captcha = re.search(check_captcha_pat, html)        check_pass_error_pat = u'密码不正确'        check_pass_error = re.search(check_pass_error_pat, html)        if check_captcha:            print '说验证码错误?'        elif check_pass_error:            print '账号或密码不对,修改一下重新运行吧。'        else:            print '登错5次了。。等10分钟吧,要么换个账号继续。。'            sys.exit()        # 保存验证码到本地        img = self.session.get(check_img_url).content        with open(self.captchaFile, 'wb')as f:            f.write(img)        # 打开验证码图片,登录成功后自动删除        subprocess.call(self.captchaFile, shell=True)        captcha = raw_input('识别到验证码,关闭图片后输入验证码:')        postdata['validateCode'] = captcha        new_postdata = postdata        os.remove(self.captchaFile)        # 回调login方法,提交加上验证码参数        self.login(postdata=new_postdata)    def login(self, postdata):        '''        第一次登录时运行,登录成功后保存cookie        :param postdata:        :return:        '''        if os.path.exists(self.current_dir):            print '<#提示#:当前为‘已登录’状态!勿需运行login方法>\n'            pass        else:            print '正在登录中...'            html = self.session.post(self.url, data=postdata).text            # print html            check_string = ['redirect = "http://www.csdn.net/"', 'redirected to http://www.csdn.net/']  #            for string in check_string:                check_it = re.search(string, html)                if check_it:  # 若登录成功,网页的response会包含check_string中的字符串,这里通过正则抓取来检测即可                    print '登录csdn网站成功!'                    self.savecookie()                    break            else:                captcha_pat = 'src=.(.*?). id=.yanzheng.'                check_img = re.search(captcha_pat, html)  # 正则抓取验证码的url                check_pass_error_pat = [u'密码不正确',u'系统检测到账号异常']                for string in check_pass_error_pat:                    check_pass_error = re.search(string, html)  # 正则抓取关键字符来判断错误类型                # 如果登录失败了,要么账号/密码不对,要么有验证码                    if check_pass_error:                        print '账号或密码不对,修改一下重新运行吧。'                        sys.exit()                    else:pass                if check_img:                    check_img_url = check_img.group(1)                    # print html                    self.check_captcha(postdata, check_img_url, html)                else:                    print '未抓取到验证码图片url,登录URL被跳转到其他页面,请调试!'  # 为以后网页结构调整做个预判                    #print html    def savecookie(self):        '''        把登陆后的cookie保存到文件        此处将字典对象转化为字符串进行存储        :return:        '''        with open(self.current_dir, 'wb') as f:            cookies = self.session.cookies.get_dict()            json.dump(cookies, f)            print '=' * 50            print '已在当前目录下生成cookie文件:%s' % self.current_dir    def load_cookie(self):        '''        如果在本地存在cookies文件        则从本地文件加载cookie,没有就返回空        :return:        '''        if os.path.exists(self.current_dir):            with open(self.current_dir) as f:                cookie = json.load(f)                return cookie        else:            return  # 返回None    def view_blog(self):        '''        访问博客列表页(这个页面是需要登录才能访问的)        :return:        '''        url = 'http://write.blog.csdn.net/postlist'        html = self.session.get(url).text        check_string = u'文章列表'        check_it = re.search(check_string, html)  # 如果访问博客列表页成功,网页内容会包含check_string,所以通过正则抓取来判断即可        if check_it:            print '=' * 50            print '访问个人博客列表页成功,输出html内容:'            print '=' * 50            print html        else:            print '=' * 50            print '未知原因导致失败,请自行调试!'            print '=' * 50    # 登录成功保存cookie后,运行这个方法,调用上面写好的类中的session对象,可直接访问主域名是csdn.net的其他URL    def open_csdn_site(self, url, data=None, timeout=5):        '''        返回登录成功后的session        :return:        '''        return self.session.get(url, data=data, timeout=timeout)if __name__ == '__main__':  # 若在本程序自身中(非调用)运行,则运行下面的代码    u = 'random@qq.com'  # csdn账号(邮箱/手机/账号昵称)    p = '123456'  # csdn密码    c = CSDN(acount=u, passwd=p)    data = c.get_login_data()  # 用于第一次登录获取post表单,后续不用再运行    log = c.login(data)  # 用于第一次登录获取cookie,后续不用再运行    # blog = c.view_blog()     #登录博客主页    # print c.open_csdn_site('http://my.csdn.net/').text

参考文章:http://blog.csdn.net/shell_zero/article/details/50783078
如果有什么疑问请留言,会尽量回复。

资源群(IT各领域、非技术)645026970

原创粉丝点击