Learning python reptiles: verification codes sliding yards

The first two articles mentioned verification code identifying the general picture, and in particular the way for recognition of machine learning accuracy will be relatively high. But now popular slide code, so there is little mention of a simple sliding verification code recognition skills.

Open Firefox, press  F12 Enter  url to  http://www.gsxt.gov.cn/index.html  , you can open  the national enterprise credit information publicity system  , enter the keyword  China Unicom  , click on the search will pop out a slip verification code this paper is mainly to identify this URL sliding verification code.

Such codes identify the main use of the slide  selenium library, the picture is determined to need to be from the correct button slider position. You first need to open the browser, set the maximum loading time  90 seconds, if more than  90 seconds for so long a direct call  js to stop loading, and finally determine whether a page is loaded, and if not, then reload:

from selenium import webdriver
# 打开浏览器
'''
遇到python不懂的问题,可以加Python学习交流群:1004391443一起学习交流,群文件还有零基础入门的学习资料
'''
def openbrowser(url):
    global browser

    # 声明谷歌浏览器
    browser = webdriver.Chrome()
    # 限制加载时间不能超过90秒
    browser.set_page_load_timeout(90)

    try:
        # 输入网址
        browser.get(url)
        if "400 Bad request" in browser.page_source:
            browser.get(url)
    except:
        # 超过90秒强制停止加载
        browser.execute_script('window.stop()')
        if "400 Bad request" in browser.page_source:
            browser.get(url)
        else:
            pass
    time.sleep(5)

Use  F12 can know the input box  id=keyword , the query box  id=btn_query :

# 输入关键字并查询
def inputKeyword(keyword):
    # 清空输入框
    browser.find_element_by_id("keyword").clear()
    # 输入查找的关键字
    browser.find_element_by_id("keyword").send_keys(keyword)
    time.sleep(5)
    # 点击查询按钮
    browser.find_element_by_id("btn_query").click()
    time.sleep(5)

And  selenium can control the mouse, you can call the library. China Unicom input query, slide identification codes, whereby the slider can know occurrence of the cross-brace  classname=gt_slider_knob , a function is provided, a drag input horizontal distance and a vertical distance of:

from selenium.webdriver.common.action_chains import ActionChains
# 拖放滑块
def drag_and_drop(x_offset, y_offset):
    # 找到滑块并滑动
    source = browser.find_element_by_class_name("gt_slider_knob")
    # 调用鼠标操作并且拖动
    ActionChains(browser).drag_and_drop_by_offset(source, x_offset, y_offset).perform()
    time.sleep(8)

Here is the key here! Core identification codes is sliding, and a verification code is determined picture image  RGB change value, assuming the original image verification code is:

Then gently pull the slider with the mouse to the bottom of the slide image verification code will appear:

Generally, we all know that each picture with many pixels are composed of:

每一个像素点都会有一个 RGB 值,这个值代表的是改像素点图片的颜色,而这里生成的验证码的图片很明显是有一个凹下去的区域,这个区域的颜色和原图不一样。所以我们主要是判断:

  1. 在什么地方原图和验证码图片的 RGB 值相差很大
  2. 相差很大的这个点的横纵坐标是多少,横坐标即为需要进行滑动的距离

在浏览器中找到验证码图片的位置,即为 classname=gt_box

获取这个图片的 left 、 top 、 right 、 bottom ,这里需要解释一下,top 和 right 相当于一张图片左上角的坐标,right 是距离左上角这个点向右的宽度,bottom 是距离左上角这个点向下的宽度:

定位到这张图片的位置,截取图片保存到内存中:

import io
'''
遇到python不懂的问题,可以加Python学习交流群:1004391443一起学习交流,群文件还有零基础入门的学习资料
'''
# 截取验证码图片
def screenShotImage():
    try:
        # 定位到验证码的框
        captchaElement = browser.find_element_by_class_name("gt_box")
    except:
        inputKeyword(keyword)
        # 定位到验证码的框
        captchaElement = browser.find_element_by_class_name("gt_box")
    locations = captchaElement.location
    sizes = captchaElement.size

    left = int(locations["x"])
    top = int(locations["y"])
    right = left + int(sizes["width"])
    bottom = top + int(sizes['height'])

    # 截图
    screenshot = browser.get_screenshot_as_png()
    screenshot = Image.open(io.BytesIO(screenshot))
    png = screenshot.crop((left, top, right, bottom))
    png.save(str(int(time.time())) + ".png")
    time.sleep(1)
    return png

在对原图和验证码图片进行对比的时候,要排除掉拼图的干扰,拼图也就是这张图片,它和原图也是不一样的:

如何排除这张图片的干扰呢?本文首先找到这张图片的宽度:

# 获取滑块的图片,是为了得到滑块的宽度
def getWidth():
    # 找到滑块并滑动
    slider = browser.find_element_by_class_name("gt_slice")
    sizes = slider.size
    width = sizes["width"]
    return width

由于该滑块总是出现在左边,所以在对比 RBG 值的时候跳过这个宽度。

将原图的每个像素点和验证码的每个像素点做差,如果差值都小于60则认为这个像素点出现 明显差异 ,即认定为验证码凹陷位置的起点。由于观察验证码图片的时候发现,滑块左边其实是有5个位移是空白的,所以最后的位移值要减掉5。而如果没有找到正确的偏移值,则返回一个假的偏移值55,防止程序中断:

# 获取滑动偏移量
def getOffset():
    img1 = screenShotImage()
    drag_and_drop(x_offset=5, y_offset=0)
    img2 = screenShotImage()
    w1, h1 = img1.size
    w2, h2 = img2.size
    print("wh")
    print(w1, h1, w2, h2)

    if w1 != w2 or h1 != h2:
        return False

    slider = getWidth()
    print("开始循环", w3, h3)
    for x in range(slider, w3):
        print(x)
        for y in range(0, h3):
            pix1 = img1.getpixel((x, y))
            pix2 = img2.getpixel((x, y))
            # 如果相差超过70则就认为找到了缺口的位置
            if abs(pix1[0]-pix2[0]) < 60 and abs(pix1[1]-pix2[1]) < 60 and abs(pix1[2]-pix2[2]) < 60:
				# 滑块左边其实是有5个位移是空白的,所以要减掉
                return x-5
	# 如果没有找到正确的偏移值,则返回一个假的偏移值,防止程序中断
    return 55

但是不管临界值选取60还是其他值效果都非常差,所以可以利用图片库比较两张图片有什么不同:

# 判断两张图片不同的地方
img3 = ImageChops.difference(img1, img2)
img3.save(str(int(time.time())) + ".png")

可以判断这张图片如果底色不是黑色,即 RBG(0,0,0) ,且像素颜色鲜艳,颜色鲜艳即 RBG 的某个值大于70,那么就认为找到了凹陷地方的边界,更改代码增加挑选条件:

# 获取滑动偏移量
def getOffset():
    img1 = screenShotImage()
    drag_and_drop(x_offset=5, y_offset=0)
    img2 = screenShotImage()
    # 判断两张图片不同的地方
    img3 = ImageChops.difference(img1, img2)
    img3.save(str(int(time.time())) + ".png")
    w1, h1 = img1.size
    w2, h2 = img2.size
    w3, h3 = img3.size
    print("wh")
    print(w1, h1, w2, h2)

    if w1 != w2 or h1 != h2:
        return False

    slider = getWidth()
    print("开始循环", w3, h3)
    for x in range(slider, w3):
        print(x)
        for y in range(0, h3):
            pix1 = img1.getpixel((x, y))
            pix2 = img2.getpixel((x, y))
            pix3 = img3.getpixel((x, y))
            print(pix3[0],pix3[1],pix3[2])
            # 如果相差超过70则就认为找到了缺口的位置
            if pix3[0] > 70 or pix3[1] > 70 or pix3[2] > 70 and abs(pix1[0]-pix2[0]) < 60 and abs(pix1[1]-pix2[1]) < 60 and abs(pix1[2]-pix2[2]) < 60:
                # 滑块左边其实是有5个位移是空白的,所以要减掉
                return x-5
    # 如果没有找到正确的偏移值,则返回一个假的偏移值,防止程序中断
    return 55

最后代入运行能准确的找到滑块验证码的位置:

Guess you like

Origin blog.csdn.net/qq_40925239/article/details/90698098