Ошибка очистки показывает, когда нет данных для очистки объекта

#python #web-scraping #scrapy

Вопрос:

Я продолжаю получать сообщение об ошибке «Объект’NoneType’ не подлежит подписке», когда запускаю свой скрап-код. Я понимаю, что значение объекта равно None, но как это пропустить и поручить Scrapy записать этот объект как пустой?

Вот метод

 def parse_country(self, response):
    try:

        item = response.meta['item']
        link_id = response.meta['link_id']
        place_data = json.loads(response.body)
        
        place_country = place_data[0][0][0]

        item['place_country'] = place_country

        yield item
    
    except Exception as e:
        print(e)    
 

Ошибка отображается только при отсутствии данных для очистки.

Ответ №1:

Try/except полезно для обнаружения ошибок или ошибок. Я бы предложил if/else решение.

Что-то подобное может сработать для вас:

 def parse_country(self, response):
    item = response.meta['item']
    link_id = response.meta['link_id']
    place_data = json.loads(response.body)                    
                 
    if place_data[0][0][0] is not None:
         place_country = place_data[0][0][0]
         item['place_country'] = place_country
    else
         item['place_country'] = 'No Country found'
    
 

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

1. Он по-прежнему выдает ту же ошибку после использования if/else.

2. каков возможный элемент «нетип»?

3. Это должен быть элемент[‘страна размещения’] = страна размещения

4. если response.body пусто, вы громко получите place_data[0][0][0] = None . Так что вы можете протестировать place_data[0][0][0] в своем if/else состоянии. Я отредактировал свой ответ.

Ответ №2:

Обратите внимание, что использование try блока в качестве управляющего оператора не является хорошей практикой.

Когда вы пишете place_data[0][0][0] , это означает, что вы ищете многоуровневый вложенный список. Решение состоит в том, чтобы проверить наличие None и длину на каждом уровне. Если какой-либо из этих пунктов есть None , у вас возникнет эта ошибка.

Решение состоит в том, чтобы проверить наличие всех этих значений. Вы можете сделать это одним, если утверждение, подобное этому

 if place_data and len(place_data) > 0 
         and place_data[0] and len(place_data[0]) > 0 
         and place_data[0][0] and len(place_data[0][0]) 
         and place_data[0][0][0]:
    item['place_country'] = place_data[0][0][0]
else:
     item['place_country'] = None
 

Или вы можете разбить его на несколько вложенных if операторов для лучшей читаемости.

Примечание № 1: Использование meta не рекомендуется в более новой версии scrapy. Используйте cb_kwargs вместо этого. Посмотрите документы.

Примечание № 2: Вы можете напрямую связаться json по телефону response.json()

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

1. Спасибо за ваш ответ и 2 примечания. Я добавил ниже код, который работает для меня после выполнения многих слепых тестов. Для примечания 2: Вы имеете в виду не использовать json.loads(response.body) ?

Ответ №3:

После многих тестов вот код, который работает для меня

 def parse_images(self, response):
    try:
                   
        link_id = response.meta['link_id']
        place_data = json.loads(response.body)
        item = response.meta['item']
        
        try: 
            place_country = place_data[0][0][0]
        except:
            place_country = ''

        yield {
            'link_id': link_id,
            'place_country': place_country
        }
    except Exception as e:
        print(e)