码迷,mamicode.com
首页 > 编程语言 > 详细

python爬虫scrapy框架——人工识别登录知乎倒立文字验证码和数字英文验证码(2)

时间:2017-09-14 13:30:14      阅读:1220      评论:0      收藏:0      [点我收藏+]

标签:main   cookies   打开   word   def   with open   密码   http   size   

操作环境:python3

在上一文中python爬虫scrapy框架——人工识别登录知乎倒立文字验证码和数字英文验证码(1)我们已经介绍了用Requests库来登录知乎,本文如果看不懂可以先看之前的文章便于理解

本文将介绍如何用scrapy来登录知乎。


 不多说,直接上代码:

import scrapy
import re
import json


class ZhihuSpider(scrapy.Spider):
    name = zhihu
    allowed_domains = [www.zhihu.com]
    start_urls = [https://www.zhihu.com/]

    headers = {
        HOST: www.zhihu.com,
        Referer: https://www.zhihu.com,
        User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8,
    }

    def parse(self, response):
        pass

    def parse_detail(self, response):
        # 爬取文章细节
        pass

    # scrapy开始时先进入start_requests()
    def start_requests(self):
        # 为了提取_xsrf:要先访问知乎的登录页面,让scrapy在登录页面获取服务器给我们的数据(_xsrf),再调用login
        return [scrapy.Request(https://www.zhihu.com/#signin, headers=self.headers, callback=self.login)]

    def login(self, response):
        xsrf = ‘‘
        match_obj = re.match([\s\S]*name="_xsrf" value="(.*?)", response.text)
        if match_obj:
            xsrf =  match_obj.group(1)

        # 如果提取到了xsrf就进行下面的操作,如果没xsrf有就没必要往下做了
        if xsrf:
            post_data = {
                captcha_type: cn,
                _xsrf: xsrf,
                phone_num: 13043330319,
                password: Wcw19961223,
                captcha: ‘‘,
            }
            import time
            captcha_url = https://www.zhihu.com/captcha.gif?r=%d&type=login&lang=cn % (int(time.time() * 1000))
            # scrapy会默认把Request的cookie放进去
            return scrapy.Request(captcha_url, headers=self.headers, meta={post_data: post_data}, callback=self.login_after_captcha)

    def login_after_captcha(self, response):
        # 保存并打开验证码
        with open(captcha.gif, wb) as f:
            f.write(response.body)
            f.close()
        from PIL import Image
        try:
            img = Image.open(captcha.gif)
            img.show()
        except:
            pass
        # 输入验证码
        captcha = {
            img_size: [200, 44],
            input_points: [],
        }
        points = [[22.796875, 22], [42.796875, 22], [63.796875, 21], [84.796875, 20], [107.796875, 20],
                  [129.796875, 22], [150.796875, 22]]
        seq = input(请输入倒立字的位置\n>)
        for i in seq:
            captcha[input_points].append(points[int(i) - 1])
        captcha = json.dumps(captcha)

        post_url = https://www.zhihu.com/login/phone_num
        post_data = response.meta.get(post_data, {})
        post_data[captcha] = captcha
        return [scrapy.FormRequest(
            # 在这里完成像之前的requests的登录操作,每一个Request如果要做下一步处理都要设置callback
            url=post_url,
            formdata=post_data,
            headers=self.headers,
            callback=self.check_login,
        )]

    def check_login(self, response):
        # 验证服务器的返回数据判断是否成功
        text_json = json.loads(response.text)
        if msg in text_json and text_json[msg] == 登录成功:
            print(登录成功!)
            for url in self.start_urls:
                yield scrapy.Request(url, dont_filter=True, headers=self.headers)

 这个文件是你爬虫目录下的spider/zhihu.py,有scrapy基础的都看得懂。

下面让我们一起分析一下这个逻辑


 

首先你要知道:

  1. 如果要爬取知乎文章就必须先登录。
  2. 爬虫开始前要执行 start_requests() 函数 ,然后执行 parse() 函数。

所以我们要在 start_requests() 里进行登录,再在 parse() 里进行提取我们要爬取的字段。这里我们不分析 parse() 怎么写,只分析如何登录。下面让我们逐步分析如何登录:

首先要访问知乎的登录界面获取 "_xsrf" 字段的值

def start_requests(self):
    return [scrapy.Request(https://www.zhihu.com/#signin, headers=self.headers, callback=self.login)]

在scrapy请求了https://www.zhihu.com/#signin后,知乎服务器返回的cookies就会被scrapy保存,下次请求(request)会默认带着这些cookies。

在 login() 函数里进行提取 "_xsrf" 字段(看不懂如何提取的可参考之前的文章),并去请求知乎的验证码URL,这里是必须要注意的,在请求知乎的验证码URL后,知乎服务器会返回cookies,我们在提交验证码字段时必须带上直呼服务器给你的cookies,知乎服务器会进行匹配,如果cookies不对就会验证失败。

def login(self, response):
    xsrf = ‘‘
    match_obj = re.match([\s\S]*name="_xsrf" value="(.*?)", response.text)
    if match_obj:
        xsrf =  match_obj.group(1)

    # 如果提取到了xsrf就进行下面的操作,如果没xsrf有就没必要往下做了
    if xsrf:
        post_data = {
            captcha_type: cn,
            _xsrf: xsrf,
            phone_num: ‘这里写你登录的电话号,
            password: ‘这里写你的登录密码,
            captcha: ‘‘,
        }
        import time
        captcha_url = https://www.zhihu.com/captcha.gifr=%d&type=login&lang=cn % (int(time.time() * 1000))
        # scrapy会默认把Request的cookie放进去
        yield scrapy.Request(captcha_url, headers=self.headers, meta={post_data: post_data}, callback=self.login_after_captcha)

向知乎服务器请求验证码后,这个 request 返回的 response 里其实就是验证码图片了,下面我们会调用 login_after_captcha() 函数,进行验证码图片的保存、自动打开、手动输入验证码的位置,再利用 python 的 Json 模块把 captcha 这个dict转换成 Json 格式放入 post_data 中。顺便一提,目前这里的 yield 完全可以用 return 代替。

def login_after_captcha(self, response):
    # 保存并打开验证码
    with open(captcha.gif, wb) as f:
        f.write(response.body)
        f.close()
    from PIL import Image
    try:
        img = Image.open(captcha.gif)
        img.show()
    except:
        pass
    # 输入验证码
    captcha = {
        img_size: [200, 44],
        input_points: [],
    }
    points = [[22.796875, 22], [42.796875, 22], [63.796875, 21], [84.796875, 20], [107.796875, 20],
              [129.796875, 22], [150.796875, 22]]
    seq = input(请输入倒立字的位置\n>)
    for i in seq:
        captcha[input_points].append(points[int(i) - 1])
    captcha = json.dumps(captcha)

    post_url = https://www.zhihu.com/login/phone_num
    post_data = response.meta.get(post_data, {})
    post_data[captcha] = captcha
    return [scrapy.FormRequest(
        # 在这里完成像之前的requests的登录操作,每一个Request如果要做下一步处理都要设置callback
        url=post_url,
        formdata=post_data,
        headers=self.headers,
        callback=self.check_login,
    )]

把填写好的 post_data 发送给知乎登录URL:https://www.zhihu.com/login/phone_num,这里只演示电话号码登录,邮箱登录一个原理,只不过URL不一样:https://www.zhihu.com/login/email。之后我们要调用 check_login() 函数来检查是否登录成功,思路就是查看返回的"msg"字段是否为"登陆成功"。然后再调用scrapy原有的 start_request() 函数里的方法,经查看源码它的方法实际就是下面的遍历self.start_url再进行request(我的start_url是知乎主页,所以这个request就会访问知乎主页)

def check_login(self, response):
    # 验证服务器的返回数据判断是否成功
    text_json = json.loads(response.text)
    if msg in text_json and text_json[msg] == 登录成功:
        print(登录成功!)
        for url in self.start_urls:
            yield scrapy.Request(url, dont_filter=True, headers=self.headers)

由于我们已经登陆成功了,scrapy再访问知乎主页www.zhihu.com就会带着知乎服务器返回已经登录成功的cookies,因此就会直接进入登录成功的主页。

到此为止,我们就大功告成了!

技术分享

 

让我们利用 Pycharm 的 Debug 模式在parse那打个断点,查看response的text,已经登录上知乎了,是不是很开心!

python爬虫scrapy框架——人工识别登录知乎倒立文字验证码和数字英文验证码(2)

标签:main   cookies   打开   word   def   with open   密码   http   size   

原文地址:http://www.cnblogs.com/wangchaowei/p/7518979.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!