某麒麟网站模拟登录(验证码识别)

这是「进击的Coder」的第 707 篇技术分享

作者:TheWeiJun

来源:逆向与爬虫的故事

阅读本文大概需要 7 分钟。

 目录


一、前言介绍

二、模拟登录

三、参数分析

四、代码实现

五、思路总结


趣味模块

      小军是一名 spider 工程师,最近有个新的需求,领导希望小军能够写一个模拟登录,完成每天定时导出报表工作。小军拿到领导给的任务后,马上开始写代码,但是在模拟登录过程中遇到了验证码。接下来咱们一起去看看小军是如何实现的模拟登录和解决的验证码识别吧!


一、前言介绍

1.  什么是模拟登录?

解释:网页上以及 app 中输入账号密码的过程称为登录,不经过登录有些页面是无法直接跳转的。而模拟登录就是模拟手动输入账号密码的过程,获得登录成功后的 cookie,以此 cookie 直接访问需要登录才能进入的页面,从而获取数据。

2.  什么是 Cookie?

解释:cookie 是某些网站为了辨别用户身份,进行 Session 跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息。

3.  什么是 Session?

解释:Session 是另一种记录客户状态的机制,不同的是 Cookie 保存在客户端浏览器中,而 Session 保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是 Session。客户端浏览器再次访问时只需要从该 Session 中查找该客户的状态就可以了。


二、模拟登录

1、找到我们本次需要模拟登录的网站,打开网页,截图如下所示:

0b07a6c2331dfab5c9d3f5865d1a6b66.png

2、完成模拟登录操作,浏览器查看相关请求包,截图如下所示:

1520037e753017c2bb188dced1bdba36.png

环节说明:因为我们想要获取登录的协议接口,所以我们随便输入内容,可查看到模拟登录所需要的参数主要为上图四个。接下来,我们只需要模拟这四个参数即可实现模拟登录!


三、参数分析

1、参数初判断,需要我们模拟的参数主要有以下四个:

  • username:登录所需要的账号。

  • password:登录所需要的密码。

  • captcha:登录所需要的验证码。

  • _token:登录所需要的 token 认证。

2、验证码接口定位,打开网页源码,截图如下所示:

2715b1b63e2ac7f60b4cec15c331cc67.png

环节说明:在模拟登录过程中,我们需要访问首页页面的验证码才能保证和真实登录时候的验证码流程一致,否则会产生数据不同步问题产生。这个时候,实现模拟登录我们最好使用 session 保持会话,这样会避免一些干扰问题存在。

3、_token 参数模拟,表单提交时候需要同步的参数,截图如下所示:

426df2223fd29def70b43a33c7fafbee.png

环节说明:通过观察上图,我们可以看到其实这个参数其实也存在于首页页面中,其他网站的我觉得流程也类似,基本是通用的,我们只需要通过 xpath 提取即可!参数分析流程完毕后,接下来我们进入代码实现流程环节吧。


四、代码实现

1、验证码 url、_token 参数获取实现

def start_requests(self):
    response = self.request(self.auth_url)
    resp = etree.HTML(response)
    captcha_url = resp.xpath("//img[@class='captcha-img']/@src")[0]
    _token = resp.xpath("//input[@name='_token']")[0]
    token = _token.attrib.get("value")


代码运行后,终端输出信息如下:

d9cb8f03ee0a3d135dd9e77802ed3498.png

2、验证码图片保存及识别实现

def get_captcha(self, captcha_url):
    response = self.request(captcha_url)
    text = self.ocr.recognition(response)
   return text

环节说明:将刚刚获取的验证码url进行下载并提取验证码内容,与我们保存的图片进行比对,查看识别率是否准确。验证码识别模型训练我会在后面的文章中教大家如何实现!

运行当前代码,截图如下所示:

ee2becfdbde91090f1d37f1912de00e9.png

查看保存于本地的验证码,截图如下:

f69667137ac2ba5b7aee6517ff68a3c9.png

环节说明:此刻我们可以看到保存本地的验证和我们识别的文本内容完全一致,接下来上完整代码,再次运行看看是否能登录成功吧。

注意细节:最后模拟登录时的 url 和之前首页的 url 是一致的,只是请求的方式从 get 变成了 post

3、完整代码实现如下

# -*- coding: utf-8 -*-
# ------------------------------
# @author : 公众号:逆向与爬虫的故事
# ------------------------------
import requests
from lxml import etree
from captcha_ocr import CaptchaOcr




class HuoSpider(object):
    def __init__(self):
        self.headers = {
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
            'Accept-Language': 'zh-CN,zh;q=0.9',
            'Cache-Control': 'no-cache',
            'Connection': 'keep-alive',
            'Origin': 'http://www.xxxx.com',
            'Pragma': 'no-cache',
            'Referer': 'http://www.xxxx.com/dgbak/auth/login',
            'Upgrade-Insecure-Requests': '1',
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
        }
        self.auth_url = 'http://www.xxxx.com/dgbak/auth/login'
        self.session = requests.Session()
        self.ocr = CaptchaOcr()


    def get_captcha(self, captcha_url):
        response = self.request(captcha_url)
        text = self.ocr.recognition(response)
        return text


    def request(self, url, data=None):
        if data:
            resp = self.session.post(url=url, headers=self.headers, data=data, verify=False)
        else:
            resp = self.session.get(url=url, headers=self.headers, verify=False)
        return resp.content


    def start_requests(self):
        response = self.request(self.auth_url)
        resp = etree.HTML(response)
        captcha_url = resp.xpath("//img[@class='captcha-img']/@src")[0]
        _token = resp.xpath("//input[@name='_token']")[0]
        token = _token.attrib.get("value")
        self.auth_requests(captcha_url, token)


    def auth_requests(self, captcha_url, token):
        data = {
            'username': '186******',
            'password': '123456****',
            'captcha': self.get_captcha(captcha_url),
            '_token': token,
        }
        response = self.request(self.auth_url, data=data)
        resp = etree.HTML(response)
        user_name = resp.xpath("//span[@class='hidden-xs']/text()")
        if user_name:
            print(f"登录后的用户名称: {user_name[0]}")




if __name__ == '__main__':
    hs = HuoSpider()
    hs.start_requests()

代码 run 起来后,截图如下所示:

974f04419739cb80101c38f216cfabe7.png

网站页面登录成功后,截图如下所示:

881045f5007238b11179306521c724af.png

总结:对比上面两张截图,我们发现内容完全一致,此刻我们已经实现了模拟登录。


五、思路总结

回顾整个分析流程,本次难点主要概括为以下几点:

  • 如何快速定位到模拟登录的接口

  • 模拟每一个参数的生成并能实现

  • 如何实现对验证码内容文字的提取

  • 区分同一个 url 不同的 method 方法

今天分享到这里就结束了,欢迎大家关注下期文章,我们不见不散⛽️

fac64223cfc9b7768dc14711843a99fb.png

End

崔庆才的新书《Python3网络爬虫开发实战(第二版)》已经正式上市了!书中详细介绍了零基础用 Python 开发爬虫的各方面知识,同时相比第一版新增了 JavaScript 逆向、Android 逆向、异步爬虫、深度学习、Kubernetes 相关内容,‍同时本书已经获得 Python 之父 Guido 的推荐,目前本书正在七折促销中!

内容介绍:《Python3网络爬虫开发实战(第二版)》内容介绍

8db75284489f1a857881b0d49e4cc670.jpeg

扫码购买

33e87de693e3ad22d082ab508595cb43.png

e76cbd9d0cf9d761a8b5758faf5d82bc.png

点个在看你最好看

outside_default.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值