主要实现功能:
– 登陆网页
– 动态等待网页加载
– 验证码下载
很早就有一个想法,就是自动按照脚本执行一个功能,节省大量的人力——个人比较懒。花了几天写了写,本着想完成验证码的识别,从根本上解决问题,只是难度太高,识别的准确率又太低,计划再次告一段落。
希望这次经历可以与大家进行分享和交流。
python打开浏览器
相比与自带的urllib2模块,操作比较麻烦,针对于一部分网页还需要对cookie进行保存,很不方便。于是,我这里使用的是python2.7下的selenium模块进行网页上的操作。
测试网页:http://graduate.buct.edu.cn
打开网页:(需下载chromedriver)
为了支持中文字符输出,我们需要调用sys模块,把默认编码改为 utf-8
from selenium.webdriver.support.ui import select, webdriverwait
from selenium import webdriver
from selenium import common
from pil import image
import pytesser
import sys
reload(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下的开发者模式(全程需要这个功能来找到相关的资源)。
vczkprbljnjkcxvvo9gh1pht0lnytcsyv7fwpgjyic8+dqo8aw1nigfsdd0=”这里写图片描述” src=”http://www.jb51.net/uploadfile/collfiles/20160414/20160414092144893.png” title=”\” />
这里我们看到有一个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,根据测试,可以唯一定位一个元素的位置,很好用。
//*[@]/tbody/tr/td[2] (前面是xpath)
爬取信息
接下来我们要进行的步骤是爬取现有的有效报告:
# 寻找有效报告
flag = 1
count = 2
count_valid = 0
while flag:
try:
category = broswer.find_element_by_xpath(‘//*[@]/tbody/tr[‘ + str(count) + ‘]/td[1]’).text
count += 1
except common.exceptions.nosuchelementexception:
break
# 获取报告信息
flag = 1
for currentlecture in range(2, count):
# 类别
category = broswer.find_element_by_xpath(‘//*[@]/tbody/tr[‘ + str(currentlecture) + ‘]/td[1]’).text
# 名称
name = broswer.find_element_by_xpath(‘//*[@]/tbody/tr[‘ + str(currentlecture) + ‘]/td[2]’).text
# 单位
unitspublish = broswer.find_element_by_xpath(‘//*[@]/tbody/tr[‘ + str(currentlecture) + ‘]/td[3]’).text
# 开始时间
starttime = broswer.find_element_by_xpath(‘//*[@]/tbody/tr[‘ + str(currentlecture) + ‘]/td[4]’).text
# 截止时间
endtime = broswer.find_element_by_xpath(‘//*[@]/tbody/tr[‘ + str(currentlecture) + ‘]/td[5]’).text
爬取验证码
对网页中的验证码进行元素审查后,我们发现了其中的一个一个链接,是 identifyingcode.apsx,后面我们就对这个页面进行加载,并批量获取验证码。
爬取的思路是用selenium截取当前页面(仅显示部分),并保存到本地——需要翻页并截取特定位置的请研究:
broswer.set_window_position(**)相关函数;然后人工进行验证码的定位,通过pil模块进行截取并保存。
最后调用谷歌在python下的pytesser进行字符识别,但这个网站的验证码有很多的干扰,外加字符旋转,仅仅能识别其中的一部分字符。
# 获取验证码并验证(仅仅一幅)
authcodeurl = broswer.find_element_by_xpath(‘//*[@]/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(‘//*[@]/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()
爬取下来的验证码
一部分验证码原图:
从上面的验证码看出,字符是带旋转的,而且因为旋转造成的重叠对于后续的识别也有很大的影响。我曾尝试过使用神经网络进行训练,但因没有进行特征向量的提取,准确率低得离谱。
关于python爬虫爬验证码实现功能详解就给大家介绍到这里,希望对大家有所帮助!