zoukankan      html  css  js  c++  java
  • python爬虫scrapy之登录知乎

    下面我们看看用scrapy模拟登录的基本写法:

      注意:我们经常调试代码的时候基本都用chrome浏览器,但是我就因为用了谷歌浏览器(它总是登录的时候不提示我用验证码,误导我以为登录时不需要验证码,其实登录时候必须要验证码的),这里你可以多试试几个浏览器,一定要找个提示你输入验证码的浏览器调试。

      1、我们登录的时候,提示我们输入验证码,当验证码弹出之前会有个请求,我们打开这个请求,很明显,type是login,验证码无疑了,就算是看请求的因为名,你也应该知道这个就是验证码的请求,或者打开这个验证码的请求url,这。

      

      

      验证码的图片,悲惨了,这怎么整。别着急。。

      

      2、验证码提示我们要点击倒着写的字体,这。。。,爬虫和反爬虫就是无休止的互相折磨。这明显就是上面那个图片的信息。

      

      3、机智的我,发现验证码的请求参数里面有三个参数,r是一个13位的数字,type是登录用的,lang很可疑,改改它,把cn给他改成en。mygod这不也是验证码么,就试试它了。

      

      

      4、页面基本登录原理分析完了,我们接下来看看代码怎么写,首先我们重构scrapy的start_requests方法(有scrapy基础的同学都知道,这个名字可不是瞎写的)。

      5、分析这个验证码的请求连接,https://www.zhihu.com/captcha.gif?r=1511878790500&type=login&lang=en,这里面都可以固定,但是这个验证码肯定不行,13位的数字,果断想到了当前时间

       最后,我们要请求这个url,这里必须要加上请求头信息,callback就是下面你要执行的方法。

        def start_requests(self):
            '''
            1、首先构造并抓取登录需要提交的验证码
            :return:
            '''
            t = str(int(time.time() * 1000))
            captcha_url = 'https://www.zhihu.com/captcha.gif?r={0}&type=login&lang=en'.format(t)
            return [scrapy.Request(url=captcha_url, headers=self.header, callback=self.parser_captcha)]
    

      6、上面请求完成后,就会将请求结果直接返回个下面的这个方法,所以它必须有个形式参数,来接收请求的结果,首先我们将请求的的结果,其实就是刚才我们看到的那个图片,图片的信息就在body里面,直接将整个body存成一个文件,然后我这里用的是Image打开我们存入的文件,文件都给你打开了,你还不得看看输入一下(如果你有云大码平台的服务,就直接让云大码平台搞定就行),这里我们只能自己看自己输入了。搞完了验证码,我们现在准备开始登陆,这里可不是直接用登陆的url登陆就行,你仔细的话还有个xrsf参数需要我们获取,那就请求的url直接就是登陆页面,注意你的头部信息,不伪装一下,立马给你请求出错。callback就不说了吧。这需要注意的就是,这直接把验证码存入了scrapy的meta里面了。

        def parser_captcha(self, response):
            '''
            1、根据start_requests方法返回的验证码,将它存入本地
            2、打开下载下来的验证码
            3、这里是需要手动输入的,这里可以接入打码平台
            :param response:
            :return:
            '''
            with open('captcha.jpg', 'wb') as f:
                f.write(response.body)
                f.close()
            try:
                im = Image.open('captcha.jpg')
                im.show()
                im.close()
            except:
                pass
            captcha = input("请输入你的验证>")
            return scrapy.FormRequest(url='https://www.zhihu.com/#signin', headers=self.header, callback=self.login, meta={
                'captcha': captcha
            })
    

      7、下面我们来搞定xsrf参数,这里我用xpath,一句话搞定,下面就是post_url就是上面phone_num请求里面的url,也是真正意义上的post提交登录信息的url。因为我们已经把验证码放进了meta里面了,所以这里直接获取就行。基本登录信息伪装完成以后,开始提交登录信息,登录完成以后,我们设置一个callback回调方法,检查一下登录信息。

        def login(self, response):
            xsrf = response.xpath("//input[@name='_xsrf']/@value").extract_first()
            if xsrf is None:
                return ''
            post_url = 'https://www.zhihu.com/login/phone_num'
            post_data = {
                "_xsrf": xsrf,
                "phone_num": '你的账户名称',
                "password": '你的账户密码',
                "captcha": response.meta['captcha']
            }
            return [scrapy.FormRequest(url=post_url, formdata=post_data, headers=self.header, callback=self.check_login)]
    

      8、上面请求完成以后,会返回我们一个字典,这里我们判断一下是否登录成功,如果登录成功以后,就执行我们start_urls里面的url地址,因为已经登录成功了,所以这里我们的start_urls就是https://www.zhihu.com,这样我们就可以再parse方法里面继续解析我们登录后的html信息了。

        def check_login(self, response):
            js = json.loads(response.text)
            print(js)
            if 'msg' in js and js['msg'] == '登录成功':
                for url in self.start_urls:
                    print(url)
                    yield scrapy.Request(url=url, headers=self.header, dont_filter=True)
            else:
                print("登录失败,请检查!!!")
    

      

      

    代码如下:

    import json
    import scrapy
    import time
    from PIL import Image
    
    
    class ZhihuloginSpider(scrapy.Spider):
        name = 'zhihu_login'
        allowed_domains = ['zhihu.com']
        start_urls = ['https://www.zhihu.com/']
        header = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,'
                                                ' like Gecko) Chrome/62.0.3202.94 Safari/537.36',
        }
    
        def parse(self, response):
            #主页爬取的具体内容
            print(response.text)
    
        def start_requests(self):
            '''
            1、首先构造并抓取登录需要提交的验证码
            :return:
            '''
            t = str(int(time.time() * 1000))
            captcha_url = 'https://www.zhihu.com/captcha.gif?r={0}&type=login&lang=en'.format(t)
            return [scrapy.Request(url=captcha_url, headers=self.header, callback=self.parser_captcha)]
    
        def parser_captcha(self, response):
            '''
            1、根据start_requests方法返回的验证码,将它存入本地
            2、打开下载下来的验证码
            3、这里是需要手动输入的,这里可以接入打码平台
            :param response:
            :return:
            '''
            with open('captcha.jpg', 'wb') as f:
                f.write(response.body)
                f.close()
            try:
                im = Image.open('captcha.jpg')
                im.show()
                im.close()
            except:
                pass
            captcha = input("请输入你的验证>")
            return scrapy.FormRequest(url='https://www.zhihu.com/#signin', headers=self.header, callback=self.login, meta={
                'captcha': captcha
            })
    
        def login(self, response):
            xsrf = response.xpath("//input[@name='_xsrf']/@value").extract_first()
            if xsrf is None:
                return ''
            post_url = 'https://www.zhihu.com/login/phone_num'
            post_data = {
                "_xsrf": xsrf,
                "phone_num": '你的账户名称',
                "password": '你的账户密码',
                "captcha": response.meta['captcha']
            }
            return [scrapy.FormRequest(url=post_url, formdata=post_data, headers=self.header, callback=self.check_login)]
    
        # 验证返回是否成功
        def check_login(self, response):
            js = json.loads(response.text)
            print(js)
            if 'msg' in js and js['msg'] == '登录成功':
                for url in self.start_urls:
                    print(url)
                    yield scrapy.Request(url=url, headers=self.header, dont_filter=True)
            else:
                print("登录失败,请检查!!!")
    

      

  • 相关阅读:
    如何用ps简单快速扣头发丝
    thinkphp在iis上不是出现500错误
    PHP数组函数详解大全
    一个搜图的好网站
    手把手编写PHP MVC框架实例教程
    centos配置epel和remi源
    CentOS 7 yum 安装php5.6
    20162322 朱娅霖 作业005&006 栈,队列
    2017-2018-1 bug终结者 团队博客002
    2017-2018-1 bug终结者 团队博客001
  • 原文地址:https://www.cnblogs.com/lei0213/p/7912619.html
Copyright © 2011-2022 走看看