前段时间获取验证码,人工识别后模拟登陆成功,心里还小窃喜了一阵子。但是最近用同样的方法爬取另一家网站的验证码模拟登陆总是失败,提示验证码不正确,弄得很迷惑。
后来通过使用httpfox抓包仔细对比,怀疑每个验证码对应的cookie是固定的。爬取验证码的时候是一个cookie,登陆的时候却是另一个cookie,两者不匹配就无法成功登陆。(嗨,大学期间计算机网络没好好学落下的后遗症)
痛定思痛,一来为了验证我的思路是否正确,二来希望重新通过实践来回忆网络通信机制,决定尝试在获取验证码的同时从包中把cookie抓出来,然后用对应的cookie模拟登陆。
在借鉴的大牛的文章后(http://www.crifan.com/files/doc/docbook/web_scrape_emulate_login/release/html/web_scrape_emulate_login.html),最终的代码见文章最后。需要说明如下几点:
一、经验证,验证码确实跟cookie(本文就是一个sessionID)是一一对应的,因此获取验证码的时候在头文件中就要加入cookie,再用该cookie和验证码一起登陆就可以了。
二、通过很多次尝试,发现sessionID是可以自己随便设的,只要保证验证码和它是对应就好。应该不是普遍现象,大多数网站应该还是要老老实实抓取sessionID的。这也是本代码没有解决的主要问题
三、从第一次发本文到今天粘上代码,用了20天时间。期间不仅仅实现了虚拟登陆功能,还实现了结构化爬取数据(后续补充内容),写在网上一来方便记忆,而来希望能够帮到有同样问题的朋友,哈哈,我想这就是分享的魅力吧。
还得再接再厉
import urllib
import urllib2
import string
import re
import random
import Image
#涉及到的各页面地址
mainurl='重定向的网址'
hosturl = '网址一'
imgurl='验证码网址'
#任意指定一个NET_SessionId,用于后续的获取验证码和登陆
mycookie='ASP.NET_SessionId=xabcdefghijklmnopqrstuvw'
#使用上述的ID获取验证码
myimg ="F:\\MyPython\\code.gif"
imgrequest = urllib2.Request(imgurl)
imgrequest.add_header('Cookie',mycookie)
imgresponse=urllib2.urlopen(imgrequest)
dlimg = open(myimg,'wb')
dlimg.write(imgresponse.read())
dlimg.close()
#人工识别并输入验证码
im = Image.open(myimg)
im.show()
mycode=raw_input("Please Input The Code:")
#模拟登陆页面 ,并获取登陆后返回的页面
loginheaders = {
'Host':'dx.9lin.com',
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; rv:27.0) Gecko/20100101 Firefox/27.0',
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language':'zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3',
'Accept-Encoding':'gzip, deflate',
'Referer':'http://xx.xx.xx',
'Cookie':mycookie,
'Connection':'keep-alive',
'Content-Type':'application/x-www-form-urlencoded',
'Content-Length':'327'
}
loginpostData = {
'__EVENTTARGET':'btnSubmit',
'__EVENTARGUMENT':'',
'__VIEWSTATE':'xxxxxxxxx',#一堆编码,暂不知道作何用
'__VIEWSTATEGENERATOR':'xxxx',#一串数字,暂不知道作何用
'__EVENTVALIDATION':'xxxxx',#又是一堆编码,暂不知道作何用
'txt_username' : 'username',
'txt_userpwd' : 'mypassword',
'txt_ccode' : mycode
}
loginpostData = urllib.urlencode(loginpostData)
request = urllib2.Request(hosturl, loginpostData, loginheaders)
response = urllib2.urlopen(request)
text = response.read()
pattern=re.compile('xxxx')#通过分析获取到的页面判断是否登陆成功,应该有更简便的方法
if pattern.findall(text):
print "登陆成功"