我试图抓一个要求用户输入搜索值和验证码的网站。我有一个验证码的光学字符识别(OCR)程序,大约33%的时间成功。由于验证码始终是字母文本,因此如果OCR函数返回非字母字符,我想重新加载验证码。一旦我有了文字" word",我想提交搜索表单。
结果返回到同一页面,表单已准备好进行新搜索和新验证码。所以我需要冲洗并重复,直到我的搜索条件用完为止。
这是顶级算法:
我尝试使用管道获取验证码,但后来我没有提供表单提交的价值。如果我只是在不通过框架的情况下获取图像,使用urllib或其他东西,那么会话的cookie就不会被提交,因此服务器上的验证码验证失败。
理想的Scrapy方式是什么?
答案 0 :(得分:11)
这是一个非常深刻的主题,有很多解决方案。但是,如果您想应用您在帖子中定义的逻辑,则可以使用scrapy use a facet。
类似的东西:
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
此示例将拦截每个响应并尝试解决验证码。如果失败,它将重试页面以获取新的验证码,如果成功,它将添加一些元键以响应解决的验证码值。
在你的蜘蛛中你会像这样使用它:
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