现在的位置: 首页 > 综合 > 正文

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

2013年10月09日 ⁄ 综合 ⁄ 共 4282字 ⁄ 字号 评论关闭

新博客地址: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_url

def 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本时:

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

抱歉!评论已关闭.