zoukankan      html  css  js  c++  java
  • python爬虫模拟登录验证码解决方案

    【前言】几天研究验证码解决方案有三种吧。第一、手工输入,即保存图片后然后我们手工输入;第二、使用cookie,必须输入密码一次,获取cookie;第三、图像处理+深度学习方案,研究生也做相关课题,就用了这种。

    一、处理思路

      1、图像处理,针对我要识别的期货中心的验证码,有我针对性的处理。目标是得到去噪后的二值图片,然后使用深度学习神经网络方法进行识别。

      2、第一次尝试了用谷歌的开源tesseract-ocr方法,做了一个模型训练。因为都是集成好的开发环境,自动分割,自己只需手动的调整一些识别错误的。准确率还是可以的。

      3、使用了腾讯的免费ocr接口,是被效果大大提升。最后用一个正则表达式加一个提取器,只提取字母和数字。识别率百分之90是有的。

      直接上代码。亲测可用自动登录中国期货市场监控中心的网站https://investorservice.cfmmc.com/

      1 # /usr/bin/python
      2 # encoding: utf-8
      3 
      4 import time
      5 from selenium import webdriver
      6 import sys
      7 import urllib2
      8 import urllib
      9 import time
     10 import re
     11 
     12 from PIL import Image
     13 from pytesseract import *
     14 import PIL.ImageOps
     15 
     16 import requests
     17 import hmac
     18 import hashlib
     19 import base64
     20 import time
     21 import random
     22     
     23     #方案一:在线二维码识别(也是先下载到本地,但是由于动态二维码原因,两次获取的页面不一样,导致验证码不匹配。匹配不成功)
     24     #下面有针对此方案的解决方法,就是解析同一个界面下的验证码,先下载到本地,然后上传处理。这种适合服务器不能图片截屏获取二维码,可以使用session或者cookie方式。
     25 def yanzheng_online():
     26     # 爬取图片
     27     reload(sys)
     28     sys.setdefaultencoding('utf8')
     29 
     30     headers = ("User-Agent",
     31                "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36")
     32     opener = urllib2.build_opener()
     33     opener.addheaders = [headers]
     34     urllib2.install_opener(opener)
     35      
     36      #循环爬取多张,建立数据集
     37     # for i in range(1, 1500):
     38     #     url = "https://investorservice.cfmmc.com/veriCode.do?t=1531728079700" + str(i)
     39     #     data = urllib2.urlopen(url).read()
     40     #     # data=urllib2.quote(data).decode('utf-8')
     41     #     file = "G:/360Downloads/pic/" + str(i) + ".png"
     42     #     playFile = open(file, 'wb')
     43     #     playFile.write(data)
     44     #     playFile.close()
     45     #     time.sleep(1)
     46     url = "https://investorservice.cfmmc.com/veriCode.do?t=1531728079700"
     47     data = urllib2.urlopen(url).read()
     48     file = "G:/360Downloads/pic/" + "yanzhengma" + ".png"
     49     playFile = open(file, 'wb')
     50     playFile.write(data)
     51     playFile.close()
     52     time.sleep(1)
     53 
     54     # 图像处理
     55     im = Image.open('G:/360Downloads/pic/yanzhengma.png')
     56 
     57     im = im.convert('L')
     58     #im.show()
     59     im2 = im.point(lambda x: 0 if x > 200 else 255)
     60     #im2.show()
     61     im3 = im2.save("G:/360Downloads/pic/yanzhengma.png")
     62 
     63     # 借助腾讯免费的OCR识别
     64     appid = "1257XX2374"  # 写入自己的腾讯云号码,我修改了
     65     # bucket = "你的bucket"  # 不要也可以
     66     secret_id = "AKIDGKXXXXXXXXX1XnnWyA5sFgz"  # 写入自己的账号里面的地址
     67     secret_key = "EDwRggaXXXXXXXXXXysY0CA"  # 同上
     68     expired = time.time() + 2592000
     69     onceExpired = 0
     70     current = time.time()
     71     rdm = ''.join(random.choice("0123456789") for i in range(10))
     72     userid = "0"
     73     fileid = "tencentyunSignTest"
     74 
     75     info = "a=" + appid + "&k=" + secret_id + "&e=" + str(expired) + "&t=" + str(current) + "&r=" + str(
     76         rdm) + "&u=0&f="  # 去掉bucket
     77 
     78     signindex = hmac.new(secret_key, info, hashlib.sha1).digest()  # HMAC-SHA1加密
     79     sign = base64.b64encode(signindex + info)  # base64转码
     80 
     81     url = "http://recognition.image.myqcloud.com/ocr/general"
     82     headers = {'Host': 'recognition.image.myqcloud.com',
     83                "Authorization": sign,
     84                }
     85     files = {'appid': (None, appid),
     86              #  'bucket': (None, bucket),
     87              'image': ('yanzhengma.png', open('G:/360Downloads/pic/yanzhengma.png', 'rb'), 'image/jpeg')
     88 
     89              }
     90 
     91     r = requests.post(url, files=files, headers=headers)
     92     responseinfo = r.content
     93     #print responseinfo
     94     # 创建内存中的word文档对象
     95     # file=docx.Document()
     96     r_index = r'itemstring":"(.*?)"'  # 做一个正则匹配,会匹配出一些特殊符号
     97     result = re.findall(r_index, responseinfo)
     98     #print result
     99     # result2=re.findall(r'w+',result)
    100     # new_crazy = filter(str.isalnum, result)
    101     # print new_crazy
    102     a = 0
    103     for i in result:
    104         # file.add_paragraph(i)
    105         # 只识别出数字和字母
    106         new_crazy = filter(str.isalnum, i)
    107         #print new_crazy
    108         a = new_crazy
    109     # file.save("D:\writeResult.docx")
    110     return a
    111     
    112     #方案二:网页裁剪验证码,本地识别识别。匹配成功!!
    113 def yanzheng_local():
    114     #对截取的图片处理
    115     im = Image.open('G:/360Downloads/pic/yanzhengma.png')
    116     box = (526, 247, 623, 273)  # 设置要裁剪的区域96*25,根据自己验证码位置
    117     region = im.crop(box)  # 此时,region是一个新的图像对象。
    118     # region.show()#显示的话就会被占用,所以要注释掉
    119     region.save("G:/360Downloads/pic/yanzhengma.png")
    120     # 爬取图片
    121     reload(sys)
    122     sys.setdefaultencoding('utf8')
    123 
    124     headers = ("User-Agent",
    125                "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36")
    126     opener = urllib2.build_opener()
    127     opener.addheaders = [headers]
    128     urllib2.install_opener(opener)
    129 
    130     # 图像处理
    131     im = Image.open('G:/360Downloads/pic/yanzhengma.png')
    132 
    133     im = im.convert('L')
    134     #im.show()
    135     im2 = im.point(lambda x: 0 if x > 200 else 255)
    136     #im2.show()
    137     im3 = im2.save("G:/360Downloads/pic/yanzhengma.png")
    138 
    139     # 腾讯ocr识别
    140     appid = "1257XXX374"  # 写入自己的腾讯云号码
    141     # bucket = "你的bucket"  # 不要也可以
    142     secret_id = "AKIDGKXXXXXXXXnnWyA5sFgz"  # 写入自己的账号里面的地址
    143     secret_key = "EDwRggaXXXXXXXXtVrysY0CA"  # 同上
    144     expired = time.time() + 2592000
    145     onceExpired = 0
    146     current = time.time()
    147     rdm = ''.join(random.choice("0123456789") for i in range(10))
    148     userid = "0"
    149     fileid = "tencentyunSignTest"
    150 
    151     info = "a=" + appid + "&k=" + secret_id + "&e=" + str(expired) + "&t=" + str(current) + "&r=" + str(
    152         rdm) + "&u=0&f="  # 去掉bucket
    153 
    154     signindex = hmac.new(secret_key, info, hashlib.sha1).digest()  # HMAC-SHA1加密
    155     sign = base64.b64encode(signindex + info)  # base64转码
    156 
    157     url = "http://recognition.image.myqcloud.com/ocr/general"
    158     headers = {'Host': 'recognition.image.myqcloud.com',
    159                "Authorization": sign,
    160                }
    161     files = {'appid': (None, appid),
    162              #  'bucket': (None, bucket),
    163              'image': ('yanzhengma.png', open('G:/360Downloads/pic/yanzhengma.png', 'rb'), 'image/jpeg')
    164 
    165              }
    166 
    167     r = requests.post(url, files=files, headers=headers)
    168     responseinfo = r.content
    169     #print responseinfo
    170     # 创建内存中的word文档对象
    171     # file=docx.Document()
    172     r_index = r'itemstring":"(.*?)"'  # 做一个正则匹配
    173     result = re.findall(r_index, responseinfo)
    174     #print result
    175     # result2=re.findall(r'w+',result)
    176     # new_crazy = filter(str.isalnum, result)
    177     # print new_crazy
    178     a = 0
    179     for i in result:
    180         # file.add_paragraph(i)
    181         # 只识别出数字和字母
    182         new_crazy = filter(str.isalnum, i)
    183        
    184         #print new_crazy
    185         a = new_crazy
    186     # print 'a'
    187     # file.save("D:\writeResult.docx")
    188     return a
    189 
    190 def login(username, password):
    191    
    192     url = 'https://investorservice.cfmmc.com '
    193     
    194     driver = webdriver.Chrome(executable_path='C:Program Files (x86)GoogleChromeApplicationchromedriver.exe')
    195     driver.get(url)
    196     # print driver.title
    197     name_input = driver.find_element_by_name('userID')  # 找到用户名的框框
    198     pass_input = driver.find_element_by_name('password')  # 找到输入密码的框框
    199     yanzheng_input=driver.find_element_by_name('vericode') #验证码输入框
    200     login_button = driver.find_element_by_name('imageField2')  # 找到登录按钮
    201 
    202     name_input.clear()
    203     name_input.send_keys(username)  # 填写用户名
    204     time.sleep(0.2)
    205     pass_input.clear()
    206     pass_input.send_keys(password)  # 填写密码
    207     #验证码获取
    208     #local方法专用,截取验证码所在的网页
    209     driver.get_screenshot_as_file('G:/360Downloads/pic/yanzhengma.png')  # 截图网页保存
    210     
    211 
    212     #yzm=yanzheng_online()
    213     #使用本地裁剪识别,即方案二
    214     yzm=yanzheng_local()
    215     print yzm
    216     yanzheng_input.send_keys(yzm)
    217     time.sleep(1.2)
    218     login_button.click()            # 点击登录
    219 
    220     time.sleep(1.2)
    221     #print driver.get_cookies()
    222 
    223     #打印“登录成功”表示成功,否则重新运行
    224         if('login'in driver.current_url):   
    225             print "登录成功"
    226     driver.close()
    227 
    228 if __name__ == "__main__":
    229      #账号密码
    230     user = "xxxxxxx"
    231     pw = "xxxxxxxx"
    232     login(user, pw)

    #后面会继续实现cookie保存,爬取信息,存储数据库。
    二、最好的解决方法 
      这几天深入了解了python爬虫,因为要在登录之后,请求新的网页时要保持登录,不然在请求新的网页时又会跳转到登录页面。如何保持登录呢?两种方式,本地携带cookie访问,服务器端保持session.如此,不如在登录的时候采用登录保持的方式,保持session.(当然携带cookie也可以)。这几天学习了抓包分析表单,实现了请求cookie,提交token.还有一个验证码,就采用网页抓取,正则解析出验证码地址,下载本地上传深度学习模型,识别出验证码传入post表单。
    源码地址:https://www.cnblogs.com/huangfuyuan/p/9356747.html
      本方法适用于windows带图形界面的,不适用于服务器。
    三、验证码生成原理及python代码
     1 def verifycode(request): 
     2     # 引入绘图模块 
     3     from PIL import Image, ImageDraw, ImageFont 
     4     # 引入随机函数模块 
     5     import random 
     6     # 定义变量,用于画面的背景色、宽、高 
     7     bgcolor = (random.randrange(20, 100), random.randrange(20, 100), random.randrange(20, 100)) width = 100 height = 50 
     8     # 创建画面对象 
     9     im = Image.new('RGB',(width, height),bgcolor) 
    10     # 创建画笔对象 
    11     draw = ImageDraw.Draw(im) 
    12     # 调用画笔的point()函数绘制噪点 
    13     for i in range(0, 100): 
    14         xy = (random.randrange(0, width), random,randrange(0, height)) 
    15         fill = (random.randrange(0, 255), 255, random.randrange(0, 255)) 
    16         draw.point(xy, fill=fill) 
    17     # 定义验证码的备选值 
    18     str = '1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM' 
    19     # 随机选取四个值作为验证码 
    20     rand_str = '' 
    21     for i in range(0,4): 
    22         rand_str += str[random.randrange(0, len(str))] 
    23     # 构建字体对象 ,读取本地字体模板
    24     font = ImageFont.truetype(r'CWindowsFontsAdobeArabic-Bold.otf', 40) 
    25     # 构建字体颜色 
    26     fontcolor1 =(255, random.randrange(0, 255), random.randrange(0, 255))    
    27     fontcolor2 =(255, random.randrange(0, 255), random.randrange(0, 255)) 
    28     fontcolor3 =(255, random.randrange(0, 255), random.randrange(0, 255)) 
    29     fontcolor4 =(255, random.randrange(0, 255), random.randrange(0, 255)) 
    30     # 绘制四个字 
    31     draw.text((5, 2), rand_str[0], font=font, fill=fontcolor1) 
    32     draw.text((25, 2), rand_str[1], font=font, fill=fontcolor2) 
    33     draw.text((50, 2), rand_str[2], font=font, fill=fontcolor3) 
    34     draw.text((75, 2), rand_str[3], font=font, fill=fontcolor4) 
    35     # 释放画笔 
    36     del draw 
    37     # 存入session , 用于做进一步验证 
    38     request.session['verifycode'] = rand_str 
    39     # 内存文件操作 
    40     import io buf = io.BytesIO() 
    41     # 将图片保存在内存中,文件类型为png 
    42     im.safe(buf, 'png') 
    43     # 将内存中的图片数据返回给客户端,MIME类型为图片png 
    44     return HttpResponse(buf.getValue(), 'image/png')
  • 相关阅读:
    struct/enum/union加typedef与不加typedef
    拷贝构造函数、拷贝运算符、析构函数
    TextQuery程序
    动态内存-动态数组
    动态内存
    动态内存
    matlab文件处理
    [leetcode]_Best Time to Buy and Sell Stock I && II
    [leetcode]_Valid Palindrome
    [leetcode]_Pascal's Triangle II
  • 原文地址:https://www.cnblogs.com/huangfuyuan/p/9317675.html
Copyright © 2011-2022 走看看