某网站验证码的识别笔记【三】

来源:互联网 发布:感康和泰诺 知乎 编辑:程序博客网 时间:2024/06/05 22:42

新博客地址:http://gorthon.sinaapp.com/

识别笔记一:http://blog.csdn.net/bh20077/article/details/7041280

识别笔记二:http://blog.csdn.net/bh20077/article/details/7041400


这一篇其实与验证码识别没有关系。

但是是由验证码识别引起的一些问题。


这个网站是一个电子书籍分享下载网站,但是有下载限制(每天每个用户只能下载10本),试了一下注册新的账号又可以下载10本,看来是没有对ip进行处理。

我本意是要下载python,C++以及css,html方面的书籍的,但是每天10本的限制我得下载到什么时候……

所以准备如下:

1. 网站自动注册

以下是注册界面:

注册界面

可以看到站长做了个创新,需要填写C语言运行结果才能注册,这抵挡了相当一大部分普通用户注册,这是为何?试验结果表明这里刷新页面后可能出现C(居多)、Python(较多)以及JavaScript(很少)代码。而且几乎只用刷新5次你就能得到相同的代码…………

解决方法:

先准备一个用于进行get以及post请求的类:

class Net(object):    def __init__(self):        self.cookie = cookielib.LWPCookieJar()        self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookie))        self.opener.addheaders = [('User-agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1;\zh-CN; rv:1.9.2.3) #Gecko/20100401 Firefox/3.6.3')]        urllib2.install_opener(self.opener)    def post(self, url, params):        return self.opener.open(urllib2.Request(url, urllib.urlencode(params))).read().decode('u8')        def get(self, url):        try:            return self.opener.open(urllib2.Request(url)).read().decode('u8')        except:            return self.opener.open(urllib2.Request(url)).read()

然后自动注册:

随机生成用户名:

def generateUserName():    table = string.letters + string.digits    return ''.join(random.sample(table, random.randint(10, 15)))

注册:

def register():    n = Net()    name = generateUserName()    pwd = name    url = 'http://www.和谐.com/register'    html = n.get(url)    cpp_code = re.findall('<pre class="brush:(\w+);.*?>(.*?)</pre>', html, re.S)[0]    language = cpp_code[0]    code = cpp_code[1]    code = HTMLParser().unescape(code)    if language == u'python':        answer = pythonAnswer(code)    elif language == u'c':        answer = cppAnswer(code)    else: # javascript        answer = 'true'    if answer == 'error':        print 'javascript'        register()    p = {        'loginname' : name,        'email' : '%s@df.com' % name,        'loginpass' : pwd,        'verifypass' : pwd,        'answer' : answer,        'submit' : '注册'    }    js = eval('u"'+eval(n.post(url, p).replace('true', 'True').replace('false', 'False'))['msg']+'"')    print js    if u'注册成功' in js:        #return name        file('./user-pwd.txt', 'a').write(name + '\n')

下面是得到python以及c代码的运行结果:(Linux下可以使用gcc代码cl)

def pythonAnswer(code):    try:        buf = StringIO()        tmp = sys.stdout        sys.stdout = buf        exec(code)        answer = buf.getvalue().strip()    except:        answer = 'error'    finally:        sys.stdout  = tmp    return answer    def cppAnswer(code):    file('./tmp.cpp', 'w').write(code)    os.system('cl.exe tmp.cpp')    return Popen(['tmp.exe'], stdout=PIPE).communicate()[0].strip()

可以事先注册好多个用户,也可以下载过了10本的时候再注册:

for i in range(20): # 注册20个用户    register()

user-pwd.txt里面将会保存这20个注册成功的用户名

3. 抓包分析

用户登录:

def login():    url = 'http://www.和谐.com/login/'    p = {        'loginname' : name,        'loginpass' : pwd,        'remember' : 'on'        }    if u'退出' in n.post(url, p):        return True

分析要下载的资源的url以及get/post流程:

看到一个下载页面之后,中间有下载地址:

下载地址

“点击获取下载地址”会提示需要输入验证码:

验证码

输入后如下:

地址

至此得到下载地址,具体验证码获取地址可抓包得到。


4. 验证码识别

这个部分已经做好了,可以参见上面笔记一与笔记二的链接。

因为此网站验证码数量很少,而且大多是我们非常熟悉的单词,下面这章图列出了部分由笔记二识别的结果。可以看出仅仅一两百张图片就有好多重复,这个加个单词检查提高识别率,不过在我的试验过程中,效果已经不错,问题就交给电脑吧。

这里是单词图片

5. 下载:

def download(book):    html = n.get(book)    ext = re.findall(u'文件格式:</span>(\w+?)</p>', html)[0]    size = re.findall(u'文件大小:</span>(.*?)</p>', html, re.S)[0]    print size##    if raw_input(u'继续吗:y/n') == 'n':##        return    filename = book.split('/')[-1][:-5] + '.' + ext    filename = urllib.unquote(str(filename))    try:        skey = re.findall('surl="/captcha\?skey=(.*?)"', html)[0]    except:        skey = 'dda032aaedd063e3360b159aef8d54ba'    url = 'http://www.和谐.com/captcha'    try:        png = n.get('http://www.和谐.com/captcha/?skey=%s' % skey)    except:        print u'验证码解析失败\n尝试重新获取中...'        download(book)        return    try:        post_skey = re.findall('name="skey" value="(.*?)"', html)[0]    except:        post_skey = 'UlcENQokUidVMwZtUw9UOwIgBmIOY1M3VjFRbFdvUDE='    file('./captcha.png', 'wb').write(png)    captcha = getCode('captcha.png')    print u'识别出的验证码为: ' + captcha    p = {'captcha' : captcha,         'skey' : post_skey         }    html = n.post(url, p)    msg = eval('u"'+eval(html)['msg']+'"')    if u'为节省服务器资源' in msg:        print msg        return msg    if not 'data' in html:        print u'验证码识别错误\n正在重新获取验证码...\n'        download(book)        return    ftp_url = eval(html)['data'].replace('\/', '/')    print u'验证码正确'    print u'下载地址为:' + ftp_url    print filename    try:        file(filename.decode('u8').encode('gbk'), 'wb').write(n.get(ftp_url))    except:        file("unknow" + '.%s' % ext, 'wb').write(n.get(ftp_url))    print u'下载成功'    time.sleep(999)    return ftp_urldef getNextUser():    for line in file('user-pwd.txt'):        name = line.strip()        print name        yield name

运行:

def main():    for line in file('url.txt'):if not line.startswith('http://'):            continue        name = getNextUser().next()        print name        pwd = name        global n        n = Net(name, pwd)        if not login():            print u'登录失败'            continue        print u'登录成功'        url = line.strip()        thread.start_new_thread(download, (url, ))        time.sleep(2)    if __name__ == '__main__':    main()    while True:        time.sleep(.33)

超过10本时:

换用户名之后正确下载(可以加上自动换用户名,懒得弄了……):



原创粉丝点击