2012-06-11 16 views
8

Tôi mới sử dụng phần mềm này. Tôi đang viết một con nhện được thiết kế để kiểm tra danh sách dài các url cho mã trạng thái máy chủ và khi thích hợp, chúng sẽ được chuyển hướng đến URL nào. Quan trọng hơn, nếu có một chuỗi các chuyển hướng, tôi cần phải biết mã trạng thái và url ở mỗi bước nhảy. Tôi đang sử dụng response.meta ['redirect_urls'] để ghi lại các url nhưng không chắc chắn cách nắm bắt các mã trạng thái - dường như không có khóa meta phản hồi cho nó.Chụp mã trạng thái http bằng con nhện bị lột

Tôi nhận ra mình có thể cần phải viết một số đồ lót tùy chỉnh để hiển thị các giá trị này nhưng không rõ cách đăng nhập mã trạng thái cho mỗi hop cũng như cách truy cập các giá trị này từ nhện. Tôi đã có một cái nhìn nhưng không thể tìm thấy một ví dụ về bất cứ ai làm điều này. Nếu bất cứ ai có thể chỉ cho tôi đúng hướng nó sẽ được nhiều đánh giá cao.

Ví dụ,

items = [] 
    item = RedirectItem() 
    item['url'] = response.url 
    item['redirected_urls'] = response.meta['redirect_urls']  
    item['status_codes'] = #???? 
    items.append(item) 

Sửa - Dựa trên phản hồi từ warawauk và một số sự giúp đỡ thực sự chủ động từ những kẻ trên kênh IRC (freenode #scrappy) Tôi đã quản lý để làm điều này. Tôi tin rằng đó là một chút hacky vì vậy bất kỳ ý kiến ​​để cải thiện chào đón:

(1) Vô hiệu hoá các middleware mặc định trong các thiết lập, và thêm của riêng bạn:

DOWNLOADER_MIDDLEWARES = { 
    'scrapy.contrib.downloadermiddleware.redirect.RedirectMiddleware': None, 
    'myproject.middlewares.CustomRedirectMiddleware': 100, 
} 

(2) Tạo CustomRedirectMiddleware của bạn trong middlewares của bạn .py. Nó kế thừa từ lớp redirectmiddleware chính và nắm bắt được chuyển hướng:

class CustomRedirectMiddleware(RedirectMiddleware): 
    """Handle redirection of requests based on response status and meta-refresh html tag""" 

    def process_response(self, request, response, spider): 
     #Get the redirect status codes 
     request.meta.setdefault('redirect_status', []).append(response.status) 
     if 'dont_redirect' in request.meta: 
      return response 
     if request.method.upper() == 'HEAD': 
      if response.status in [301, 302, 303, 307] and 'Location' in response.headers: 
       redirected_url = urljoin(request.url, response.headers['location']) 
       redirected = request.replace(url=redirected_url) 

       return self._redirect(redirected, request, spider, response.status) 
      else: 
       return response 

     if response.status in [302, 303] and 'Location' in response.headers: 
      redirected_url = urljoin(request.url, response.headers['location']) 
      redirected = self._redirect_request_using_get(request, redirected_url) 
      return self._redirect(redirected, request, spider, response.status) 

     if response.status in [301, 307] and 'Location' in response.headers: 
      redirected_url = urljoin(request.url, response.headers['location']) 
      redirected = request.replace(url=redirected_url) 
      return self._redirect(redirected, request, spider, response.status) 

     if isinstance(response, HtmlResponse): 
      interval, url = get_meta_refresh(response) 
      if url and interval < self.max_metarefresh_delay: 
       redirected = self._redirect_request_using_get(request, url) 
       return self._redirect(redirected, request, spider, 'meta refresh') 


     return response 

(3) Bây giờ bạn có thể truy cập vào danh sách chuyển hướng trong nhện của bạn với

request.meta['redirect_status'] 
+1

Bạn nên đăng giải pháp của mình làm câu trả lời – raben

Trả lời

2

Tôi tin rằng đó là có sẵn như là

response.status 

Xem http://doc.scrapy.org/en/0.14/topics/request-response.html#scrapy.http.Response

+0

Cảm ơn bạn đã trả lời câu trả lời của bạn. Khó khăn của tôi là cách sử dụng điển hình của response.status cho bạn trạng thái đáp ứng của phản hồi cuối cùng, sau tất cả các chuyển hướng. Tôi cần response.status cho mỗi hop và tôi không rõ ràng về cách nắm bắt tất cả chúng. Điều đó có ý nghĩa? – reportingmonkey

+0

Bạn cũng có thể nối mã trạng thái giống như cách bạn cho là ['redirect_urls'];) –

+0

Ồ tôi hiểu rồi, tôi hiểu lầm. Sau đó, tôi nghĩ bạn cần phân lớp 'scrapy.contrib.spidermiddleware.SpiderMiddleware' theo http://doc.scrapy.org/en/0.14/topics/spider-middleware.html#writing-your-own-spider-middleware và ghi đè 'process_spider_input' để thêm mã trạng thái trung gian vào, ví dụ:' response.meta ['status_codes'] 'sẽ được khởi tạo dưới dạng danh sách trống. Nhưng tôi đã không thử điều này. – lindelof

3

response.meta['redirect_urls' được điền bởi RedirectMiddleware. Gọi lại spider của bạn sẽ không bao giờ nhận được phản hồi ở giữa, chỉ là người cuối cùng sau tất cả các chuyển hướng.

Nếu bạn muốn kiểm soát quy trình, phân lớp RedirectMiddleware, hãy tắt chế độ gốc và kích hoạt máy của bạn. Sau đó, bạn có thể kiểm soát quá trình chuyển hướng, bao gồm theo dõi trạng thái phản hồi.

Đây là việc thực hiện ban đầu (scrapy.contrib.downloadermiddleware.redirect.RedirectMiddleware):

class RedirectMiddleware(object): 
    """Handle redirection of requests based on response status and meta-refresh html tag""" 

    def _redirect(self, redirected, request, spider, reason): 
     ... 
            redirected.meta['redirect_urls'] = request.meta.get('redirect_urls', []) + \ 
                [request.url] 

Như bạn thấy _redirect phương pháp được gọi là từ các bộ phận khác nhau tạo meta['redirect_urls']

Và trong phương pháp process_responsereturn self._redirect(redirected, request, spider, response.status) được gọi, có nghĩa là phản ứng ban đầu không được truyền cho nhện.

+0

Cảm ơn warwaruk, điều đó có ý nghĩa. Tôi đã nhìn vào redirectmiddleware. Tôi nghĩ rằng tôi có thể đảo ngược kỹ sư phần này. Tôi nghĩ rằng tôi vẫn còn thiếu một cái gì đó ở đây mặc dù như lớp này tham khảo request.meta.get ['redirect_urls'] vì vậy tôi nghĩ rằng các giá trị đang được thông qua cho mỗi yêu cầu. Điều này cũng có ý nghĩa, nhưng tôi không thể tìm thấy nơi đó thực sự xảy ra. Tôi sẽ chỉnh sửa bài viết gốc của mình để xem liệu tôi có thể làm rõ nơi tôi đang đấu tranh – reportingmonkey

+0

@ user1449163, phần mềm trung gian này là phần tạo 'meta ['redirect_urls']' - xem cập nhật cho câu trả lời hay không – warvariuc

0

giải pháp KISS: Tôi nghĩ rằng nó là tốt hơn để thêm tối thiểu nghiêm ngặt mã để chụp các lĩnh vực chuyển hướng mới, và để cho RedirectMiddleware làm phần còn lại:

from scrapy.contrib.downloadermiddleware.redirect import RedirectMiddleware 

class CustomRedirectMiddleware(RedirectMiddleware): 
    """Handle redirection of requests based on response status and meta-refresh html tag""" 

    def process_response(self, request, response, spider): 
    #Get the redirect status codes 
    request.meta.setdefault('redirect_status', []).append(response.status) 
    response = super(CustomRedirectMiddleware, self).process_response(request, response, spider) 
    return response 

Sau đó, subclassing BaseSpider, bạn có thể truy cập vào redirect_status với những điều sau đây:

def parse(self, response): 
     item = ScrapyGoogleindexItem() 
     item['redirections'] = response.meta.get('redirect_times', 0) 
     item['redirect_status'] = response.meta['redirect_status'] 
     return item