2016-03-07 3 views
1

Я запускаю паук Scrapy в python для очистки изображений с веб-сайта. Одно из изображений не загружается (даже если я пытаюсь загрузить его регулярно через сайт), что является внутренней ошибкой для сайта. Это прекрасно, я не забочусь о том, чтобы попытаться получить изображение, я просто хочу пропустить изображение, когда оно не удается, и переместиться на другие изображения, но я продолжаю получать ошибку 10054.Scrapy: Ошибка 10054 после повторного загрузки изображения

> Traceback (most recent call last): File 
> "c:\python27\lib\site-packages\twisted\internet\defer.py", line 588, 
> in _runCallbacks 
>  current.result = callback(current.result, *args, **kw) File "C:\Python27\Scripts\nhtsa\nhtsa\spiders\NHTSA_spider.py", line 137, 
> in parse_photo_page 
>  self.retrievePhoto(base_url_photo + url[0], url_text) File "C:\Python27\Scripts\nhtsa\nhtsa\retrying.py", line 49, in wrapped_f 
>  return Retrying(*dargs, **dkw).call(f, *args, **kw) File "C:\Python27\Scripts\nhtsa\nhtsa\retrying.py", line 212, in call 
>  raise attempt.get() File "C:\Python27\Scripts\nhtsa\nhtsa\retrying.py", line 247, in get 
>  six.reraise(self.value[0], self.value[1], self.value[2]) File "C:\Python27\Scripts\nhtsa\nhtsa\retrying.py", line 200, in call 
>  attempt = Attempt(fn(*args, **kwargs), attempt_number, False) File "C:\Python27\Scripts\nhtsa\nhtsa\spiders\NHTSA_spider.py", line 
> 216, in retrievePhoto 
>  code.write(f.read()) File "c:\python27\lib\socket.py", line 355, in read 
>  data = self._sock.recv(rbufsize) File "c:\python27\lib\httplib.py", line 612, in read 
>  s = self.fp.read(amt) File "c:\python27\lib\socket.py", line 384, in read 
>  data = self._sock.recv(left) error: [Errno 10054] An existing connection was forcibly closed by the remote 

Вот моя функция синтаксического анализа, который смотрит на страницы с фотографией и находит важный URL,:

def parse_photo_page(self, response): 
     for sel in response.xpath('//table[@id="tblData"]/tr'): 
      url = sel.xpath('td/font/a/@href').extract() 
      table_fields = sel.xpath('td/font/text()').extract() 
      if url: 
       base_url_photo = "http://www-nrd.nhtsa.dot.gov/" 
       url_text = table_fields[3] 
       url_text = string.replace(url_text, "&nbsp","") 
       url_text = string.replace(url_text," ","") 
       self.retrievePhoto(base_url_photo + url[0], url_text) 

Вот моя функция загрузки с повторной попытки декоратора:

from retrying import retry 
@retry(stop_max_attempt_number=5, wait_fixed=2000) 
    def retrievePhoto(self, url, filename): 
     fullPath = self.saveLocation + "/" + filename 
     urllib.urlretrieve(url, fullPath) 

Он повторит скачайте 5 раз, но затем выдает ошибку 10054 и не переходит к следующему изображению. Как я могу заставить паука продолжать работу после повторной попытки? Опять же, я не забочусь о загрузке образа проблемы, я просто хочу пропустить его.

+1

Это не рекомендуется смешивать синхронную сеть IO (например, 'urllib.urlretrieve') и асинхронной IO (SCRAPY/скрученный). В любом случае, после 5 попыток, 'self.retrievePhoto (base_url_photo + url [0], url_text)' все равно может вызвать исключение. Вам нужно поймать это в 'try: ... except: ...', если вы хотите продолжить итерации цикла в 'parse_photo_page'. У Scrapy есть ['ImagesPipeline'] (http://doc.scrapy.org/en/latest/topics/media-pipeline.html#using-the-images-pipeline) для асинхронного извлечения изображений. –

+0

Спасибо за комментарий, я пытаюсь реализовать ImagePipeline сейчас ... не могу заставить его работать, я не впечатлен документацией для этого –

+0

@JohnK: вы говорите, что хотите внести свой вклад к проекту с открытым исходным кодом путем совершенствования документации? –

ответ

1

Правильно, что вы не должны использовать urllib внутри scrapy, потому что он блокирует все. Попытайтесь прочитать ресурсы, связанные с «scrapy twisted» и «scrapy асинхронным». Во всяком случае ... Я не верю, что ваша главная проблема заключается в том, что «продолжить после повторной попытки», но не использовать «соответствующие xpaths» в ваших выражениях. Вот версия, которая работает для меня (Обратите внимание на ./ в './td/font/a/@href'):

import scrapy 
import string 
import urllib 
import os 

class MyspiderSpider(scrapy.Spider): 
    name = "myspider" 
    start_urls = (
     'file:index.html', 
    ) 

    saveLocation = os.getcwd() 

    def parse(self, response): 
     for sel in response.xpath('//table[@id="tblData"]/tr'): 
      url = sel.xpath('./td/font/a/@href').extract() 
      table_fields = sel.xpath('./td/font/text()').extract() 
      if url: 
       base_url_photo = "http://www-nrd.nhtsa.dot.gov/" 
       url_text = table_fields[3] 
       url_text = string.replace(url_text, "&nbsp","") 
       url_text = string.replace(url_text," ","") 
       self.retrievePhoto(base_url_photo + url[0], url_text) 

    from retrying import retry 
    @retry(stop_max_attempt_number=5, wait_fixed=2000) 
    def retrievePhoto(self, url, filename): 
     fullPath = self.saveLocation + "/" + filename 
     urllib.urlretrieve(url, fullPath) 

И вот (намного лучше) версия, которая следует ваши шаблоны, но использует ImagesPipeline что @paul trmbrth упоминается.

import scrapy 
import string 
import os 

class MyspiderSpider(scrapy.Spider): 
    name = "myspider2" 
    start_urls = (
     'file:index.html', 
    ) 

    saveLocation = os.getcwd() 

    custom_settings = { 
     "ITEM_PIPELINES": {'scrapy.pipelines.images.ImagesPipeline': 1}, 
     "IMAGES_STORE": saveLocation 
    } 

    def parse(self, response): 
     image_urls = [] 
     image_texts = [] 
     for sel in response.xpath('//table[@id="tblData"]/tr'): 
      url = sel.xpath('./td/font/a/@href').extract() 
      table_fields = sel.xpath('./td/font/text()').extract() 
      if url: 
       base_url_photo = "http://www-nrd.nhtsa.dot.gov/" 
       url_text = table_fields[3] 
       url_text = string.replace(url_text, "&nbsp","") 
       url_text = string.replace(url_text," ","") 
       image_urls.append(base_url_photo + url[0]) 
       image_texts.append(url_text) 

     return {"image_urls": image_urls, "image_texts": image_texts} 

Демо-файл я использую это:

$ cat index.html 
<table id="tblData"><tr> 

<td><font>hi <a href="img/2015/cav.jpg"> foo </a> <span /> <span /> green.jpg  </font></td> 

</tr><tr> 

<td><font>hi <a href="img/2015/caw.jpg"> foo </a> <span /> <span /> blue.jpg  </font></td> 

</tr></table> 
+0

Спасибо alot @neverlastn !! Я согласен с тем, что конвейер изображений - это путь. Вчера я пытался внедрить трубопровод и не мог заставить его работать. Этот маленький фрагмент для custom_settings сделал это для меня, я думаю, что мой файл settings.py не был правильно привязан. Опять же, спасибо за ваш полный ответ. –

+0

Добро пожаловать! :) Я думаю, что 'settings.py' - правильный способ сделать это. 'custom_settings' немного взломан - не очень чистый! Я просто поставил его там, чтобы иметь простой автономный ответ. – neverlastn

+0

«реализовать трубопровод» - это очень сложно. Не забудьте всегда google для «любого искаженного», когда вы хотите найти, как делать что угодно. Scrapy - это приложение Twisted, и если вы не используете методы Twisted (например, «urllib»), ваша производительность будет страдать. Здесь есть несколько примеров: https: // github.com/scalingexcellence/scrapybook/tree/master/ch09/свойства/свойства/трубопроводы – neverlastn

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