2015-01-06 15 views

Trả lời

8

Phế liệu không cung cấp bất kỳ thứ gì như thế này. Bạn có thể set the DEPTH_LIMIT per-spider, nhưng không phải trên mỗi miền.

Chúng ta có thể làm gì? Read the code, uống cà phê và giải quyết nó (thứ tự quan trọng).

Ý tưởng là tắt tính năng tích hợp sẵn DepthMiddlewareprovide our custom one của Scrapy.

Trước tiên, hãy xác định cài đặt:

  • DOMAIN_DEPTHS sẽ là một cuốn từ điển với giới hạn chiều sâu cho mỗi tên miền
  • DEPTH_LIMIT thiết lập chúng tôi sẽ để lại như một mặc định một trong trường hợp một miền không được cấu hình

Cài đặt mẫu:

DOMAIN_DEPTHS = {'amazon.com': 1, 'homedepot.com': 4} 
DEPTH_LIMIT = 3 

Được rồi, bây giờ middleware tùy chỉnh (dựa trên DepthMiddleware):

from scrapy import log 
from scrapy.http import Request 
import tldextract 


class DomainDepthMiddleware(object): 
    def __init__(self, domain_depths, default_depth): 
     self.domain_depths = domain_depths 
     self.default_depth = default_depth 

    @classmethod 
    def from_crawler(cls, crawler): 
     settings = crawler.settings 
     domain_depths = settings.getdict('DOMAIN_DEPTHS', default={}) 
     default_depth = settings.getint('DEPTH_LIMIT', 1) 

     return cls(domain_depths, default_depth) 

    def process_spider_output(self, response, result, spider): 
     def _filter(request): 
      if isinstance(request, Request): 
       # get max depth per domain 
       domain = tldextract.extract(request.url).registered_domain 
       maxdepth = self.domain_depths.get(domain, self.default_depth) 

       depth = response.meta.get('depth', 0) + 1 
       request.meta['depth'] = depth 

       if maxdepth and depth > maxdepth: 
        log.msg(format="Ignoring link (depth > %(maxdepth)d): %(requrl)s ", 
          level=log.DEBUG, spider=spider, 
          maxdepth=maxdepth, requrl=request.url) 
        return False 
      return True 

     return (r for r in result or() if _filter(r)) 

Lưu ý rằng nó đòi hỏi tldextract module để được cài đặt (được sử dụng để trích xuất một tên miền từ url):

>>> import tldextract 
>>> url = 'http://stackoverflow.com/questions/27805952/scrapy-set-depth-limit-per-allowed-domains' 
>>> tldextract.extract(url).registered_domain 
'stackoverflow.com' 

Bây giờ chúng ta cần để tắt phần mềm trung gian mặc định và sử dụng phần mềm trung gian mặc định và sử dụng phần mềm trung gian mà chúng tôi đã triển khai:

SPIDER_MIDDLEWARES = { 
    'myproject.middlewares.DomainDepthMiddleware': 900, 
    'scrapy.contrib.spidermiddleware.depth.DepthMiddleware': None 
} 
+0

Làm thế nào để tldextract khác với gói python phổ biến hơn 'tld'? –

+2

@FredericBazin Tôi không chắc chắn lắm, chưa so sánh chúng. Tôi nghĩ ở đây nó không quan trọng lắm. Bạn có thể sử dụng bất kỳ một trong số chúng, hoặc thậm chí giải quyết nó với 'urlparse()' có một hàm 'extract_domain()' tùy chỉnh. Cảm ơn. – alecxe

+0

Cảm ơn bạn đã giải thích tuyệt vời! Nên 'response.meta ['depth'] = 0' ở trên' depth = response.meta ['depth'] + 1' Khác, 'response.meta ['depth']' rỗng và sẽ đưa ra một keyerror –

Các vấn đề liên quan