selenium +pytesseract 验证码识别+web自动化

  • 作者:ykk
  • 分类: python
  • 发表时间:2020-05-28 09:17:27
  • 阅读量:(437)

需求分析:

日常处理工作中,OA里面待办事项经常要进行重复性点击,而且需要收集信息进行登记管理,初步想法,使用selenium编写好规则脚本实现 web自动化,将获取到的有效信息直接插入后台Oracle数据库中,方便查询管理。

下面开始实现。

下载好对应的浏览器驱动chromewebdriver。


import time
import pytesseract
from PIL import Image, ImageEnhance, ImageDraw
from selenium import webdriver
from selenium.webdriver.common.by import By

import oracle_insert

# 将验证码转为灰度图时用到的"lookup table"
THRESHOLD = 165
LUT = [0] * THRESHOLD + [1] * (256 - THRESHOLD)

# 降噪数组
t2val = {}


def twoValue(image, G):
    for y in range(0, image.size[1]):
        for x in range(0, image.size[0]):
            g = image.getpixel((x, y))
            if g > G:
                t2val[(x, y)] = 1
            else:
                t2val[(x, y)] = 0


"""
# 根据一个点A的RGB值,与周围的8个点的RBG值比较,设定一个值N(0 <N <8),当A的RGB值与周围8个点的RGB相等数小于N时,此点为噪点
# G: Integer 图像二值化阀值
# N: Integer 降噪率 0 <N <8
# Z: Integer 降噪次数
# 输出
#  0:降噪成功
#  1:降噪失败
"""


def clearNoise(image, N, Z):
    for i in range(0, Z):
        t2val[(0, 0)] = 1
        t2val[(image.size[0] - 1, image.size[1] - 1)] = 1

        for x in range(1, image.size[0] - 1):
            for y in range(1, image.size[1] - 1):
                nearDots = 0
                L = t2val[(x, y)]
                if L == t2val[(x - 1, y - 1)]:
                    nearDots += 1
                if L == t2val[(x - 1, y)]:
                    nearDots += 1
                if L == t2val[(x - 1, y + 1)]:
                    nearDots += 1
                if L == t2val[(x, y - 1)]:
                    nearDots += 1
                if L == t2val[(x, y + 1)]:
                    nearDots += 1
                if L == t2val[(x + 1, y - 1)]:
                    nearDots += 1
                if L == t2val[(x + 1, y)]:
                    nearDots += 1
                if L == t2val[(x + 1, y + 1)]:
                    nearDots += 1

                if nearDots < N:
                    t2val[(x, y)] = 1


def saveImage(filename, size):
    image = Image.new("1", size)
    draw = ImageDraw.Draw(image)

    for x in range(0, size[0]):
        for y in range(0, size[1]):
            draw.point((x, y), t2val[(x, y)])

    image.save(filename)


def NoiseCoring(path):
    image = Image.open(path).convert("L")
    twoValue(image, 100)
    clearNoise(image, 3, 2)
    saveImage('maxxcaptcha.png', image.size)


def login_oa(name, password):

   
    url = "http://test.com"
    # 1、打开浏览器,最大化浏览器  #driver.minimize_window()  #driver.maximize_window()
    driver = webdriver.Chrome()
    driver.get(url)
    driver.implicitly_wait(10)
    # 用户名元素
    userElement = driver.find_element(By.XPATH, '//*[@id="login_username"]')
    # 密码元素
    passElement = driver.find_element(By.XPATH, '//*[@id="login_password"]')
    # 验证码输入框元素
    codeElement = driver.find_element(By.XPATH, '//*[@id="VerifyCode"]')
    # 验证图片元素
    imgElement = driver.find_element(By.XPATH, '//*[@id="VerifyCodeImg"]')

    # 2、截取屏幕内容,保存到本地
    driver.save_screenshot("big.png")

    # 3、打开截图,获取验证码位置,截取保存验证码
    ran = Image.open("big.png")
    # 通过location定位x,y
    left = imgElement.location['x']
    top = imgElement.location['y']
    # 通过x,y的值拼接长和宽
    right = left + imgElement.size['width']
    bottom = top + imgElement.size['height']
    # 定位验证码坐标位置
    box = (left, top, right, bottom)
    print('网页尺寸' + str(ran.size))
    print('验证码尺寸' + str(box))
    imageCode = ran.crop(box)  # 截图定位到验证码方块
    sharp_img = ImageEnhance.Contrast(imageCode).enhance(2.0)  # 对比度增强
    sharp_img.save("maxcaptcha.png")
    sharp_img.load()
    time.sleep(2)
    NoiseCoring('maxcaptcha.png')  # 降噪色彩转灰度
    im = Image.open('maxxcaptcha.png')
    keys = pytesseract.image_to_string(im).replace(" ", "")  # 图片识别转字符串
    key = ''.join(c for c in keys if c.isdigit())
    print('验证码转字符串:' + keys)  # 验证码都为4位数字,只保留识别出来验证码中数字部分
    print('验证码转字符串只保留数字:' + key)
    userElement.send_keys(name)
    passElement.send_keys(password)
    codeElement.send_keys(key)
    click_login = driver.find_element(By.XPATH, '//*[@id="login_button"]')
    click_login.click()
    time.sleep(3)
    currentPageUrl = driver.current_url
    print("当前页面的url是:", currentPageUrl)
    if currentPageUrl == "http://test.com/loginend":

        time.sleep(2)
        print('验证成功')
        find_ddi(driver)
    else:
        driver.close()
        print('验证失败')
        return 1


def get_ddi(driveri):
    print('-------------------------------------分割线------------------------------------------------')
    createdate = driveri.find_element_by_xpath(
        '// *[ @ id = "colSummaryData"] / table[1] / tbody / tr[2] / td / span / span').text  # 发起时间
    driveri.switch_to.frame('zwIframe')
    deptid = driveri.find_element_by_xpath(
        '// *[ @ id = "field0001"]').text.replace(" ", "").replace("\n", "")  # 部门
    buyerid = driveri.find_element_by_xpath(
        '// *[ @ id = "field0002"]').text.replace(" ", "").replace("\n", "")  # 采购员
    show = driveri.find_element_by_xpath(
        '// *[ @ id = "field0003"]').text.replace(" ", "").replace("\n", "")  # 说明
    approve = driveri.find_element_by_xpath(
        '//*[@id="field0004"]').text.replace("\n", "")  # 审批信息
    cstname = driveri.find_element_by_xpath(
        '//*[@id="field0005"]').text.replace(" ", "").replace("\n", "")  # 供应商
    print('部门:%s' % deptid)
    print('采购员:%s' % buyerid)
    print('供应商:%s' % cstname)
    print('说明:%s' % show)
    print('审批信息:%s' % approve)
    print('发起时间:%s' % createdate)
    sql = ''' insert  into
           pub_ddi_ratify
           (deptid, buyerid, cstname, show, approve, createdate,processtime)
       values
       ( '%s', '%s', '%s', '%s', '%s', to_date('%s','yyyy-mm-dd hh24:mi:ss'),sysdate)''' % (
        deptid, buyerid, cstname, show, approve, createdate)
    oracle_insert.insertinto(sql)
    print('DDI数据拉取完毕')
    driveri.switch_to.default_content()
    print('输入处理意见:     已收到,麻烦通知第三方技术人员联系我进行对接!')
    opinion = driveri.find_element_by_xpath('//*[@id="content_deal_comment"]')
    opinion.send_keys('已收到,麻烦通知第三方技术人员联系我进行对接!')
    driveri.find_element_by_xpath('//*[@id="_dealSubmit"]').click()  # 点击提交按钮
    time.sleep(3)
    print('关闭子窗口,点击下一个DDI事项')


def find_ddi(driveri):
    time.sleep(2)
    print('开始点击待办事项')
    click1_login = driveri.find_element(
        By.XPATH, '//*[@id="sectionHeaderMore-8673963913602642900"]/i')
    click1_login.click()
    time.sleep(2)
    driveri.switch_to.frame('mainIframe')
    driveri.switch_to.frame('pendingMainIframe')
    print('开始输入关键字DDI搜索')
    click2_login = driveri.find_element(By.XPATH, '// *[ @ id = "title"]')
    time.sleep(1)
    click2_login.send_keys('DDI\n')
    print('DDI搜索完毕')
    time.sleep(2)
    time.sleep(2)
    ddi_numbers = driveri.find_element(
        By.XPATH, '//*[@id="gridId_total_number"]').text
    ddi_number = int(''.join(c for c in ddi_numbers if c.isdigit()))
    print('一共查询出%s个DDI事项' % str(ddi_number))
    for em in range(0, int(ddi_number)):
        print('第%s循环' % str(em))
        driveri.find_element_by_css_selector('.titleText').click()
        time.sleep(2)
        n = driveri.window_handles
        driveri.switch_to.window(n[-1])
        print('DDI子窗口:' + driveri.title)
        get_ddi(driveri)
        driveri.switch_to.window(driveri.window_handles[0])  # 取到主页
        driveri.switch_to.frame('mainIframe')
        driveri.switch_to.frame('pendingMainIframe')  # 进入iframe
        print(ddi_number)


oracle_insert.setpath()
oracle_insert.conn()

while True:
    if login_oa('tiger', 'tiger') != 1:
        break


print('程序结束')

页面简单展示

登录页面

数据拉取页面

后续补充:

为了方便查询管理DDI数据,又使用Django+bootstrap制作出一个web登录查询页面,后台数据库使用Oracle。

页面展示

完成后在服务器建了个任务计划程序,在服务器后台跑,以后就可以自动处理OA的待办事项啦。

 

 

上一篇: CSS简单实现吃豆人动画

下一篇: itchat实现微信群聊自动签到

评论 列表: