Ошибка типа: объект ‘NoneType’ не может быть повторен при использовании Scrapy для обхода API

#python #scrapy

Вопрос:

Я пытаюсь начать с этой страницы (https://api.pointsbet.com/api/v2/competitions/7176/events/featured), возьмите ключ и добавьте его в api событий (https://api.pointsbet.com/api/v2/events/) таким образом, я могу получить некоторые данные из api событий, а затем выполнить цикл.

Я получаю ошибку TypeError: объект ‘NoneType’ не может быть повторен, и я понятия не имею, почему.

Заранее спасибо!

 import scrapy
import json


class PbSpider(scrapy.Spider):
    name = 'pb'
    allowed_domains = ['api.pointsbet.com']
    start_urls = ['https://api.pointsbet.com/api/v2/competitions/7176/events/featured']

    def parse(self, response):
        resp = json.loads(response.body)
        events = resp.get('events')

        for event in events:
            eventKey = event.get('key')
            gameapi = f'https://api.pointsbet.com/api/v2/events/{eventKey}'

            if gameapi:

                yield scrapy.Request(url=gameapi, callback=self.parse)

                res = json.loads(response.body)
                fixedOddsMarkets = res.get('fixedOddsMarkets')

                for fixedOddsMarket in fixedOddsMarkets:
                    market = fixedOddsMarket.get('eventName')
                    outcomes = fixedOddsMarket.get('outcomes')

                    for outcome in outcomes:
                        name = outcome.get('name')
                        price = outcome.get('price')

                        print(market, name, price)
 

Комментарии:

1. Скорее всего, вы попытаетесь пройти через какую-то структуру в одном из ваших for циклов, которая ранее не была успешно назначена. Проверьте res outcomes , правильно ли они fixedOddsMarkets назначены или нет, я бы предположил, что один из них ничего не возвращает…

Ответ №1:

Не могли бы вы дать немного больше информации? Я вижу в вашем коде по крайней мере 3 объекта для итераций ( events , fixedOddsMarkets , outcomes ). Какой из них возвращает ошибку?

Ошибка «Нетипичный» объект не может быть повторен означает, что один из ваших методов .get() не смог найти элемент. Чтобы избежать этой ошибки, вы можете добавить второй аргумент в свои методы .get () (это было бы похоже resp.get('events', []) ) или resp.get('events', {}) . Это зависит от структуры вашего json (список или диктант)).

Но если у вас возникли некоторые проблемы с подключением к api (или также неправильно назначен какой — либо объект json) — это не может решить вашу проблему.

Прежде всего, проверьте, является ли код состояния ответа приемлемым (200, А НЕ 400, 403 и т.д.). Вы можете сделать это с print(response.status) помощью своего def parse(self, response) метода).

Если все в порядке, проверьте данные json, которые api возвращает вам непосредственно в коде (вы можете сделать это с print(resp) помощью ). Если на этом шаге у вас есть соответствующий файл json из api (и данные для вас в порядке), проверьте свой код и структуру файла json. fixedOddsMarkets или outcomes должны быть неправильно назначены.


Как я понял, он пытается удалить «события» из вашей ссылки gameapi, верно? Проблема в том, что вы используете «self.parse» в качестве аргумента обратного вызова.

Добавьте другой метод, он должен решить вашу проблему:

 def parse(self, response):
    resp = json.loads(response.body)
    events = resp.get('events')

    for event in events:
        eventKey = event.get('key')
        gameapi = f'https://api.pointsbet.com/api/v2/events/{eventKey}'

        if gameapi:

            yield scrapy.Request(url=gameapi, callback=self.parse_event)
def parse_event(self, response):
    res = json.loads(response.body)
    fixedOddsMarkets = res.get('fixedOddsMarkets')

    for fixedOddsMarket in fixedOddsMarkets:
        market = fixedOddsMarket.get('eventName')
        outcomes = fixedOddsMarket.get('outcomes')

        for outcome in outcomes:
            name = outcome.get('name')
            price = outcome.get('price')

            print(market, name, price)
 

Кроме того, это не очень хороший вариант использовать if gameapi утверждение, так как оно всегда верно. Я думаю, что лучше заменить if gameapi: на if eventKey:

Комментарии:

1. Большое спасибо! Добавление второго аргумента в метод get() разрешило ошибку «Нетип» объекта, не являющуюся повторяемой ошибкой. Проблема, с которой я сейчас сталкиваюсь, заключается в том, что элемент gameapi не отслеживается, а последующие элементы пытаются удалить с исходной страницы. Все ответы — 200, так что все в порядке, и когда я печатаю игровой файл, он работает, поэтому должно быть следующее- это выглядит правильно?

2. @GeordieFrost , попробуйте добавить другой метод. Это должно вам помочь. Для получения дополнительной информации о том, как это сделать, пожалуйста, проверьте мой ответ еще раз. Я обновил его всего минуту назад.

3. Большое вам спасибо, Лоуренс, что отлично сработало! Очень признателен!