2017-01-19 16 views
0

У меня есть рабочий паук, очищающий URL-адреса изображений и размещение их в поле image_urls scrapy.Item. У меня есть собственный конвейер, который наследуется от ImagesPipeline. Когда определенный URL-адрес возвращает код ответа не-200 http (например, ошибка 401). Например, в лог-файлы, я считаюRetreive http return code from ImagesPipeline (или MediaPipeline) в scrapy

WARNING:scrapy.pipelines.files:File (code: 404): Error downloading file from <GET http://a.espncdn.com/combiner/i%3Fimg%3D/i/headshots/tennis/players/full/425.png> referred in <None> 
WARNING:scrapy.pipelines.files:File (code: 307): Error downloading file from <GET http://www.fansshare.com/photos/rogerfederer/federer-roger-federer-406468306.jpg> referred in <None> 

Однако, я не могу захватить коды ошибок , и т.д. в моем пользовательском трубопроводе изображения в item_completed() функции:

def item_completed(self, results, item, info): 

    image_paths = [] 
    for download_status, x in results: 
     if download_status: 
      image_paths.append(x['path']) 
      item['images'] = image_paths # update item image path 
      item['result_download_status'] = 1 
     else: 
      item['result_download_status'] = 0 
      #x.printDetailedTraceback() 
      logging.info(repr(x)) # x is a twisted failure object 

    return item 

Копаясь через исходный код scrapy, внутри функции media_downloaded() в files.py, я обнаружил, что для кодов ответов, отличных от 200, регистрируется предупреждение (что объясняет приведенные выше строки WARNING), а затем FileException поднял.

if response.status != 200: 
     logger.warning(
      'File (code: %(status)s): Error downloading file from ' 
      '%(request)s referred in <%(referer)s>', 
      {'status': response.status, 
      'request': request, 'referer': referer}, 
      extra={'spider': info.spider} 
     ) 

     raise FileException('download-error') 

Как мне этот ответ код, так что я могу справиться с этим в моем трубопроводе в item_completed функции()?

ответ

1

Если вы не знакомы с асинхронным программированием и Twisted callbacks и errbacks, вы можете легко смутить все эти методы, связанные с медиа-конвейерами Scrapy, поэтому основная идея в вашем случае - перезаписать media_downloaded таким образом, -200 ответ, как это (только быстрый и грязный PoC):

class MyPipeline(ImagesPipeline): 

    def media_downloaded(self, response, request, info): 
     if response.status != 200: 
      return {'url': request.url, 'status': response.status} 
     super(MyPipeline, self).media_downloaded(response, request, info) 

    def item_completed(self, results, item, info): 
     image_paths = [] 
     for download_status, x in results: 
      if download_status: 
       if not x.get('status', False): 
        # Successful download 
       else: 
        # x['status'] contains non-200 response code 
+0

Спасибо за ваш ответ. Но в media_downloaded код состояния всегда 200, поскольку он вызывается только в случае успешной загрузки (я полагаю). Фактически, я пробовал аналогичный подход. Я перегрузил file_downloaded() вместо media_downloaded(), поскольку ImagesPipeline наследует от FilesPipeline, который определяет этот метод. См. Мой подход в http://pastebin.com/bpLKyWYx. Тем не менее, я не вижу коды статуса не-200 в item_completed(). Я думаю, это потому, что, как я упоминал в вопросе, возникает исключение FileException, когда происходят коды статуса не-200. – hAcKnRoCk

+0

Фактически 'media_downloaded' получает любой ответ, а не только 200. Что мы делаем в приведенном выше коде, перезаписываем по умолчанию' media_downloaded', проверяем, не отвечает ли ответ не 200, если да, верните dict с ответом, иначе вызовите родительский метод ImagesPipeline - таким образом, код выше работает для каждого ответа ** перед ** повышением исключения. – mizhgun

+0

Спасибо за руководство. Я понял, что лучший способ состоял в том, чтобы поймать исключение и обработать его вместо вызова супер только для ответов, отличных от 200. Я отправлю свой подход в качестве отдельного ответа, хотя ваше руководство было необходимо для продолжения и выяснения ответа – hAcKnRoCk

0

Правильный путь, чтобы захватить не-200 кодов ответа, кажется, наследуя media_downloaded но назвать родительскую функцию и поймать исключение. Вот код, который работает:

def media_downloaded(self, response, request, info): 
    try: 
     resultdict = super(MyPipeline, self).media_downloaded(response, request, info) 
     resultdict['status'] = response.status 
     logging.warning('No Exception : {}'.format(response.status)) 
     return resultdict 
    except FileException as exc: 
     logging.warning('Caused Exception : {} {}'.format(response.status, str(exc))) 
     return {'url': request.url, 'status': response.status} 

Код ответа может быть обработан внутри item_completed()

def item_completed(self, results, item, info): 
    image_paths = [] 
    for download_status, x in results: 
     if x.get('status', True): 
      item['result_download_status'] = x['status'] # contains non-200 response code 
      if x['status'] == 200: 
       image_paths.append(x['path']) 
       item['images'] = image_paths # update item image path 

 Смежные вопросы

  • Нет связанных вопросов^_^