python爬虫scrapy之登陆知乎

下面咱们看看用scrapy模拟登陆的基本写法:html

  注意:咱们常常调试代码的时候基本都用chrome浏览器,可是我就由于用了谷歌浏览器(它老是登陆的时候不提示我用验证码,误导我觉得登陆时不须要验证码,其实登陆时候必需要验证码的),这里你能够多试试几个浏览器,必定要找个提示你输入验证码的浏览器调试。python

  一、咱们登陆的时候,提示咱们输入验证码,当验证码弹出以前会有个请求,咱们打开这个请求,很明显,type是login,验证码无疑了,就算是看请求的由于名,你也应该知道这个就是验证码的请求,或者打开这个验证码的请求url,这。chrome

  

  

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

  

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

  

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

  

  

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

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

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

    def start_requests(self):
        '''
        一、首先构造并抓取登陆须要提交的验证码
        :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)]

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

    def parser_captcha(self, response):
        '''
        一、根据start_requests方法返回的验证码,将它存入本地
        二、打开下载下来的验证码
        三、这里是须要手动输入的,这里能够接入打码平台
        :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
        })

  七、下面咱们来搞定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)]

  八、上面请求完成之后,会返回咱们一个字典,这里咱们判断一下是否登陆成功,若是登陆成功之后,就执行咱们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):
        '''
        一、首先构造并抓取登陆须要提交的验证码
        :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):
        '''
        一、根据start_requests方法返回的验证码,将它存入本地
        二、打开下载下来的验证码
        三、这里是须要手动输入的,这里能够接入打码平台
        :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("登陆失败,请检查!!!")
相关文章
相关标签/搜索