Python 爬验证码,, 主要


主要实现功能:
- 登陆网页
- 动态等待网页载入
- 验证码下载

非常早就有一个想法,就是自己主动依照脚本运行一个功能。节省大量的人力——个人比較懒。花了几天写了写,本着想完成验证码的识别,从根本上解决这个问题,仅仅是难度太高,识别的准确率又太低。计划再次告一段落。
希望这次经历能够与大家进行分享和交流。

注:代码中的 username与password都是无效的!


Python打开浏览器

相比与自带的urllib2模块,操作比較麻烦。针对于一部分网页还须要对cookie进行保存,非常不方便。于是。我这里使用的是Python2.7下的selenium模块进行网页上的操作。

測试网页:http://graduate.buct.edu.cn


打开网页:(需下载chromedriver)
为了支持中文字符输出,我们须要调用sys模块。把默认编码改为 UTF-8

from selenium.webdriver.support.ui import Select, WebDriverWaitfrom selenium import webdriverfrom selenium import commonfrom PIL import Imageimport pytesserimport sysreload(sys)sys.setdefaultencoding(‘utf8‘)broswer = webdriver.Chrome()broswer.maximize_window()username = ‘test‘password = ‘test‘url = ‘http://graduate.buct.edu.cn‘broswer.get(url)

等待网页载入完成

使用的是selenium中的WebDriverWait。上面的代码中已经载入

url = ‘http://graduate.buct.edu.cn‘broswer.get(url)wait = WebDriverWait(webdriver,5) #设置超时时间5s# 在这里输入表单填写并载入的代码elm = wait.until(lambda webdriver: broswer.find_element_by_xpath(xpathMenuCheck))

元素定位、字符输入

接下来我们须要进行登录操作:这里我使用的是Chrome,右键选择须要进行填写内容的部分,选择检查,会自己主动转跳到 F12下的开发人员模式(全程须要这个功能来找到相关的资源)。

技术分享

以下的UserRole部分就是和“教师端”选择有关的部分
技术分享
这里我们看到有一个value = “1”,考虑到下拉框的属性,我们仅仅要想办法把这个value赋值给UserRole就好了。
这里使用的是通过selenium的Select模块来进行选择,定位控件使用 find_element_by_**,能一一相应,非常方便。

select = Select(broswer.find_element_by_id(‘UserRole‘))select.select_by_value(‘2‘)name = broswer.find_element_by_id(‘username‘)name.send_keys(username)pswd = broswer.find_element_by_id(‘password‘)pswd.send_keys(password)btnlg = broswer.find_element_by_id(‘btnLogin‘)btnlg.click()

这是用脚本自己主动填充完的效果,之后就会转跳到下一页。
技术分享


这里,我须要的是功能是自己主动对学术报告进行报名
技术分享

对须要已有的报告右键就可以发现和这个活动有关的消息,因如今没有报告,所以仅仅显示了标题。但对于后面的有效报告识别有类似的地方。
技术分享

对于元素的定位,我优先选择了 xpath。依据測试。能够唯一定位一个元素的位置,非常好用。

//*[@id="dgData00"]/tbody/tr/td[2]  (前面是xpath)

技术分享


爬取信息

接下来我们要进行的步骤是爬取现有的有效报告:

# 寻找有效报告flag = 1count = 2count_valid = 0while flag:    try:        category = broswer.find_element_by_xpath(‘//*[@id="dgData00"]/tbody/tr[‘ + str(count) + ‘]/td[1]‘).text        count += 1    except common.exceptions.NoSuchElementException:        break# 获取报告信息flag = 1for currentLecture in range(2, count):    # 类别    category = broswer.find_element_by_xpath(‘//*[@id="dgData00"]/tbody/tr[‘ + str(currentLecture) + ‘]/td[1]‘).text    # 名称    name = broswer.find_element_by_xpath(‘//*[@id="dgData00"]/tbody/tr[‘ + str(currentLecture) + ‘]/td[2]‘).text    # 单位    unitsPublish = broswer.find_element_by_xpath(‘//*[@id="dgData00"]/tbody/tr[‘ + str(currentLecture) + ‘]/td[3]‘).text    # 開始时间    startTime = broswer.find_element_by_xpath(‘//*[@id="dgData00"]/tbody/tr[‘ + str(currentLecture) + ‘]/td[4]‘).text    # 截止时间    endTime = broswer.find_element_by_xpath(‘//*[@id="dgData00"]/tbody/tr[‘ + str(currentLecture) + ‘]/td[5]‘).text

爬取验证码

技术分享

对网页中的验证码进行元素审查后,我们发现了当中的一个一个链接,是 IdentifyingCode.apsx。后面我们就对这个页面进行载入,并批量获取验证码。

技术分享

爬取的思路是用selenium截取当前页面(仅显示部分)。并保存到本地——须要翻页并截取特定位置的请研究:broswer.set_window_position(**)相关函数;然后人工进行验证码的定位,通过PIL模块进行截取并保存。
最后调用谷歌在Python下的pytesser进行字符识别,但这个站点的验证码有非常多的干扰,外加字符旋转,仅仅能识别当中的一部分字符。

# 获取验证码并验证(仅仅一幅)authCodeURL = broswer.find_element_by_xpath(‘//*[@id="Table2"]/tbody/tr[2]/td/p/img‘).get_attribute(‘src‘)  # 获取验证码地址broswer.get(authCodeURL)broswer.save_screenshot(‘text.png‘)rangle = (0, 0, 64, 28)i = Image.open(‘text.png‘)frame4 = i.crop(rangle)frame4.save(‘authcode.png‘)qq = Image.open(‘authcode.png‘)text = pytesser.image_to_string(qq).strip()
# 批量获取验证码authCodeURL = broswer.find_element_by_xpath(‘//*[@id="Table2"]/tbody/tr[2]/td/p/img‘).get_attribute(‘src‘)  # 获取验证码地址# 获取学习样本for count in range(10):    broswer.get(authCodeURL)    broswer.save_screenshot(‘text.png‘)    rangle = (1, 1, 62, 27)    i = Image.open(‘text.png‘)    frame4 = i.crop(rangle)    frame4.save(‘authcode‘ + str(count) + ‘.png‘)    print ‘count:‘ + str(count)    broswer.refresh()broswer.quit()

技术分享

一部分验证码原图:
技术分享 技术分享 技术分享 技术分享

从上面的验证码看出。字符是带旋转的,并且由于旋转造成的重叠对于兴许的识别也有非常大的影响。我曾尝试过使用神经网络进行训练。但因没有进行特征向量的提取。准确率低得离谱。


这个是一位作者实践后的心得:
http://www.cnblogs.com/sweetwxh/p/captcha_recognize.html

看了之后我变得清醒。决定不再继续识别验证码了。但这个经验非常实用,以后就能够拿来爬各种数据了

Python 爬验证码

评论关闭