如何设置Scrapy来处理验证码

Sus*_*hil 15 python captcha scrapy web-scraping

我正在尝试抓一个网站,要求用户输入搜索值和验证码.我有一个验证码的光学字符识别(OCR)程序,大约33%的时间成功.由于验证码始终是字母文本,因此如果OCR函数返回非字母字符,我想重新加载验证码.一旦我有一个文字"单词",我想提交搜索表单.

结果返回到同一页面,表单已准备好进行新搜索和新的验证码.所以我需要冲洗并重复,直到我的搜索条件用完为止.

这是顶级算法:

  1. 最初加载页面
  2. 下载验证码图像,通过OCR运行它
  3. 如果OCR没有返回纯文本结果,请刷新验证码并重复此步骤
  4. 使用搜索词和验证码在页面中提交查询表单
  5. 检查响应以查看验证码是否正确
  6. 如果是正确的,请抓取数据
  7. 转到2

我已经尝试使用管道获取验证码,但后来我没有表单提交的价值.如果我只是在不通过框架的情况下获取图像,使用urllib或其他东西,那么会话的cookie就不会被提交,因此服务器上的验证码验证失败.

什么是理想的Scrapy方式?

Gra*_*rus 11

这是一个非常深刻的主题与一堆解决方案.但是如果你想应用你在帖子中定义的逻辑,你可以使用scrapy Downloader Middlewares.

就像是:

class CaptchaMiddleware(object):
    max_retries = 5
    def process_response(request, response, spider):
        if not request.meta.get('solve_captcha', False):
            return response  # only solve requests that are marked with meta key
        catpcha = find_catpcha(response)
        if not captcha:  # it might not have captcha at all!
            return response
        solved = solve_captcha(captcha)
        if solved:
            response.meta['catpcha'] = captcha
            response.meta['solved_catpcha'] = solved
            return response
        else:
            # retry page for new captcha
            # prevent endless loop
            if request.meta.get('catpcha_retries', 0) == 5:
                logging.warning('max retries for captcha reached for {}'.format(request.url))
                raise IgnoreRequest 
            request.meta['dont_filter'] = True
            request.meta['captcha_retries'] = request.meta.get('captcha_retries', 0) + 1
            return request
Run Code Online (Sandbox Code Playgroud)

此示例将拦截每个响应并尝试解决验证码.如果失败,它将重试页面以获取新的验证码,如果成功,它将添加一些元键以响应解决的验证码值.
在你的蜘蛛中,你会像这样使用它:

class MySpider(scrapy.Spider):
    def parse(self, response):
        url = ''# url that requires captcha
        yield Request(url, callback=self.parse_captchad, meta={'solve_captcha': True},
                      errback=self.parse_fail)

    def parse_captchad(self, response):
        solved = response['solved']
        # do stuff

    def parse_fail(self, response):
        # failed to retrieve captcha in 5 tries :(
        # do stuff
Run Code Online (Sandbox Code Playgroud)

  • 您尚未定义任何 find_catpcha() 和solve_captcha() 函数。是库函数还是自定义函数? (3认同)
  • @Priyanshgupta,这是你必须自己定义的东西,因为这些函数将超出 stackoverflow 问题的范围。 (3认同)
  • 您能列举一些“一系列解决方案”吗?除了 scrapy``下载器中间件````。 (2认同)