返回介绍

5.3 验证码的处理

发布于 2025-04-21 19:15:27 字数 3988 浏览 0 评论 0 收藏

5.3.1 带验证码的网站登录分析

这一节简单分析一下带验证码登录的情况。

假设不小心登录豆瓣的时候连续输错密码,再重新登录豆瓣网站,就会发现需要填写验证码才可以登录,如图 5-6 所示。

图 5-6 需填写验证码的豆瓣登录页面

为了搞清楚带验证码登录都向服务器发送了什么数据,可以先登录一次,使用 Chrome 浏览器的检查功能分析一下,填写验证码登录时,系统都向服务器 POST 了哪些数据。

按照上节的步骤,在 Chrome 浏览器中打开“检查”功能,填写用户名、密码和验证码并单击“登录豆瓣”,然后在浏览器中查看这次登录的 Form Data,会发现系统向服务器提交的数据多了两项内容,如图 5-7 所示。

图 5-7 系统向服务器提交的数据

一项是 captcha-solution: music。显然这个 captcha 就是验证码的意思,captchasolution 的值就是用户输入的验证码。

另一项是 captcha-id: sF1wibCmaB1dHiJ5u4dNY6TS:en。这一项看上去很复杂,也不了解它的含义,那这一项是否是变化的呢?若退出并重新登录一次,会发现这一项是变化的,也就是说这一项是需要提供给网站服务器的变量。假设在打开网站登录页面准备登录的时候,这一项应该是网站提供给用户,然后用户在登录的时候将此项内容提交给网站。为了验证这一想法,现在退出登录,直接来到豆瓣登录页面,如图 5-8 所示。

图 5-8 豆瓣登录页面

在这个页面单击右键,在弹出的菜单中选择“查看网页源码”,在打开的网页源码页面中按 Ctrl+F 组合键,系统弹出搜索框,搜索 captcha-id,结果如图 5-9 所示。

图 5-9 豆瓣登录页面源码搜索结果

从搜索结果可见,验证码代码段的下面有 hidden 项,它的 value 正是需要向网站提交的 captcha-id 的值。如果要使用验证码登录豆瓣网站,需要另外提供 captchasolution 和 captcha-id 两个字段的值,而这两个字段的值是在打开的登录页面中提供给用户的。这就说明用户不能像上一节那样直接登录了,必须首先打开一次登录页面,获取 captcha-solution 和 captcha-id 这两个字段的值,然后再构造表单登录。

5.3.2 验证码的识别和处理

在编写代码之前,先简单分析一下验证码的识别和处理。

验证码用于测试用户是真实的人类还是计算机机器人,它实质上可以说是一种反爬虫的手段。一般来说,用户遇到验证码,有 3 种常见的处理选择。

(1)下载并显示验证码图片,然后由人工识别。这种方式的优势是正确率高、成本低,但缺点也很明显;这种方式无法规模化和自动化,因为人们不能总在计算机前等着输入验证码。当然,可以设置一个邮件提醒,在遇到验证码时将验证码图片实时发送到手机上,然后人工识别出验证码并回传给爬虫服务器。总的来说,人工识别验证码的方式适合个人小型的爬取任务,对于大型的爬取任务,必须考虑自动化的方法。

(2)使用算法识别图像。用户可以充分利用现在的机器学习和深度学习算法,实现对验证码的自动识别。这样虽然可以自动化完成识别,但是开发成本比较高,而且识别准确率也不会太高。

(3)使用专业打码平台提供的服务。当遇到大型识别验证码的任务时,可以将识别任务交给专业的打码平台,由这个平台使用人工智能或人工处理。这种方式适合大规模的自动化爬虫任务,但会增加一定的成本。

总体来说,如果是小型的任务,建议使用第一种方法;如果是大型爬虫,建议直接使用打码平台的服务,但对于近几年出现的中文顺序单击验证码和极验验证等验证方式,打码平台也不能很好地解决。验证码的处理对于爬虫工程师来说,是个比较难以逾越的障碍。

本节登录豆瓣网站是一个相对简单的任务,为了简单演示,在这里使用第一种方式,由自己人工来识别验证码。

5.3.3 编写带验证码的豆瓣网站登录代码

先梳理一下登录流程。在有验证码的情况下,使用 Requests 登录网站,需要先爬取一次登录页面。

第一步,爬取登录页面,获得 captcha-solution 和 captcha-id 这两项的值。

第二步,构造 POST 表单数据。

第三步,登录并爬取首页。

下面按照这个流程来编写全部登录代码。

首先需要获取登录页面。

import requests
from lxml import etree 
 
 
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) \ 
         AppleWebKit/537.36 (KHTML, like Gecko) \ 
         Chrome/46.0.2490.80 Safari/537.36'} 
url = 'https://www.douban.com/accounts/login' 
response = requests.get(url, headers=headers)   #获取背景页面 
html = etree.HTML(response.text) 

然后解析出 captcha-solution 和 captcha-id 这两项的值。这里要先判断是否出现了验证码,如果出现,就下载并使用 Python 的图片处理函数 PIL,打开验证码图片。

captcha = html.xpath('//*[@id="captcha_image"]/@src')
if captcha:                    #判断是否有验证码 
    captcha_url = captcha[0]     #获取验证码图片 URL 
    captcha_image = requests.get(captcha_url)   #下载验证码图片 
    from PIL import Image 
    from io import BytesIO 
    img = Image.open(BytesIO(captcha_image.content))  #打开验证码图片 
    img.show()     #显示验证码图片 
    captcha_text = input(u'请输如验证码:')  #输入识别出的验证码 
    #下面解析出 captcha_id 的值 
    captcha_id = captcha_url.split('=')[1].split('&')[0] 
else: 
    captcha_id = None       #若没有验证码,设置为 None 
    captcha_text = None

上面代码中使用 Image 函数打开图片,自己人工查看并填写识别出的验证码,最后赋值给 captcha_text。

第四步,构造 POST 表单。

formdata = {'source':'index_nav',
            'form_email':'your_email@xxx.com',  
            'form_password':'your_password',  
            'captcha-solution':captcha_text,  
            'captcha-id':captcha_id} 
s = requests.session()    #初始化会话 
r = s.post(url, data=formdata, headers=headers) 

为了验证是否已经成功登录,还是要查看一下返回的内容中是否包含个人昵称。

print('日月光华' in r.text)
True 

运行显示的结果为 True,说明已经完成了带验证码的登录,可以继续爬取豆瓣其他的页面了。

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。