【爬虫开发】爬虫开发从0到1全知识教程第7篇:反爬与反反爬,验证码处理【附代码文档】

随笔3周前发布 奕氏蒹葭
31 0 0

【爬虫开发】爬虫开发从0到1全知识教程第7篇:反爬与反反爬,验证码处理【附代码文档】

本教程的知识点为:爬虫概要 爬虫基础 爬虫概述 知识点: 1. 爬虫的概念 requests模块 requests模块 知识点: 1. requests模块介绍 1.1 requests模块的作用: 数据提取概要 数据提取概述 知识点 1. 响应内容的分类 知识点:了解 响应内容的分类 Selenium概要 selenium的介绍 知识点: 1. selenium运行效果展示 1.1 chrome浏览器的运行效果 Selenium概要 selenium的其它使用方法 知识点: 1. selenium标签页的切换 知识点:掌握 selenium控制标签页的切换 反爬与反反爬 常见的反爬手段和解决思路 学习目标 1 服务器反爬的原因 2 服务器常反什么样的爬虫 反爬与反反爬 验证码处理 学习目标 1.图片验证码 2.图片识别引擎 反爬与反反爬 JS的解析 学习目标: 1 确定js的位置 1.1 观察按钮的绑定js事件 Mongodb数据库 介绍 内容 mongodb文档 mongodb的简单使用 Mongodb数据库 介绍 内容 mongodb文档 mongodb的聚合操作 Mongodb数据库 介绍 内容 mongodb文档 mongodb和python交互 scrapy爬虫框架 介绍 内容 scrapy官方文档 scrapy的入门使用 scrapy爬虫框架 介绍 内容 scrapy官方文档 scrapy管道的使用 scrapy爬虫框架 介绍 内容 scrapy官方文档 scrapy中间件的使用 scrapy爬虫框架 介绍 内容 scrapy官方文档 scrapy_redis原理分析并实现断点续爬以及分布式爬虫 scrapy爬虫框架 介绍 内容 scrapy官方文档 scrapy的日志信息与配置 利用appium抓取app中的信息 介绍 内容 appium环境安装 学习目标

完整笔记资料代码:https://gitee.com/yinuo112/Backend/tree/master/爬虫/爬虫开发从0到1全知识教程/note.md

感兴趣的小伙伴可以自取哦~


全套教程部分目录:

【爬虫开发】爬虫开发从0到1全知识教程第7篇:反爬与反反爬,验证码处理【附代码文档】

【爬虫开发】爬虫开发从0到1全知识教程第7篇:反爬与反反爬,验证码处理【附代码文档】


部分文件图片:

【爬虫开发】爬虫开发从0到1全知识教程第7篇:反爬与反反爬,验证码处理【附代码文档】

反爬与反反爬

本阶段主要学习爬虫的反爬及应对方法。

验证码处理

学习目标
  1. 了解 验证码的相关知识
  2. 掌握 图片识别引擎的使用
  3. 了解 常见的打码平台
  4. 掌握 通过打码平台处理验证码的方法

1.图片验证码

1.1 什么是图片验证码

  • 验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序。

1.2 验证码的作用

  • 防止恶意破解密码、刷票、论坛灌水、刷页。有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登录尝试,实际上使用验证码是现在很多网站通行的方式(比如招商银行的网上个人银行,百度社区),我们利用比较简易的方式实现了这个功能。虽然登录麻烦一点,但是对网友的密码安全来说这个功能还是很有必要,也很重要。

1.3 图片验证码在爬虫中的使用场景

  • 注册
  • 登录
  • 频繁发送请求时,服务器弹出验证码进行验证

1.4 图片验证码的处理方案

  • 手动输入(input) 这种方法仅限于登录一次就可持续使用的情况
  • 图像识别引擎解析 使用光学识别引擎处理图片中的数据,目前常用于图片数据提取,较少用于验证码处理
  • 打码平台 爬虫常用的验证码解决方案

2.图片识别引擎

OCR(Optical Character Recognition)是指使用扫描仪或数码相机对文本资料进行扫描成图像文件,然后对图像文件进行分析处理,自动识别获取文字信息及版面信息的软件。

2.1 什么是tesseract
  • Tesseract,一款由HP实验室开发由Google维护的开源OCR引擎,特点是开源,免费,支持多语言,多平台。
  • 项目地址:[
2.2 图片识别引擎环境的安装

1 引擎的安装

  • mac环境下直接执行命令
brew install --with-training-tools tesseract

  • 1
  • windows环境下的安装 可以通过exe安装包安装,下载地址可以从GitHub项目中的wiki找到。安装完成后记得将Tesseract 执行文件的目录加入到PATH中,方便后续调用。

  • linux环境下的安装

sudo apt-get install tesseract-ocr

  • 1

2 Python库的安装

# PIL用于打开图片文件


pip/pip3 install pillow



# pytesseract模块用于从图片中解析数据


pip/pip3 install pytesseract

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
2.3 图片识别引擎的使用
  • 通过pytesseract模块的 image_to_string 方法就能将打开的图片文件中的数据提取成字符串数据,具体方法如下
from PIL import Image
import pytesseract

im = Image.open()

result = pytesseract.image_to_string(im)

print(result)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
2.4 图片识别引擎的使用扩展
  • [tesseract简单使用与训练](
  • 其他ocr平台
微软Azure 图像识别:
  有道智云文字识别:
  阿里云图文识别:
  腾讯OCR文字识别:

  • 1
  • 2
  • 3
  • 4

3 打码平台

1.为什么需要了解打码平台的使用

现在很多网站都会使用验证码来进行反爬,所以为了能够更好的获取数据,需要了解如何使用打码平台爬虫中的验证码

2 常见的打码平台
  1. 云打码:[

能够解决通用的验证码识别

  1. 极验验证码智能识别辅助:[

能够解决复杂验证码的识别

3 云打码的使用

下面以云打码为例,了解打码平台如何使用

3.1 云打码官方接口

下面代码是云打码平台提供,做了个简单修改,实现了两个方法:

  1. indetify:传入图片的响应二进制数即可
  2. indetify_by_filepath:传入图片的路径即可识别

其中需要自己配置的地方是:

username = 'whoarewe' # 用户名

password = '***' # 密码

appid = 4283 # appid

appkey = '02074c64f0d0bb9efb2df455537b01c3' # appkey

codetype = 1004 # 验证码类型

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

云打码官方提供的api如下:

#yundama.py


import requests
import json
import time

class YDMHttp:
    apiurl = '
    username = ''
    password = ''
    appid = ''
    appkey = ''

    def __init__(self, username, password, appid, appkey):
        self.username = username
        self.password = password
        self.appid = str(appid)
        self.appkey = appkey

    def request(self, fields, files=[]):
        response = self.post_url(self.apiurl, fields, files)
        response = json.loads(response)
        return response

    def balance(self):
        data = {'method': 'balance', 'username': self.username, 'password': self.password, 'appid': self.appid,
                'appkey': self.appkey}
        response = self.request(data)
        if (response):
            if (response['ret'] and response['ret'] < 0):
                return response['ret']
            else:
                return response['balance']
        else:
            return -9001

    def login(self):
        data = {'method': 'login', 'username': self.username, 'password': self.password, 'appid': self.appid,
                'appkey': self.appkey}
        response = self.request(data)
        if (response):
            if (response['ret'] and response['ret'] < 0):
                return response['ret']
            else:
                return response['uid']
        else:
            return -9001

    def upload(self, filename, codetype, timeout):
        data = {'method': 'upload', 'username': self.username, 'password': self.password, 'appid': self.appid,
                'appkey': self.appkey, 'codetype': str(codetype), 'timeout': str(timeout)}
        file = {'file': filename}
        response = self.request(data, file)
        if (response):
            if (response['ret'] and response['ret'] < 0):
                return response['ret']
            else:
                return response['cid']
        else:
            return -9001

    def result(self, cid):
        data = {'method': 'result', 'username': self.username, 'password': self.password, 'appid': self.appid,
                'appkey': self.appkey, 'cid': str(cid)}
        response = self.request(data)
        return response and response['text'] or ''

    def decode(self, filename, codetype, timeout):
        cid = self.upload(filename, codetype, timeout)
        if (cid > 0):
            for i in range(0, timeout):
                result = self.result(cid)
                if (result != ''):
                    return cid, result
                else:
                    time.sleep(1)
            return -3003, ''
        else:
            return cid, ''

    def post_url(self, url, fields, files=[]):
        # for key in files:
        #     files[key] = open(files[key], 'rb');
        res = requests.post(url, files=files, data=fields)
        return res.text 

username = 'whoarewe' # 用户名

password = '***' # 密码

appid = 4283 # appid

appkey = '02074c64f0d0bb9efb2df455537b01c3' # appkey

filename = 'getimage.jpg' # 文件位置

codetype = 1004 # 验证码类型



# 超时


timeout = 60

def indetify(response_content):
    if (username == 'username'):
        print('请设置好相关参数再测试')
    else:
        # 初始化
        yundama = YDMHttp(username, password, appid, appkey)

        # 登陆云打码
        uid = yundama.login();
        print('uid: %s' % uid)

        # 查询余额
        balance = yundama.balance();
        print('balance: %s' % balance)

        # 开始识别,图片路径,验证码类型ID,超时时间(秒),识别结果
        cid, result = yundama.decode(response_content, codetype, timeout)
        print('cid: %s, result: %s' % (cid, result))
        return result

def indetify_by_filepath(file_path):
    if (username == 'username'):
        print('请设置好相关参数再测试')
    else:
        # 初始化
        yundama = YDMHttp(username, password, appid, appkey)

        # 登陆云打码
        uid = yundama.login();
        print('uid: %s' % uid)

        # 查询余额
        balance = yundama.balance();
        print('balance: %s' % balance)

        # 开始识别,图片路径,验证码类型ID,超时时间(秒),识别结果
        cid, result = yundama.decode(file_path, codetype, timeout)
        print('cid: %s, result: %s' % (cid, result))
        return result

if __name__ == '__main__':
    pass

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148

4 常见的验证码的种类

4.1 url地址不变,验证码不变

这是验证码里面非常简单的一种类型,对应的只需要获取验证码的地址,然后请求,通过打码平台识别即可

4.2 url地址不变,验证码变化

这种验证码的类型是更加常见的一种类型,对于这种验证码,大家需要思考:

在登录的过程中,假设我输入的验证码是对的,对方服务器是如何判断当前我输入的验证码是显示在我屏幕上的验证码,而不是其他的验证码呢?

在获取网页的时候,请求验证码,以及提交验证码的时候,对方服务器肯定通过了某种手段验证我之前获取的验证码和最后提交的验证码是同一个验证码,那这个手段是什么手段呢?

很明显,就是通过cookie来实现的,所以对应的,在请求页面,请求验证码,提交验证码的到时候需要保证cookie的一致性,对此可以使用requests.session来解决


小结

  1. 了解 验证码的相关知识
  2. 掌握 图片识别引擎的使用
  3. 了解 常见的打码平台
  4. 掌握 通过打码平台处理验证码的方法

chrome浏览器使用方法介绍

学习目标
  1. 了解 新建隐身窗口的目的
  2. 了解 chrome中network的使用
  3. 了解 寻找登录接口的方法

1 新建隐身窗口

浏览器中直接打开网站,会自动带上之前网站时保存的cookie,但是在爬虫中首次获取页面是没有携带cookie的,这种情况如何解决呢?

使用隐身窗口,首次打开网站,不会带上cookie,能够观察页面的获取情况,包括对方服务器如何设置cookie在本地

【爬虫开发】爬虫开发从0到1全知识教程第7篇:反爬与反反爬,验证码处理【附代码文档】

2 chrome中network的更多功能

【爬虫开发】爬虫开发从0到1全知识教程第7篇:反爬与反反爬,验证码处理【附代码文档】

2.1 Perserve log

默认情况下,页面发生跳转之后,之前的请求url地址等信息都会消失,勾选perserve log后之前的请求都会被保留 【爬虫开发】爬虫开发从0到1全知识教程第7篇:反爬与反反爬,验证码处理【附代码文档】

2.2 filter过滤

在url地址很多的时候,可以在filter中输入部分url地址,对所有的url地址起到一定的过滤效果,具体位置在上面第二幅图中的2的位置

2.3 观察特定种类的请求

在上面第二幅图中的3的位置,有很多选项,默认是选择的all,即会观察到所有种类的请求

很多时候处于自己的目的可以选择all右边的其他选项,比如常见的选项:

  • XHR:大部分情况表示ajax请求
  • JS:js请求
  • CSS:css请求

但是很多时候我们并不能保证我们需要的请求是什么类型,特别是我们不清楚一个请求是否为ajax请求的时候,直接选择all,从前往后观察即可,其中js,css,图片等不去观察即可

不要被浏览器中的一堆请求吓到了,这些请求中除了js,css,图片的请求外,其他的请求并没有多少个

3 寻找登录接口

回顾之前人人网的爬虫我们找到了一个登陆接口,那么这个接口从哪里找到的呢?

[

3.1 寻找action对的url地址

【爬虫开发】爬虫开发从0到1全知识教程第7篇:反爬与反反爬,验证码处理【附代码文档】

可以发现,这个地址就是在登录的form表单中action对应的url地址,回顾前端的知识点,可以发现就是进行表单提交的地址,对应的,提交的数据,仅仅需要:用户名的input标签中,name的值作为键,用户名作为值,密码的input标签中,name的值作为键,密码作为值即可

思考:

如果action对应的没有url地址的时候可以怎么做?

3.2 通过抓包寻找登录的url地址

【爬虫开发】爬虫开发从0到1全知识教程第7篇:反爬与反反爬,验证码处理【附代码文档】

通过抓包可以发现,在这个url地址和请求体中均有参数,比如uniqueTimestamprkey以及加密之后的password

这个时候我们可以观察手机版的登录接口,是否也是一样的

【爬虫开发】爬虫开发从0到1全知识教程第7篇:反爬与反反爬,验证码处理【附代码文档】

可以发现在手机版中,依然有参数,但是参数的个数少一些,这个时候,我们可以使用手机版作为参考,下一节来学习如何分析js


小结

  1. 使用隐身窗口的主要目的是为了避免首次打开网站携带cookie的问题
  2. chrome的network中,perserve log选项能够在页面发生跳转之后任然能够观察之前的请求
  3. 确定登录的地址有两种方法:

  4. 寻找from表单action的url地址

  5. 通过抓包获取
© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...