Python爬虫笔记【一】模拟用户访问之webdriver用户登入——第一次(6)
这时跳转表单,填写账号密码,识别验证码这三项都已经完成,下面就开始模拟登入了(提前说明一下,这次模拟登入是在每张验证码都有固定的url,在下载到本地的验证码需要与打开网页时的验证码相同才行。你可以在网页中找到验证码的src打开两次,如果图片相同那么下面的登入应该就能成功了,如果不同那么下一篇介绍怎么解决)
# 网络爬虫 验证码同步问题 from selenium import webdriver from selenium.common.exceptions import TimeoutException from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.keys import Keys import time from urllib.request import urlretrieve # 下面为识别函数 from shibie import recognize driver = webdriver.Firefox()
# 下面为申请的代理检测问题用的 # profile = webdriver.FirefoxProfile() # profile.set_preference('network.proxy.type', 1) # profile.set_preference('network.proxy.http', '127.0.0.1') # profile.set_preference('network.proxy.http_port', 8080) # int # profile.update_preferences() # driver = webdriver.Firefox(firefox_profile=profile) driver.get("http://xxxxxxxxx/home.aspx") # 跳转表单 driver.switch_to_frame('frm_login') # 输入账号密码 driver.find_element_by_id("txt_asmcdefsddsd").send_keys("xxxxxxx") driver.find_element_by_id("txt_asmcdefsddsd").send_keys(Keys.TAB) driver.find_element_by_id("txt_pewerwedsdfsdff").send_keys("xxxxxxx") # 点击验证码出发js以便于获取id,要不会显示找不到,如果验证码本来就显示在页面中则下面代码忽略 driver.find_element_by_id("txt_sdertfgsadscxcadsads").click() jpg = driver.find_element_by_id("imgCode") # 获取验证码属性 image = jpg.get_attribute("src") img_name = 'check.jpg' path_img = './easy_code/' + img_name urlretrieve(image, path_img) # 去除验证码中的空格 code = recognize(img_name).replace(" ", "") driver.find_element_by_id("txt_sdertfgsadscxcadsads").send_keys(code) print(code) time.sleep(5) driver.find_element_by_id("btn_login").click()
上一篇检测识别数的代码略微一改就可以换成本章的验证码处理加识别函数,下面附代码:
from PIL import Image from pytesseract import * from fnmatch import fnmatch from queue import Queue import matplotlib.pyplot as plt import cv2 import time import os def clear_border(img,img_name): '''去除边框 ''' h, w = img.shape[:2] for y in range(0, w): for x in range(0, h): # if y ==0 or y == w -1 or y == w - 2: if y < 4 or y > w -4: img[x, y] = 255 # if x == 0 or x == h - 1 or x == h - 2: if x < 4 or x > h - 4: img[x, y] = 255 return img def interference_line(img, img_name): ''' 干扰线降噪 ''' h, w = img.shape[:2] # !!!opencv矩阵点是反的 # img[1,2] 1:图片的高度,2:图片的宽度 for r in range(0,2): for y in range(1, w - 1): for x in range(1, h - 1): count = 0 if img[x, y - 1] > 245: count = count + 1 if img[x, y + 1] > 245: count = count + 1 if img[x - 1, y] > 245: count = count + 1 if img[x + 1, y] > 245: count = count + 1 if count > 2: img[x, y] = 255 return img def interference_point(img,img_name, x = 0, y = 0): """点降噪 9邻域框,以当前点为中心的田字框,黑点个数 :param x: :param y: :return: """ # todo 判断图片的长宽度下限 cur_pixel = img[x,y]# 当前像素点的值 height,width = img.shape[:2] for y in range(0, width - 1): for x in range(0, height - 1): if y == 0: # 第一行 if x == 0: # 左上顶点,4邻域 # 中心点旁边3个点 sum = int(cur_pixel) \ + int(img[x, y + 1]) \ + int(img[x + 1, y]) \ + int(img[x + 1, y + 1]) if sum <= 2 * 245: img[x, y] = 0 elif x == height - 1: # 右上顶点 sum = int(cur_pixel) \ + int(img[x, y + 1]) \ + int(img[x - 1, y]) \ + int(img[x - 1, y + 1]) if sum <= 2 * 245: img[x, y] = 0 else: # 最上非顶点,6邻域 sum = int(img[x - 1, y]) \ + int(img[x - 1, y + 1]) \ + int(cur_pixel) \ + int(img[x, y + 1]) \ + int(img[x + 1, y]) \ + int(img[x + 1, y + 1]) if sum <= 3 * 245: img[x, y] = 0 elif y == width - 1: # 最下面一行 if x == 0: # 左下顶点 # 中心点旁边3个点 sum = int(cur_pixel) \ + int(img[x + 1, y]) \ + int(img[x + 1, y - 1]) \ + int(img[x, y - 1]) if sum <= 2 * 245: img[x, y] = 0 elif x == height - 1: # 右下顶点 sum = int(cur_pixel) \ + int(img[x, y - 1]) \ + int(img[x - 1, y]) \ + int(img[x - 1, y - 1]) if sum <= 2 * 245: img[x, y] = 0 else: # 最下非顶点,6邻域 sum = int(cur_pixel) \ + int(img[x - 1, y]) \ + int(img[x + 1, y]) \ + int(img[x, y - 1]) \ + int(img[x - 1, y - 1]) \ + int(img[x + 1, y - 1]) if sum <= 3 * 245: img[x, y] = 0 else: # y不在边界 if x == 0: # 左边非顶点 sum = int(img[x, y - 1]) \ + int(cur_pixel) \ + int(img[x, y + 1]) \ + int(img[x + 1, y - 1]) \ + int(img[x + 1, y]) \ + int(img[x + 1, y + 1]) if sum <= 3 * 245: img[x, y] = 0 elif x == height - 1: # 右边非顶点 sum = int(img[x, y - 1]) \ + int(cur_pixel) \ + int(img[x, y + 1]) \ + int(img[x - 1, y - 1]) \ + int(img[x - 1, y]) \ + int(img[x - 1, y + 1]) if sum <= 3 * 245: img[x, y] = 0 else: # 具备9领域条件的 sum = int(img[x - 1, y - 1]) \ + int(img[x - 1, y]) \ + int(img[x - 1, y + 1]) \ + int(img[x, y - 1]) \ + int(cur_pixel) \ + int(img[x, y + 1]) \ + int(img[x + 1, y - 1]) \ + int(img[x + 1, y]) \ + int(img[x + 1, y + 1]) if sum <= 4 * 245: img[x, y] = 0 return img def _get_dynamic_binary_image(img_name): ''' 自适应阀值二值化 ''' img_name = './easy_code/' + img_name im = cv2.imread(img_name) im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) th1 = cv2.adaptiveThreshold(im, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21, 1) return th1 def recognize(img_name): if fnmatch(img_name, '*.jpg'): # 自适应阈值二值化 im = _get_dynamic_binary_image(img_name) # 去除边框 im = clear_border(im,img_name) # 对图片进行干扰线降噪 im = interference_line(im,img_name) # 对图片进行点降噪 im = interference_point(im,img_name) # 识别验证码 str_img = pytesseract.image_to_string(im, lang='mob') code = str_img.encode("GBK","ignore").decode('GBK') return code
本次测试我没有成功,不是因为代码问题,也不是验证码识别率问题,就是前面提到的验证码下载到本地时与网页上显示的不是同一个验证码,通过对网页抓包分析,验证码也只传过来一次,让好友对代码恢复成图片,发现是和网页上的验证码相同的,然后通过验证码网址再打开一个,恢复成图片,发现这时两张图片时不同的,所以我推测,在用urltetrieve函数下载图片时,它会再次打开一个网址,进行下载这样就导致下载的验证码与网页显示的验证码不同的问题。所以前面指出本次只针对每张验证码都有固定的src时才可以(不过这样的不多见了,哈哈)。