Python 刮痧;验证码

Python 刮痧;验证码,python,scrapy,captcha,Python,Scrapy,Captcha,我在网站中使用scrapy提交表单(任何进入页面的链接等) 我的scapy机器人成功登录,但我无法避免验证码。 对于表单提交,我使用scrapy.FormRequest.from\u response frq = scrapy.FormRequest.from_response(response, formdata={'message': 'itttttttt', 'security': captcha, 'name': '

我在网站中使用scrapy提交表单(任何进入页面的链接等)

我的scapy机器人成功登录,但我无法避免验证码。 对于表单提交,我使用scrapy.FormRequest.from\u response

frq = scrapy.FormRequest.from_response(response, formdata={'message': 'itttttttt', 
                                   'security': captcha, 'name': 'fx',
                                   'category_id': '2', 'email': 'ololo%40gmail.com', 'item_id': '216640_2', 'location': '18', 'send_message': 'Send%20Message'
                                   }, callback=self.afterForm)

    yield frq
我想从这个页面加载验证码图像,并手动输入到脚本运行时。 等

我试着

 urllib.urlretrieve(captcha, "./captcha.jpg")
但此方法加载不正确的验证码(站点拒绝我的输入)。我尝试在一个运行脚本中反复调用urllib.urlretieve,每次他返回不同的验证码时:(

之后,我尝试使用ImagePipeline。 但我的问题是,返回项(下载图像)只有在函数执行完毕后才会出现,即使我使用的是yeild

 item = BfsItem()
 item['image_urls'] = [captcha]
 yield item
 captcha = raw_input("put captcha in manually>")  
 frq = scrapy.FormRequest.from_response(response, formdata={'message': 'itttttttt', 
                                   'security': captcha, 'name': 'fx',
                                   'category_id': '2', 'email': 'ololo%40gmail.com', 'item_id': '216640_2', 'location': '18', 'send_message': 'Send%20Message'
                                   }, callback=self.afterForm)
 yield frq
那一刻,当我的脚本请求输入时,图片没有下载

如何在手动输入验证码后修改脚本并调用FormRequest


非常感谢!

我使用的方法通常效果很好,如下所示(只是要点,您需要添加具体细节):

步骤1-获取验证码url(并保留表单的响应以备将来使用)

第2步-现在scrapy将下载图像,我们必须在scrapy回调中正确处理它

def parse_captcha_download(response):
    captcha_target_filename = 'filename.png'
    # save the image for processing
    i = Image.open(StringIO(response.body))
    i.save(captcha_target_filename)

    # process the captcha (OCR, or sending it to a decaptcha service, etc ...)
    captcha_text = solve_captcha(captcha_target_filename)

    # and now we have all the data we need for building the form request
    captcha_form = response.meta['captcha_form']

    return scrapy.FormRequest.from_response(captcha_form, formdata={'message': 'itttttttt', 
                               'security': captcha_text, 'name': 'fx',
                               'category_id': '2', 'email': 'ololo%40gmail.com', 'item_id': '216640_2', 'location': '18', 'send_message': 'Send%20Message'
                               }, callback=self.afterForm)
重要细节

受验证码保护的表单需要某种方式将验证码图像链接到看到并回答此验证码的特定用户/客户端。这通常是使用基于cookie的会话或隐藏在验证码表单中的特殊参数/图像标记来完成的

刮板代码必须小心不要破坏这个链接,否则它将回答一些验证码,但不是它必须回答的验证码

为什么不使用Verz1Lka发布的两个示例?

urllib.urlretrieve方法完全在scrapy之外工作。虽然这通常不是一个好主意(这不会利用scrapys调度等的好处),这里的主要问题是:此请求将完全在目标站点用于跟踪哪个验证码发送到特定浏览器的任何会话cookie、url参数等之外工作


另一方面,使用图像管道的方法在Scrapy的规则中运行良好,但这些图像下载计划在稍后时间完成,因此验证码下载在需要时将不可用。

您正在下载不同的验证码图像,因为您没有使用输入时收到的相同cookied来形成URL。Scrapy自己管理cookies,因此您最好也使用Scrapy来下载图像。

关于cookies,您是对的(参见我的答案),但不是关于使用媒体管道。这不起作用,因为刮板无法在需要时访问下载的验证码图像。嘿@将修复你的刮板,你能帮我解决这个问题吗
def parse_page_with_captcha(response):
    captcha_url = response.xpath(...)
    data_for_later = {'captcha_form': response} # store the response for later use
    return Request(captcha_url, callback=self.parse_captcha_download, meta=data_for_later)
def parse_captcha_download(response):
    captcha_target_filename = 'filename.png'
    # save the image for processing
    i = Image.open(StringIO(response.body))
    i.save(captcha_target_filename)

    # process the captcha (OCR, or sending it to a decaptcha service, etc ...)
    captcha_text = solve_captcha(captcha_target_filename)

    # and now we have all the data we need for building the form request
    captcha_form = response.meta['captcha_form']

    return scrapy.FormRequest.from_response(captcha_form, formdata={'message': 'itttttttt', 
                               'security': captcha_text, 'name': 'fx',
                               'category_id': '2', 'email': 'ololo%40gmail.com', 'item_id': '216640_2', 'location': '18', 'send_message': 'Send%20Message'
                               }, callback=self.afterForm)