爬虫验证码问题

爬虫验证码问题

在采集数据过程中,经常会出现验证码的问题。我们可以使用打码平台进行机器识别。同时也可以手动完成。

现在有一个需求就是关于手动解决验证码的问题:当出现验证码时,出现一个提示窗口,要求手动输入验证码,再验证是否正确,如果为True,则继续采集。

第一种解决思路:

携带cookie 数值,弹出的窗口上会显示验证页面的链接,人眼识别之后,输入对话框,随机程序再携带验证结果post请求。

提醒样式在这里插入图片描述

代码:

#coding: utf-8
#弹窗程序
import webbrowser
from tkinter import *
class ManualGetCode(object):
    def __init__(self,url):
        self.url=url
        self.root=Tk()
        self.root.title('验证码')
        self.root.geometry('300x100')
        l1=Label(self.root,text="请点击下方网址,并在输入框中输入网址中的验证码")
        l1.pack()

        def run_url():
            webbrowser.open(self.url)
        Button(self.root,text=self.url,command=run_url).pack()
        self.xls_text = StringVar()
        xls = Entry(self.root, textvariable=self.xls_text)
        self.xls_text.set(" ")
        xls.pack()

    def on_click(self):
            x = self.xls_text.get()
            try:
                x=str(x).split()[0]
            except:
                x=''
            return x
    def get_code(self):
        Button(self.root, text="确定", command=self.on_click).pack()
        self.root.mainloop()
        return self.on_click()
if __name__ == '__main__':
    code=ManualGetCode('http://www.baidu.com').get_code()
    print(code)

#验证程序
def manual(self,verificate_ur,cookie):
   	with request.Session() as session:
            # 如果在win上运行
            if sys.platform.startswith('win'):
                code = ManualGetCode(verificate_url).get_code()
            #     如果运行环境是linux
            else:
                # linux
                print(verificate_url)
                code = input("请复制上面网址到浏览器,并输入网址中的验证码:")
                data={
                    'icode':code#人人网验证码 所需的字段
                }
                session.post(verificate_ur,data)
            return code

缺点:此种方式需要携带正确的cookie数值,以此来进行判断请求者身份,这样与爬虫程序的耦合性很强,同时别断也很明显:如果使用的不是同一个浏览器就行浏览,则获得的cookie数值就不相同,那么及时验证码输入正确,也不会验证成功。局限性很大。

第二种思路:

定义好接受的类型(如在程序定义接受图片或者图片的二进制流),爬虫程序将采集获得的图片或者图片的二进制传递过来,人眼解析的只是指定的图片,然后识别之后把结果返回给爬虫,这样,耦合性小,局限性小。

提醒样式:

!在这里插入图片描述

代码示例:

#coding=utf-8
#弹窗代码
import requests
from lxml import etree
from PIL import ImageTk
from tkinter import *

import tkinter as tk
import os

import PIL
class GetCode(object):

    def __init__(self):

        self.data={}
        self.root = tk.Tk()
        self.root.title('验证码')
        self.root.geometry('400x150')
        self.root.resizable(width=False,height=False)   # 固定长宽不可拉伸

        self.textLabel=tk.Label(self.root,text="请输入验证码:").pack() # 标签
        self.textStr=StringVar()
        self.textEntry=tk.Entry(self.root,textvariable=self.textStr)
        self.textStr.set("")
        self.textEntry.pack()  # 输入框
    def get_code(self,imgs):
        im = PIL.Image.open(imgs)
        img=ImageTk.PhotoImage(im)
        tk.Label(self.root,image=img).pack() # 显示图片
        self.but = tk.Button(self.root, text="确认", command=self.return_code).pack(fill="both")  # 按键

        self.root.mainloop()
        return self.data

    def return_code(self):
        # 返回输入框内容

        x=self.textStr.get()
        self.root.destroy()      # 关闭窗体
        try:
            os.remove("test.jpg")#删除图片
        except:
            pass
        try:
            x = str(x).split()[0]
        except:
            x = ''
        self.data['code']=x


#验证程序
def manual(self,verificate_ur):
   
            # 如果在win上运行
            if sys.platform.startswith('win'):
                code = ManualGetCode(verificate_url).get_code()
            #     如果运行环境是linux
            else:
                # linux
                print(verificate_url)
                code = input("请复制上面网址到浏览器,并输入网址中的验证码:")
            return code

可以看出这样验证码的一个模块,所需的参数比之前简化了很多,同时也符合了面向对象的思想。

小知识点:在第二种思路中需要接受的image或者image的二进制流,如果单纯的传递图片的很好解决,但是验证码我们不需要进行本地保存(少进行io操作增加性能嘛==)所以我们最好采用二进制流的形式进行读取并在窗口中显示,其中遇到了一个问题,就是如何把验证码的二进制流转换成image对象(否则pillow打不开二进制流),

# 此处是图片的二进制流
img_str=session.get(code_url).content
# 需要将二进制转换成image对象
img=BytesIO(img_str)

BytesIO模块,直接将二进制转换成image,这样pillow就能识别。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值