2016-04-06 5 views
0

Das folgende ist mein scrapy Code:Wie mit einem sehr großen Attribut "allowed_domains" in Scrapy arbeiten?

def get_host_regex(self, spider): 
    """Override this method to implement a different offsite policy""" 
    allowed_domains = getattr(spider, 'allowed_domains', None) 
    if not allowed_domains: 
     return re.compile('') # allow all by default 
    regex = r'^(.*\.)?(%s)$' % '|'.join(re.escape(d) for d in allowed_domains if d is not None) 
    return re.compile(regex) 

def spider_opened(self, spider): 
     self.host_regex = self.get_host_regex(spider) 
     self.domains_seen = set() 

Da die allowed_domains sehr groß ist, ist es diese Ausnahme auslöst:

regex = r'^(.*.)?(%s)$' % '|'.join(re.escape(d) for d in allowed_domains if d is not None)

Wie löse ich dieses Problem?

+0

Welche Ausnahme erhalten Sie? Wie lange ist die Domain-Liste? –

+0

flow exception: OverflowError: Die Größe des Code-Limits für reguläre Ausdrücke wurde überschritten, und aus dem Quellcode weiß ich 'regex = r'^(. *.)? (% S) $ '%' | '.join (re.escape (d) für d in allowed_domains, wenn d nicht ist) das Problem verursachen. Ich habe fünfzigtausend Domains – rowele

+0

Müssen Sie wirklich Anfragen nur auf diese 50'000 Domains beschränken, und nichts außerhalb dieser Liste? Sonst wäre es besser, wenn Sie 'allow_domains' nicht definieren, da dies jede Domain erlaubt. –

Antwort

1

Sie können Ihre eigene OffsiteMiddleware Variante erstellen, mit einer anderen Implementierung, die Anforderungen an Domänen überprüft, die nicht in der Spider allowed_domains sind.

Zum Beispiel, fügen Sie diese in einer middlewares.py Datei,

from scrapy.spidermiddlewares.offsite import OffsiteMiddleware 
from scrapy.utils.httpobj import urlparse_cached 


class SimpleOffsiteMiddleware(OffsiteMiddleware): 

    def spider_opened(self, spider): 
     # don't build a regex, just use the list as-is 
     self.allowed_hosts = getattr(spider, 'allowed_domains', []) 
     self.domains_seen = set() 

    def should_follow(self, request, spider): 
     if self.allowed_hosts: 
      host = urlparse_cached(request).hostname or '' 
      # does 'www.example.com' end with 'example.com'? 
      # test this for all allowed domains 
      return any([host.endswith(h) for h in self.allowed_hosts]) 
     else: 
      return True 

und Ihre Einstellungen ändern, um die Standard-OffsiteMiddleware zu deaktivieren, und fügen Sie folgende Aufgaben:

SPIDER_MIDDLEWARES = { 
    'scrapy.spidermiddlewares.offsite.OffsiteMiddleware': None, 
    'myproject.middlewares.SimpleOffsiteMiddleware': 500, 
} 

Warnung: Diese Middleware nicht getestet. Dies ist eine sehr naive Implementierung, definitiv nicht sehr effizient (Testen der String-Aufnahme für jede von 50'000 möglichen Domains für jede Anfrage). Sie könnten ein anderes Backend verwenden, um die Liste zu speichern und einen Hostnamen-Wert zu testen, wie zum Beispiel sqlite.

+0

Was bedeutet 'host_list', wenn ich rufe Sie implementiert Offsitemiddle, geben Fehler, 'SimpleOffsiteMiddleware' Objekt hat kein Attribut 'host_list' – rowele

+0

Sorry, Code wurde nicht getestet, es sollte 'allowed_hosts' sein –

+0

es funktioniert gut, aber ich willst du wissen ob es rausfiltert nicht zu allowed_domains gehört? Außerdem ist die Effizienz sehr gut? denke du. – rowele

Verwandte Themen