@Bjornie
Изучаю Python

Как посчитать кол-во раз посещения страницы в Scrapy?

Ниже привел пример рабочего кода, в котором я хочу реализовать лимит разгадываемых каптч. На данный момент, даже после удачной каптчи иногда Amazon вновь отдает страницу с каптчей. Иногда это происходит 15-20 раз. Я не сумел понять причину этого, т.к. отгадывание каптчи в большинстве своем работает нормально (deathbycaptcha) поэтому для таких АЗИН решил сделать лимит.
Но как определить, что данный url (или asin) уже были у "гадалки"? Я попробовал несколько вариантов насколько хватило моих знаний Питона и смекалки, но не пришел к нужному результату. Подскажите, что можно сделать в моем случае? Как заставить две функции parse_item и get_captcha хранить состояние?
Пример кода привожу ниже:
spoiler
class AmazonproductspiderSpider(scrapy.Spider):
# Читаю файл с ASIN, вызываю parse_item через коллбэк.
def start_requests(self):
        with open('asin.txt') as file:
            for i in file:
                if len(i) > 1:
                        yield scrapy.Request(
                            url='%s/gp/product/%s/' % (self.AMAZON_DOMAIN, asin_from_file),
                            callback=self.parse_item,
                            meta={
                                'asin_from_file': asin_from_file,
                                'country': self.country,
                            }
                        )
    def parse_item(self, response):
        captcha_form = response.xpath('//form[@action="/errors/validateCaptcha"]')
        # Если в респонсе найдена каптча, то срабатывает дальнейший блок кода и вызывается get_captcha
        if captcha_form:
            captcha_img = captcha_form.xpath('.//img/@src').extract_first()
            yield scrapy.Request(
                url=captcha_img,
                callback=self.get_captcha,
                dont_filter=True,
                meta={
                    'callback': self.parse_item,
                    'resp': response,
                    'proxy': response.meta['proxy']
                })
        else:
        # Иначе работает дальше и нужные мне поля передаются дальше в пайплайны по цепочке (Все ОК)
        pass
    # Разгадка каптчи, здесь все работает как нужно. Но хочется ввести лимит на кол-во каптч для одного АЗИН.
    def get_captcha(self, response):
        client = deathbycaptcha.SocketClient(self.DBC_USER, self.DBC_PWD)
        captcha_file = response.body
        try:
            balance = client.get_balance()
            captcha = client.decode(captcha_file, type=2)
            if captcha:
                print("[%s] CAPTCHA %s solved: %s" % ('url', captcha["captcha"], captcha["text"]))
                if '': # check if the CAPTCHA was incorrectly solved
                    client.report(captcha["captcha"])

            yield scrapy.FormRequest.from_response(
                response.meta['resp'],
                formdata={'field-keywords': captcha["text"]},
                callback=response.meta['callback'],
                dont_filter=True,
                meta={
                    'proxy': response.meta['proxy']
                })
            return
        except deathbycaptcha.AccessDeniedException:
            print("error: Access to DBC API denied, check your credentials and/or balance")
  • Вопрос задан
  • 323 просмотра
Пригласить эксперта
Ответы на вопрос 1
@kzoper
class AmazonproductspiderSpider(scrapy.Spider):
visited_urls = {}
# Читаю файл с ASIN, вызываю parse_item через коллбэк.
def start_requests(self):

........

    def parse_item(self, response):
        captcha_form = response.xpath('//form[@action="/errors/validateCaptcha"]')
        # Если в респонсе найдена каптча, то срабатывает дальнейший блок кода и вызывается get_captcha
        if captcha_form:
             visited_urls[response.url] += 1
            if visited_urls[response.url] < 2:
                captcha_img = captcha_form.xpath('.//img/@src').extract_first()
                yield scrapy.Request(
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы