OCR识别通过某瓣人机验证

本篇文章将带你使用ocr识别通过人机验证码

豆瓣很骚,莫名其妙就总会出来人机验证,用了代理也过不去,感觉是通过cookies识别你是否为爬虫,一识别就出404弹个人机验证,为了防止爆人机,也想了很多方法,随机ip,随机ua,延时,能试的都试了,看过有些大佬是在爆人机之后就清空cookie,不使用cookie请求然后拿到最新的cookie,一直重复此步骤,太麻烦了!咱们直接暴力干验证码。2e347d601ab241e48215e7aff27fbecd.png

 现在ocr识别的很多,国内就有大佬弄了用于识别验证码,我们直接用大佬造好的轮子就好啦,ddddocr,支持后期训练提高精度,还是非常好用的。

先正常的写程序,我们这里直接干电影区,爬电影的标题分类还有id啥的,趁他不注意先白嫖一波数据。非常的奇怪,只爬首页倒是不人机我了,但是经常爆一个gbk编码错误的错不知道是什么原因,咱们再多爬点试试。 

abcd7651e9364cac8960415c211b4205.png

来了来了!!!!

f5418d286bd7411db4429882e4ddad81.png

被人机检测的时候就会给我们返回403,404的状态码,接着开始进入我们的正题,该如何通过验证码?

1. 解析网页,获取图片验证码 

        这里我们之前已经写好了,直接把注释解掉用就行,就是使用xpath把验证码图片提取出来然后保存至本地就行,豆瓣的人机验证url永远都是这一个https://www.douban.com/misc/sorry?original-url=https%3A%2F%2Fmovie.douban.com%2Fsubject%2F33418682%2F

后面的subject参数可以不要,直接丢弃。注意请求人机验证页面时记得把之前使用的cookie带上。

随机填入123456看看是哪个发送了表单进行验证,初次猜测是这一个,我们自行手动发包看看,直接把表单里的参数都扣下来。,然后把验证码captcha-solution参数修改成和图片一样的验证码,提交请求。

054b8eb3b0c049e89e92a945812fc224.png

发现还是和原来一样,验证未通过,证明我们的表单参数不正确,咱们再看一下 

1b50f864bca44ee782669ef0371015fa.png

这里很明显,豆瓣不止验证了captcha-solution这个参数,同时还验证了captcha-id,这俩个参数都和加载出来的图片有关系,captcha-solution我们能够确定是图片中的验证码,那captcha-id是啥呢?在这边包之前并未返回其他的包,所以可以基本肯定这个参数是在某个小黑屋加密后返回的值。

7adfef7b8b2e487f8e80e6bdb791191a.png

Other ?

7375ff6e41af44143d08bfbb388de9ed.jpeg

 看到other我们直接去前端页面的代码里头找,绝对能找到加密的位置,直接复制这个url后边的尾缀misc/sorry到前端代码搜索去,不搜不知道,一搜吓一跳!

2d81da2430f044d987db593ca219b268.png

这是什么xdm ,直接能拿到数值,太爱豆瓣了

75c672720af59f8ab625ca7d7b8b39f9.png

 这和git的登入一模一样哇,相信弄过github的模拟登入都知道。直接把这个值用xpath扣下来,填到我们的表单当中,发送请求!!!

acea4153194a46be8cbc39d72758af81.png

这下直接跳出验证码的页面了,给我返回了个登入页面的信息。我们去网站手动刷新看看是否已经跳出人机验证的页面了。

1436cccc71c24d24ba12f074d18dad44.png

没有任何问题,那我们在运行之前的代码呢?

89f13f9ce93b473f9007d04e7aaec5f3.png 也是没有任何问题的!现在我们基本的思路已经了解了,但是我们刚刚是手动模拟的获取验证码发包请求,接下来我们将配合ddddocr识别图片中的验证码然后填入表单当中 。 

2. 保存验证码图片配合ocr识别出图中的验证码

pip install ddddocr  

老方法,先下载ddddocr,我们先需要了解这个ddddocr该如何使用,这里先从豆瓣那下载一张验证码至本地,我们去试试识别的精度如何。

import ddddocr
ocr = ddddocr.DdddOcr()
with open('captcha.jpg', 'rb') as f:
    img_bytes = f.read()
code = ocr.classification(img_bytes)
print(code)

663cb373627a456ab4fcbaf917292641.png

 还是非常的牛,识别的精度非常高,我们套入我们的程序当中试试。

# -*- coding: utf-8 -*-
import parsel
import requests
import time
import json
import jsonpath
import pprint
import random
from fake_useragent import UserAgent
import logging
import ddddocr


class douban:
    def get_response(self, url):
        headers = {
            'Referer': 'https://movie.douban.com/',
            'Cookie': 'bid=c3hhB5BZTeE; ll="118311"; __utmc=30149280; __utmc=223695111; Hm_lvt_eaa57ca47dacb4ad4f5a257001a3457c=1659264694; push_noty_num=0; push_doumail_num=0; _vwo_uuid_v2=D3E63167E67E933D563C28FE20D40D966|e5620e84ad8118c0437e96a4f2d8e662; __utmv=30149280.25709; ct=y; dbcl2="257094860:4ts0vmOwNK8"; ck=48vN; __gads=ID=944a8ab8e3222a77-22c156a667d500ed:T=1659339507:RT=1659339507:S=ALNI_MbLs_abyRgTlqyBhLduonUlCgbiNw; __gpi=UID=00000825b9ac2801:T=1659339507:RT=1659339507:S=ALNI_MbJSf4zVEN8KzWJexZpvYLYydg73A; __utma=30149280.1742231113.1659264694.1659339501.1659339785.11; __utmz=30149280.1659339785.11.11.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; _pk_ref.100001.4cf6=%5B%22%22%2C%22%22%2C1659350491%2C%22https%3A%2F%2Fwww.douban.com%2Fmisc%2Fsorry%3Foriginal-url%3Dhttps%253A%252F%252Fmovie.douban.com%252F%22%5D; _pk_ses.100001.4cf6=*; __utma=223695111.524410821.1659264694.1659339785.1659350491.12; __utmb=223695111.0.10.1659350491; __utmz=223695111.1659350491.12.12.utmcsr=douban.com|utmccn=(referral)|utmcmd=referral|utmcct=/misc/sorry; __utmb=30149280.36.10.1659339785; _pk_id.100001.4cf6=0d61f344e82c2272.1659264694.9.1659351438.1659347955.; Hm_lpvt_eaa57ca47dacb4ad4f5a257001a3457c=1659351438',
            'user-agent': UserAgent().random
        }
        try:
            response = requests.get(url=url, headers=headers)
            if response.status_code in [403, 404]:
                logging.debug('Request Error {} {}'.format(response.status_code, url))
                logging.info('try to get verification code...')
                douban().get_code()
            if response.status_code == 200:
                logging.info('Msg from <{} {}>'.format(response.status_code, url))
                time.sleep(random.uniform(0.5, 1))
                if response:
                    return response.text
                else:
                    pass
        except Exception as e:
            logging.debug(e)

    def get_data(self, page):
        try:
            response = douban().creat_url(page)
            json_data = json.loads(response)
            title = jsonpath.jsonpath(json_data, '$..title')
            score = jsonpath.jsonpath(json_data, '$..rate')
            id = jsonpath.jsonpath(json_data, '$..id')
            for i in range(len(title)):
                dic = {
                    'title': title[i],
                    'score': score[i],
                    'id': id[i]
                }
                detail_dic = douban().get_detail_data(id[i])
                dic.update(detail_dic)
                print(str(dic).replace(',', ',\n'))
        except Exception as e:
            logging.debug(e)

    def get_detail_data(self, id):
        url = f'https://movie.douban.com/subject/{id}/'
        detail_response = douban().get_response(url)
        selector = parsel.Selector(detail_response)
        type = selector.xpath('//*[@property="v:genre"]/text()').getall()
        release_date = selector.xpath('//*[@property="v:initialReleaseDate"]/text()').get()
        evaluate_num = selector.xpath('//*[@class="rating_people"]/span/text()').get()
        short_comment_num = selector.xpath('//*[@class="mod-hd"]/h2/span/a/text()').get()
        detail_dic = {
            'type': ' / '.join(type),
            'release_date': release_date,
            'evaluate_num': evaluate_num,
            'short_comment_num': short_comment_num
        }
        return detail_dic

    def creat_url(self, page):
        url = f'https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start={page}'
        return douban().get_response(url)

    def get_code(self):
        code_url = 'https://www.douban.com/misc/sorry?original-url=https%3A%2F%2Fmovie.douban.com%2F'
        headers = {
            'Cookie': 'bid=c3hhB5BZTeE; ll="118311"; __utmc=30149280; __utmc=223695111; Hm_lvt_eaa57ca47dacb4ad4f5a257001a3457c=1659264694; push_noty_num=0; push_doumail_num=0; _vwo_uuid_v2=D3E63167E67E933D563C28FE20D40D966|e5620e84ad8118c0437e96a4f2d8e662; __utmv=30149280.25709; ct=y; dbcl2="257094860:4ts0vmOwNK8"; ck=48vN; __gads=ID=944a8ab8e3222a77-22c156a667d500ed:T=1659339507:RT=1659339507:S=ALNI_MbLs_abyRgTlqyBhLduonUlCgbiNw; __gpi=UID=00000825b9ac2801:T=1659339507:RT=1659339507:S=ALNI_MbJSf4zVEN8KzWJexZpvYLYydg73A; __utma=30149280.1742231113.1659264694.1659339501.1659339785.11; __utmz=30149280.1659339785.11.11.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; _pk_ref.100001.4cf6=%5B%22%22%2C%22%22%2C1659350491%2C%22https%3A%2F%2Fwww.douban.com%2Fmisc%2Fsorry%3Foriginal-url%3Dhttps%253A%252F%252Fmovie.douban.com%252F%22%5D; _pk_ses.100001.4cf6=*; __utma=223695111.524410821.1659264694.1659339785.1659350491.12; __utmb=223695111.0.10.1659350491; __utmz=223695111.1659350491.12.12.utmcsr=douban.com|utmccn=(referral)|utmcmd=referral|utmcct=/misc/sorry; __utmb=30149280.36.10.1659339785; _pk_id.100001.4cf6=0d61f344e82c2272.1659264694.9.1659351438.1659347955.; Hm_lpvt_eaa57ca47dacb4ad4f5a257001a3457c=1659351438',
            'User-Agent': UserAgent().random
        }
        code_res = requests.get(url=code_url, headers=headers).text
        selector = parsel.Selector(code_res)
        captcha_id = selector.xpath('//*[@name="captcha-id"]/@value').get()
        code_pic = selector.xpath('//*[@action="/misc/sorry"]/img/@src').get()
        logging.info(captcha_id)
        img_data = requests.get(url=code_pic, headers=headers).content
        with open('captcha\\captcha.jpg', mode='wb') as f:
            f.write(img_data)
            time.sleep(1)
            logging.info('captcha dowmload success: %s', captcha_id)
            f.close()
        captcha_code = douban().get_captcha_code()
        data = {
            'ck': '48vN',
            'captcha-solution': captcha_code,
            'captcha-id': captcha_id,
            'original-url': 'https://movie.douban.com/',
        }
        # try:
        captcha_response = requests.post(url=code_url, headers=headers, data=data)
        if captcha_response.status_code == 200:
            logging.info('success pass human verification')
        else:
            logging.debug('validation error, will try again...')
        # except Exception as e:
        #     logging.debug(e)

    def get_captcha_code(self):
        ocr = ddddocr.DdddOcr()
        with open('captcha\\captcha.jpg', 'rb') as f:
            img_bytes = f.read()
        code = ocr.classification(img_bytes)
        logging.info('captcha code is: %s', code)
        time.sleep(1)
        return code

    def main(self):
        logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(message)s')
        [douban().get_data(page) for page in range(0, 200 * 20, 20)]

if __name__ == '__main__':
    douban().main()

识别的精度非常的高,测试了两三次人机都通过了,这下可以安安心心的采豆瓣了,不要因为有了验证码识别就疯狂采集不加延时,豆瓣对于请求过多次数的ip还是会封禁一段时间的,当然配合ip代理池使用会更香些。合理使用爬虫早已成为每个爬虫程序猿的基本守则,切忌使用爬虫进行非法交易。

f651bb0719be819a1e39b196dcf46c1f.jpeg

不知道为啥加入ocr识别后爆人机的次数少了,在测试的过程当中好久都没看到403和404。

仍有代码不足之处,大佬们自行修改。

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值