1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 12306验证码识别初尝试(3)——tesseract的长处与短处 使用百度文字识别与百度图片自

12306验证码识别初尝试(3)——tesseract的长处与短处 使用百度文字识别与百度图片自

时间:2022-05-16 14:03:14

相关推荐

12306验证码识别初尝试(3)——tesseract的长处与短处 使用百度文字识别与百度图片自

12306验证码识别是我人生中“抢购”这一重大环节的第一步,所以我一定会把此环节写好,现在12306已经小小成功,接下来,我打算使用keras来深度学习解决12306抢票的问题,当然,如果春运票都抢的到的话,其他抢购应该很好做。

在系列文章的第一篇(/galilajiao/article/details/86497584#comments)中,我采用google维护的开源OCR tesseract识别验证码中的关键字/question,但是效果极差。晚上发现作者用了一个pre_ocr_processing函数,我也试着用它来处理关键字,但是仍然不行,只能放弃tesseract.

tesseract的长处是开源,免费,可以识别工整的印刷体中文,但是歪曲的和明显扫描痕迹的,都识别的很差。而与此同时,不仅仅有百度OCR,还有微软OCR,还有腾讯OCR等等。所以,就不要重新造轮子了。详情可以参考这篇博文:/a/1190000012861561

于是转而使用其他工具,使用百度通用文字识别(/tech/ocr/general)试了一下,果然很不错,成功率高达75%,已经很好了,我一般登陆12306都要刷新四五次。如果就算图片识别率仅弄到30%,75%*30%=22.5%,也跟我手动刷验证码相当了。在此有一篇博文:/mdeditor/86500057#

而且百度通用文字识别有免费版,太好了:

完整版代码我会在文末贴出,在此先讲述我编程+抄袭的过程.

把网上的代码拿来用之后,研究了程序,截图的尺寸挺好,但为什么百度识别的图都显示unknown呢?于是开始学习百度识图的流程:

首先,百度识图(/docs#/ImageClassify-API/top)可以先注册,登陆之后创建应用。然后编程获取access_token,再然后照着官方程序写,来识别图片。之所以不在代码中写死access_token,是因为每个access_token只有30天有效期。

其次就是我所用的方法,首先 pip install baidu-aip,然后几行程序就搞定了,比上面简单的多。编程中简单是极为关键的,因为编程讲究的就是绝对和确定,而越长的代码就越容易出错。需要注意如果用这种方法,则不论是使用百度通用文字识别,还是百度识图,都必须install baidu-aip.此方法详情见博文:/u012236875/article/details/74726035

确定好了方法,pip install baidu-aip之后,我开始寻找我的AppID, API Key,和Secret Key. 找了半天百度的API Key和Secret Key,后来给百度打电话查询到是在自己名字的小圆圈下面的Security Credentials里面。没想到客服也错了,这个Access Key和Secret Key不知道有啥用。

经过努力,找到了正确的寻找key的方法:

1.百度“百度AI开放平台 文字识别”:

2.选择第一条,进入相关页面:

3.点击上图中的“立即使用”,进入相关页面:

4.点击上图中的“管理应用”,就可以看到AppID,API Key,Secret Key了:

现在,开始正儿八经编程了:

首先,还是说一下pip install baidu-aip.install完毕之后,不需要退出或重启pyCharm(我用的IDE),就可以在pyCharm的File-Settings-ProjectInterpretor-‘+'中可就可以找到baidu-aip.

哈哈,初步成功!话说‘双面膛’是什么鬼?

说一句题外话,貌似不需要建立一个百度AI文字识别,直接一个图片识别就可以,因为其中包含了文字识别,但是不能通过建立文字识别而包括图片识别,因为其中无相关选项:

在此亮相一下12306的截图,不是我不想用百度识图达到较高的准确率,而是12306实在是太凶残了,六幅图中就一张是大半个路灯,这不仅仅是需要识图,而且需要推理了,当然,机器推理不知道如何实现,但是可以考虑深度学习,这是后话了:

运行了很多次程序,终于成功了几次(我设定在识别出的关键字与图片的一串关键字中有一个相同时,就打印“找到啦!”):

我很快在网上找到一个大牛识别率高达96%的博文:

/weixin_41578580/article/details/80052065

他的试验网站是/weixin_41578580/article/details/80052065或http://103.46.128.47:47720/

我尝试他网站的结果:

此人说自己用的是初步的keras,没啥说的,大写的服气。初级的keras都这么厉害,那高级的keras不知道得多牛了。

闲话少说,敝帚自珍,先把我的百度识图做通再转向深度识别。为了能移动到某个(x,y)坐标然后点击(通过坐标点击相应的验证码),本来打算使用了PyAutoGUI这个包,但是pip install pyautogui死活安不上,遂放弃:

然后参考了此博文:

/jay_wonder/article/details/82529973

成功自动勾选图片:

最后添加上一句:

self.driver.find_by_text(u"登录").click()

即可在选择相关验证码图片后自动点击登录按钮。

打完收工,贴上完整版代码,有疑惑的同学欢迎留言:

# -*- coding: utf-8 -*-"""@author: Steve"""from selenium import webdriverfrom mon.action_chains import ActionChains# 导入Keys 模块from mon.keys import Keysfrom splinter.browser import Browserfrom time import sleepfrom PIL import Imagefrom PIL import ImageFilter#import urllib #这是python2的用法#import urllib2 #这是python2的用法import urllib.requestimport sysimport reimport jsonimport sslimport tracebackimport time, sysimport winsoundimport urllib.parse, urllib.request, base64from aip import AipOcrfrom aip import AipImageClassifyif hasattr(ssl, '_create_unverified_context'):ssl._create_default_https_context = ssl._create_unverified_contextUA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36"#pic_url = "/otn/passcodeNew/getPassCodeNew?module=login&rand=sjrand&0.21191171556711197"text_keyword = ""def get_img(pic_url):resp = urllib.request.urlopen(pic_url)raw = resp.read()with open("./tmp.jpg", 'wb') as fp:fp.write(raw)return Image.open("./tmp.jpg")def get_sub_img(im, x, y):assert 0 <= x <= 3assert 0 <= y <= 2WITH = HEIGHT = 68left = 5 + (67 + 5) * xtop = 41 + (67 + 5) * yright = left + 67bottom = top + 67return im.crop((left, top, right, bottom))def baidu_character():global text_keyword# 在这三个地方填入参数api_id = '15448634'api_key = '6RCoLGGswaGg5KIL4S5flQqL'secret_key = 'KN9gaY2P40TwMFbtM38nok7S0C6Cs0EK'client = AipOcr(api_id, api_key, secret_key) # 到这里都是固定用法with open('D:/pyproject/QiangHuochepiao_yanzhengma_baiduOCR/temp_question.png', 'rb') as f:img = f.read()text = client.basicGeneral(img)#print('text is:',text)# 通用文字识别方式识别图片内容,一天50000次,像什么高精度版就是basicAccurate,具体参考下方aipocr模块文档for each in text.get('words_result'):text_keyword = each.get('words')#print(text_word) # 返回的是个json,内容在这里面return text_keyword#text_str=str(text,encoding="utf-8")#text_dir = eval(text_str) # eval将字符串转换成字典#text_words= text_dir['words']#if (text_words):# print('text_words is:',text_words)# #APIKey就是client_id SecretKey就是client_secret# host = '/oauth/2.0/token?grant_type=client_credentials&client_id=6RCoLGGswaGg5KIL4S5flQqL&client_secret=KN9gaY2P40TwMFbtM38nok7S0C6Cs0EK'# request = urllib.request.Request(host)# request.add_header('Content-Type', 'application/json; charset=UTF-8')# response = urllib.request.urlopen(request)# content = response.read()# if (content):#print('content is:',content)# content_str=str(content,encoding="utf-8")# content_dir = eval(content_str) # eval将字符串转换成字典# access_token= content_dir['refresh_token']# if (access_token):#print('access_token is:',access_token)## #access_token = '#####调用鉴权接口获取的token#####'# #url = '/rest/2.0/ocr/v1/general?access_token=' + access_token# url = '/rest/2.0/ocr/v1/general?access_token=25.7dc71ed64600387995cc34af8a3eff5c.315360000.1863315462.282335-15448634'# print('url is',url)# # 二进制方式打开图文件# #f = open(r'./temp_question.png', 'rb') # 本地图片# f = open(r'D:/pyproject/QiangHuochepiao_yanzhengma_baiduOCR/temp_question.png', 'rb')# # 参数image:图像base64编码# img = base64.b64encode(f.read())# print('1')# params = {"image": img}# print('2')# params = urllib.parse.urlencode(params).encode(encoding='UTF8')# print('3')# request = urllib.request.Request(url, params)# print('4')# request.add_header('Content-Type', 'application/x-www-form-urlencoded')# print('5')# response = urllib.request.urlopen(request)# print('6')# content = response.read()# print('7')# if (content):#print(content) # print((content).decode())# return""" 读取图片 """def get_file_content(filePath):with open(filePath, 'rb') as fp:return fp.read()def baidu_stu_lookup(im):im.save("./query_temp_img.png")#raw = open("./query_temp_img.png", 'rb').read()""" 这里输入你创建应用获得的三个参数 """APP_ID = '15455771'API_KEY = 'qYpax79Lw5Gmwg9hNFlI0GU0'SECRET_KEY = '13GuQoUwgb9gyedFsFoumTiK4kQTycBZ'client = AipImageClassify(APP_ID, API_KEY, SECRET_KEY)image = get_file_content("./query_temp_img.png")""" 调用通用物体识别 """text = client.advancedGeneral(image)print(client.advancedGeneral(image))""" 得到需要的关键字 """for each in text.get('result'):img_keyword = each.get('keyword')#print(img_keyword)#print(text_keyword)if (img_keyword==text_keyword):print(u"找到啦!")return True# url = url + str(len(raw))# if (url):#print(url)# req = urllib.request.Request(url, raw, {'Content-Type': 'image/png', 'User-Agent': UA})# resp = urllib.request.urlopen(req)## resp_url = resp.read() # return a pure url## if (resp_url):#print(resp_url)# url = "/n/searchpc?queryImageUrl=" + urllib.request.quote(resp_url)## req = urllib.request.Request(url, headers={'User-Agent': UA})# resp = urllib.request.urlopen(req)## html = resp.read()# return baidu_stu_html_extract(html)# def baidu_stu_html_extract(html):## pattern = pile(r'<script type="text/javascript">(.*?)</script>', re.DOTALL | re.MULTILINE)#pattern = pile(r"keywords:'(.*?)'")##pattern = pattern.decode('utf-8') # /zoulonglong/article/details/78547191#html = html.decode('utf-8')#matches = pattern.findall(html)#if not matches:# return '[UNKNOWN]'#json_str = matches[0]##json_str = json_str.replace('\\x22', '"').replace('\\\\', '\\')### print json_str##result = [item['keyword'] for item in json.loads(json_str)]##return '|'.join(result) if result else '[UNKNOWN]'def ocr_question_extract(im):# git@:madmaze/pytesseract.gitglobal pytesseracttry:import pytesseractexcept:print("[ERROR] pytesseract not installed")returnim = im.crop((117, 3, 260, 22))#im = pre_ocr_processing(im)im.save("./temp_question.png")#im.show()return baidu_character()#return pytesseract.image_to_string(im, lang='chi_sim').strip()def pre_ocr_processing(im):im = im.convert("RGB")width, height = im.sizewhite = im.filter(ImageFilter.BLUR).filter(ImageFilter.MaxFilter(23))grey = im.convert('L')impix = im.load()whitepix = white.load()greypix = grey.load()for y in range(height):for x in range(width):greypix[x, y] = min(255, max(255 + impix[x, y][0] - whitepix[x, y][0],255 + impix[x, y][1] - whitepix[x, y][1],255 + impix[x, y][2] - whitepix[x, y][2]))new_im = grey.copy()binarize(new_im, 150)return new_imdef binarize(im, thresh=120):assert 0 < thresh < 255assert im.mode == 'L'w, h = im.sizefor y in range(0, h): # for y in xrange(0, h): # xrange只用于python 2for x in range(0, w): # for x in xrange(0, w): # xrange只用于python 2if im.getpixel((x, y)) < thresh:im.putpixel((x, y), 0)else:im.putpixel((x, y), 255)class huoche(object):"""docstring for huoche"""#dr = webdriver.Chrome() #此命令可以成功打开chromedriver_name = ''executable_path = ''# 用户名,密码username = u"galilajiao@"passwd = u"galilajiao"# cookies值,需自行寻找#starts = u"%u6B66%u6C49%2CWHN" # 武汉#ends = u"%u9EBB%u57CE%2CMCN" # 麻城starts = u"%u5317%u4EAC%2CBJP"ends = u"%u9A7B%u9A6C%u5E97%u897F%2CZLN"# 时间格式-01-19dtime = u"-01-16"# 车次,选择第几趟,0则从上之下依次点击order = 0###乘客名users = [u"耿爽","李萌萌"]##席位xb = u"二等座"pz = u"成人票""""网址"""ticket_url = "/otn/leftTicket/init"login_url = "/otn/login/init"initmy_url = "/otn/view/index.html"buy = "/otn/confirmPassenger/initDc"login_url = '/otn/login/init'def __init__(self):self.driver_name = 'chrome'self.executable_path = 'C:\Python27\chromedriver.exe'def login(self):self.driver.visit(self.login_url)#sleep(9)# 填充密码self.driver.fill("loginUserDTO.user_name", self.username)# sleep(1)self.driver.fill("userDTO.password", self.passwd)print(u"等待验证码,自行输入...")#验证码部分# 定位到要右击的元素#qqq = self.driver.driver.find_element_by_xpath("//*[@id='loginForm']/div/ul[2]/li[4]/div/div/div[3]").textpic = self.driver.driver.find_element_by_xpath("//*[@id='loginForm']/div/ul[2]/li[4]/div/div/div[3]/img")#sleep(3)pic_src = pic.get_attribute('src')# image = pic.find_element_by_tag_name("img")#pic_src = pic.value_of_css_property('background-color')#pic_src = pic.getText()#print('url is: %s' % (pic_src))#print(pic.get_attribute("alt"))# 对定位到的元素执行鼠标右键操作#qqq2 = ActionChains(self.driver).context_click(qqq).perform()#ActionChains(self.driver).contextClick(qqq).sendKeys(Keys.ARROW_DOWN).build().perform()#actionChains = ActionChains(self.driver)#actionChains.context_click(qqq).send_keys(Keys.ARROW_DOWN).send_keys(Keys.ENTER).perform()#action = ActionChains(self.driver)#action.move_to_element(qqq) # 移动到该元素#action.context_click(qqq) # 右键点击该元素#action.send_keys(Keys.ARROW_DOWN) # 点击键盘向下箭头#action.send_keys('v') # 键盘输入V保存图#action.perform() # 执行保存im = get_img(pic_src)#print('OCR Question: ',ocr_question_extract(im))ocr_question_extract(im)print('OCR Question:',baidu_character())for y in range(2):for x in range(4):im2 = get_sub_img(im, x, y)result = baidu_stu_lookup(im2)if(result == True):if(y==0 and x==0):result00=TrueActionChains(self.driver.driver).move_to_element_with_offset(pic, 40 + 72 * (1 - 1),73).click().perform()if(y==0 and x==1):result01=TrueActionChains(self.driver.driver).move_to_element_with_offset(pic, 40 + 72 * (2 - 1),73).click().perform()if (y==0 and x==2):result02 = TrueActionChains(self.driver.driver).move_to_element_with_offset(pic, 40 + 72 * (3 - 1),73).click().perform()if (y ==0 and x==3):result03 = TrueActionChains(self.driver.driver).move_to_element_with_offset(pic, 40 + 72 * (4 - 1),73).click().perform()if (y == 1 and x == 0):result10 = TrueActionChains(self.driver.driver).move_to_element_with_offset(pic, 40 + 72 * (1 - 1),145).click().perform()if (y == 1 and x == 1):result11 = TrueActionChains(self.driver.driver).move_to_element_with_offset(pic, 40 + 72 * (2 - 1),145).click().perform()if (y == 1 and x == 2):result12 = TrueActionChains(self.driver.driver).move_to_element_with_offset(pic, 40 + 72 * (3 - 1),145).click().perform()if (y == 1 and x == 3):result13 = TrueActionChains(self.driver.driver).move_to_element_with_offset(pic, 40 + 72 * (4 - 1),145).click().perform()#ActionChains(self.driver).context_click(pic).perform()#action = ActionChains(self.driver)#action.move_to_element_with_offset(pic, 5, 5)#action.click()#action.perform()#print(y, x, result)#pic2 = self.driver.driver.find_element_by_xpath("//*[@id='loginForm']/div/ul[2]/li[4]/div/div/div[3]/img")#pic.move_to_element_with_offset(pic, 5, 5).click().performprint("Here!")#ActionChains(self.driver.driver).move_to_element_with_offset(pic, 40 + 72 * (1 - 1),73).click().perform()#ActionChains(self.driver.driver).move_to_element_with_offset(pic, 40 + 72 * (2 - 1), 73).click().perform()# print("Here 2")# else:# i -= 4# ActionChains(self.driver.driver).move_to_element_with_offset(pic, 40 + 72 * (i - 1),145).click().perform()#element = self.driver.driver.find_element_by_xpath("//*[@id='loginForm']/div/ul[2]/li[4]/div/div/div[3]/img")#ActionChains(self.driver.driver).move_to_element_with_offset(pic, 40 + 72 * (1 - 1), 73).click().perform()#ActionChains(self.driver).move_to_element_with_offset(pic, 40 + 72 * (1 - 1), 73).click().perform()#num = 8#try:#element = self.browser.find_element_by_class_name('touclick-img-par')#element = self.driver.driver.find_element_by_xpath("//*[@id='loginForm']/div/ul[2]/li[4]/div/div/div[3]/img")#ActionChains(self.browser).move_to_element_with_offset(element, 40 + 72 * (1 - 1), 73).click().perform()#ActionChains(self.driver.driver).move_to_element_with_offset(pic, 40 + 72 * (1 - 1), 73).click().perform()#print("Here 0")#for i in num:# if i <= 4:# print("Here 1")# ActionChains(self.driver.driver).move_to_element_with_offset(pic, 40 + 72 * (i - 1),73).click().perform()# print("Here 2")# else:# i -= 4# ActionChains(self.driver.driver).move_to_element_with_offset(pic, 40 + 72 * (i - 1),145).click().perform()#except:# print('元素不可选!')while True:self.driver.find_by_text(u"登录").click()#self.driver.find_by_text(u"快速注册").click()if self.driver.url != self.initmy_url:sleep(1)else:breakdef start(self):self.driver = Browser(driver_name=self.driver_name, executable_path=self.executable_path)self.driver.driver.set_window_size(1400, 1000)self.login() # 此Login指上面的login函数# sleep(1)self.driver.visit(self.ticket_url) # 打开12306界面try:print(u"购票页面开始...")# sleep(1)# 加载查询信息self.driver.cookies.add({"_jc_save_fromStation": self.starts})self.driver.cookies.add({"_jc_save_toStation": self.ends})self.driver.cookies.add({"_jc_save_fromDate": self.dtime})self.driver.reload()# 重新加载cookies# 添加车次类型。放在加载之后,因为实测发现比如勾选"GC-高铁/城际"checkbox后,什么都不干页面就会自动变化l = ['GC-高铁/城际', 'D-动车'] # 在列表里可以去掉不需要的车次类型for i in l:btn = self.driver.find_by_text(i)btn.click()i = 0 # 上面的for循环使用了i,这里如果不清零,下面因为也用到了i,会报错。count = 0if self.order != 0:while self.driver.url == self.ticket_url: # 判断是否成功跳转到目标页面self.driver.find_by_text(u"查询").click()count += 1print(u"循环点击查询... 第 %s 次" % count)# sleep(1)try:self.driver.find_by_text(u"预订")[self.order - 1].click()except Exception as e:print(e)print(u"还没开始预订")continueelse:while self.driver.url == self.ticket_url:self.driver.find_by_text(u"查询").click()count += 1print(u"循环点击查询... 第 %s 次" % count)# sleep(0.8)try:for i in self.driver.find_by_text(u"预订"):i.click()sleep(1)except Exception as e:print(e)print(u"还没开始预订 %s")continueprint(u"开始预订...")# sleep(3)# self.driver.reload()sleep(1)print(u'开始选择用户...')for user in self.users:self.driver.find_by_text(user).last.click()print(u"提交订单...")sleep(1)# self.driver.find_by_text(self.pz).click()# self.driver.find_by_id('').select(self.pz)# # sleep(1)# self.driver.find_by_text(self.xb).click()# sleep(1)self.driver.find_by_id('submitOrder_id').click()# print u"开始选座..."# self.driver.find_by_id('1D').last.click()# self.driver.find_by_id('1F').last.click()sleep(1.5)print(u"确认选座...")self.driver.find_by_id('qr_submit_id').click()# 连续发出提示音while True:winsound.Beep(300, 1000)except Exception as e:print(e)cities = {'成都': '%u6210%u90FD%2CCDW','重庆': '%u91CD%u5E86%2CCQW','北京': '%u5317%u4EAC%2CBJP','广州': '%u5E7F%u5DDE%2CGZQ','杭州': '%u676D%u5DDE%2CHZH','宜昌': '%u5B9C%u660C%2CYCN','郑州': '%u90D1%u5DDE%2CZZF','深圳': '%u6DF1%u5733%2CSZQ','西安': '%u897F%u5B89%2CXAY','大连': '%u5927%u8FDE%2CDLT','武汉': '%u6B66%u6C49%2CWHN','上海': '%u4E0A%u6D77%2CSHH','麻城': '%u9EBB%u57CE%2CMCN','临沂': '%u4E34%u6C82%2CLVK','驻马店西': '%u9A7B%u9A6C%u5E97%u897F%2CZLN'}if __name__ == '__main__':huoche = huoche()#huoche.starts = cities[sys.argv[1]]#huoche.ends = cities[sys.argv[2]]#huoche.dtime = sys.argv[3]huoche.start()

12306验证码识别初尝试(3)——tesseract的长处与短处 使用百度文字识别与百度图片自动识别验证码并自动抢票 识别成功率10%

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。