2017-01-19 14 views
0

이미지 URL을 긁어내어 scrapy.Item의 image_urls 필드에 배치하는 작업 스파이더가 있습니다. ImagePipeline에서 상속받은 사용자 지정 파이프 라인이 있습니다. 특정 URL이 200이 아닌 HTTP 응답 코드 (예 : 401 오류)를 반환 할 때ImagesPipeline (또는 MediaPipeline)의 치료 중 유령 반환 코드

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 
: 예를 들어, 로그 파일에, 나는 item_completed() 기능에서 내 사용자 지정 이미지 파이프 라인에서, 나는 오류 코드 (404)를 캡처 할 수없는 나는, 그러나 등

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> 

을 찾을 수

files.py에있는 media_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을 응답 상태로 돌려줍니다. 그렇지 않으면 parent 메소드를 호출합니다. ImagesPipeline - 따라서 예외를 발생시키기 전에 모든 응답 **에 대해 위의 코드가 실행됩니다. – mizhgun

+0

감사합니다. 가장 좋은 방법은 예외를 잡아서 non-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