2017-01-19 9 views
0

image URLをスクラップしてscrapy.Itemのimage_urlsフィールドに配置している作業スパイダーがあります。私はImagesPipelineから継承したカスタムパイプラインを持っています。特定のURLが非httpのhttp応答コード(401エラーなど)を返すとき。例えば、ログファイルに、私はitem_completed()機能の私のカスタムイメージパイプラインにImagesPipeline(またはMediaPipeline)のスキャンで取得したhttpリターンコード

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> 

しかし、私はエラーコードをキャプチャすることができません、などを見つける:

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 

files.pymedia_downloaded()機能の中で治療ソースコードを調べると、200個以外の応答コードの場合、警告が記録され(上記の警告行について説明しています)、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

非同期プログラミングとツイスト・コールバックとエラー・バックに精通していない場合は、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です(私はそうです)。実際、私は同様のアプローチを試みました。 ImagesPipelineはこのメソッドを定義するFilesPipelineから継承するため、media_downloaded()ではなくfile_downloaded()をオーバーロードしました。私のアプローチはhttp://pastebin.com/bpLKyWYxをご覧ください。しかし、私はitem_completed()に200以外のステータスコードが表示されません。私はその質問で言及したように、200個以外のステータスコードが発生した場合にFileExceptionが発生するので、私はそれを考えています。 – hAcKnRoCk

+0

実際には 'media_downloaded'は200だけでなくレスポンスも受け取ります。上記のコードでは、デフォルトの' media_downloaded'を上書きし、レスポンスが200でない場合にチェックし、そうであればレスポンスステータスでdictを返します。 ImagesPipeline - 上記のコードは**例外が発生する前のすべてのレスポンス**に対して実行されます。 – mizhgun

+0

ガイダンスに感謝します。最善の方法は、例外をキャッチし、200以外のレスポンスに対してのみsuperを呼び出す代わりにそれを処理することでした。あなたの指針は、進んで答えを見つけ出すためには不可欠ではあるが、私のアプローチを別の答えとして掲示する – 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 
関連する問題