2014-02-27 10 views
17

Ich habe es schwer zu verstehen, Scrapy Crawl Spider-Regeln. Ich habe ein Beispiel, das nicht so funktioniert, wie ich es möchte, so kann es zwei Dinge sein:Wie funktionieren Scrapy-Regeln mit Crawl Spider

  1. Ich verstehe nicht, wie Regeln funktionieren.
  2. Ich bildete falsche Regex, die mich daran hindert, Ergebnisse zu bekommen, die ich brauche.

OK hier ist es, was ich tun möchte:

ich kriechen Spinne schreiben wollen, die alle verfügbaren Statistiken Informationen von http://www.euroleague.net Website erhalten. Die Website-Seite, die alle Informationen enthält, die ich für den Start benötige, ist here.

Schritt 1

Erster Schritt, was ich denke ist „Jahreszeiten“ Verknüpfung (en) extrahieren und es brach. Hier ist es HTML/href, dass ich beabsichtige zu entsprechen (Ich möchte alle Links in der "Seasons" Abschnitt eins nach dem anderen übereinstimmen, aber ich denke, dass es einfacher ist, einen Link als Beispiel zu haben):

href="/main/results/by-date?seasoncode=E2001" 

Und hier ist eine Regel/regex, die ich für sie erstellt:

Rule(SgmlLinkExtractor(allow=('by-date\?seasoncode\=E\d+',)),follow=True), 

enter image description here

Schritt 2

Wenn ich von Spinne auf die Webseite http://www.euroleague.net/main/results/by-date?seasoncode=E2001 für den zweiten Schritt gebracht werde, möchte ich diese Spinne extrahiert Link (s) aus Abschnitt "Regular Season". In diesem Fall sagen wir, es sollte "Runde 1" sein. Die HTML/href, die ich suche ist:

<a href="/main/results/by-date?seasoncode=E2001&gamenumber=1&phasetypecode=RS" 

Und Regel/regex, die ich gebaut wäre:

Rule(SgmlLinkExtractor(allow=('seasoncode\=E\d+\&gamenumber\=\d+\&phasetypecode\=\w+',)),follow=True), 

enter image description here

Schritt 3

Now I erreichte Seite (http://www.euroleague.net/main/results/by-date?seasoncode=E2001&gamenumber=1&phasetypecode=RS) Ich bin bereit, Links zu extrahieren, die zu den Seiten führen, die alle Informationen enthalten, die ich brauche d: Ich suche HTML/href:

href="/main/results/showgame?gamenumber=1&phasetypecode=RS&gamecode=4&seasoncode=E2001#!boxscore" 

Und meine regex das wäre zu folgen hat:

Rule(SgmlLinkExtractor(allow=('gamenumber\=\d+\&phasetypecode\=\w+\&gamecode\=\d+\&seasoncode\=E\d+',)),callback='parse_item'), 

enter image description here

Das Problem

Ich denke, Dieser Crawler sollte etwa so funktionieren: Der Crawler ist so etwas wie eine Schleife. Wenn der erste Link gefunden wird, folgt der Crawler der Seite "Schritt 2", dann "Schritt 3" und danach werden die Daten extrahiert.Danach kehrt es zu "Schritt 1" zurück, um der zweiten Verbindung zu entsprechen und die Schleife erneut zu dem Punkt zu starten, an dem im ersten Schritt keine Verknüpfungen vorhanden sind.

Was ich von Terminal sehe, scheint, dass der Crawler in "Schritt 1" loops. Es durchläuft alle "Schritt 1" -Links, beinhaltet jedoch keine "Schritt 2"/"Schritt 3" -Regeln.

2014-02-28 00:20:31+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2000> (referer: http:// www.euroleague.net/main/results/by-date) 
2014-02-28 00:20:31+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2001> (referer: http://www.euroleague.net/main/results/by-date) 
2014-02-28 00:20:31+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2002> (referer: http://www.euroleague.net/main/results/by-date) 
2014-02-28 00:20:32+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2003> (referer: http://www.euroleague.net/main/results/by-date) 
2014-02-28 00:20:33+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2004> (referer: http://www.euroleague.net/main/results/by-date) 

Nachdem es durch alle „Jahreszeiten“ Links-Schleifen beginnt es mit Links, die ich nicht sehe, in einem der drei Schritte, die ich erwähnt:

http://www.euroleague.net/main/results/by-date?gamenumber=23&phasetypecode=TS++++++++&seasoncode=E2013 

Und eine solche Struktur Link können Sie Finden Sie nur, wenn Sie alle Links in "Schritt 2" durchlaufen, ohne zum Ausgangspunkt "Schritt 1" zurückzukehren.

Die Frage wäre: Wie Regeln funktionieren? Arbeitet es Schritt für Schritt so, wie ich es vorhabe, sollte es mit diesem Beispiel arbeiten oder hat jede Regel ihre eigene Schleife und geht von Regel zu Regel erst, nachdem sie die erste Regel durchlaufen hat?

So sehe ich es. Natürlich könnte etwas mit meinen Regeln/Regex nicht stimmen und es ist sehr gut möglich.

Und hier ist alles, was ich von dem Terminal bin immer:

scrapy crawl basketsp_test -o item6.xml -t xml 
2014-02-28 01:09:20+0200 [scrapy] INFO: Scrapy 0.20.0 started (bot: basketbase) 
2014-02-28 01:09:20+0200 [scrapy] DEBUG: Optional features available: ssl, http11, boto, django 
2014-02-28 01:09:20+0200 [scrapy] DEBUG: Overridden settings: {'NEWSPIDER_MODULE': 'basketbase.spiders', 'FEED_FORMAT': 'xml', 'SPIDER_MODULES': ['basketbase.spiders'], 'FEED_URI': 'item6.xml', 'BOT_NAME': 'basketbase'} 
2014-02-28 01:09:21+0200 [scrapy] DEBUG: Enabled extensions: FeedExporter, LogStats, TelnetConsole, CloseSpider, WebService, CoreStats, SpiderState 
2014-02-28 01:09:21+0200 [scrapy] DEBUG: Enabled downloader middlewares: HttpAuthMiddleware, DownloadTimeoutMiddleware, UserAgentMiddleware, RetryMiddleware, DefaultHeadersMiddleware, MetaRefreshMiddleware, HttpCompressionMiddleware, RedirectMiddleware, CookiesMiddleware, ChunkedTransferMiddleware, DownloaderStats 
2014-02-28 01:09:21+0200 [scrapy] DEBUG: Enabled spider middlewares: HttpErrorMiddleware, OffsiteMiddleware, RefererMiddleware, UrlLengthMiddleware, DepthMiddleware 
2014-02-28 01:09:21+0200 [scrapy] DEBUG: Enabled item pipelines: Basketpipeline3, Basketpipeline1db 
2014-02-28 01:09:21+0200 [basketsp_test] INFO: Spider opened 
2014-02-28 01:09:21+0200 [basketsp_test] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min) 
2014-02-28 01:09:21+0200 [scrapy] DEBUG: Telnet console listening on 0.0.0.0:6023 
2014-02-28 01:09:21+0200 [scrapy] DEBUG: Web service listening on 0.0.0.0:6080 
2014-02-28 01:09:21+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date> (referer: None) 
2014-02-28 01:09:22+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date) 
2014-02-28 01:09:22+0200 [basketsp_test] DEBUG: Filtered duplicate request: <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2013> - no more duplicates will be shown (see DUPEFILTER_CLASS) 
2014-02-28 01:09:22+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2000> (referer: http://www.euroleague.net/main/results/by-date) 
2014-02-28 01:09:23+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2001> (referer: http://www.euroleague.net/main/results/by-date) 
2014-02-28 01:09:23+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2002> (referer: http://www.euroleague.net/main/results/by-date) 
2014-02-28 01:09:24+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2003> (referer: http://www.euroleague.net/main/results/by-date) 
2014-02-28 01:09:24+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2004> (referer: http://www.euroleague.net/main/results/by-date) 
2014-02-28 01:09:25+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2005> (referer: http://www.euroleague.net/main/results/by-date) 
2014-02-28 01:09:26+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2006> (referer: http://www.euroleague.net/main/results/by-date) 
2014-02-28 01:09:26+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2007> (referer: http://www.euroleague.net/main/results/by-date) 
2014-02-28 01:09:27+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2008> (referer: http://www.euroleague.net/main/results/by-date) 
2014-02-28 01:09:27+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2009> (referer: http://www.euroleague.net/main/results/by-date) 
2014-02-28 01:09:28+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2010> (referer: http://www.euroleague.net/main/results/by-date) 
2014-02-28 01:09:29+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2011> (referer: http://www.euroleague.net/main/results/by-date) 
2014-02-28 01:09:29+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?seasoncode=E2012> (referer: http://www.euroleague.net/main/results/by-date) 
2014-02-28 01:09:30+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=24&phasetypecode=TS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:30+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=23&phasetypecode=TS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:31+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=22&phasetypecode=TS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:32+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=21&phasetypecode=TS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:32+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=20&phasetypecode=TS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:33+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=19&phasetypecode=TS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:34+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=18&phasetypecode=TS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:34+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=17&phasetypecode=TS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:35+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=16&phasetypecode=TS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:35+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=15&phasetypecode=TS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:36+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=14&phasetypecode=TS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:37+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=13&phasetypecode=TS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:37+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=12&phasetypecode=TS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:38+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=11&phasetypecode=TS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:39+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=10&phasetypecode=RS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:39+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=9&phasetypecode=RS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:40+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=8&phasetypecode=RS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:40+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=7&phasetypecode=RS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:41+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=6&phasetypecode=RS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:42+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=5&phasetypecode=RS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:42+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=4&phasetypecode=RS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:43+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=3&phasetypecode=RS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:44+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=2&phasetypecode=RS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:44+0200 [basketsp_test] DEBUG: Crawled (200) <GET http://www.euroleague.net/main/results/by-date?gamenumber=1&phasetypecode=RS++++++++&seasoncode=E2013> (referer: http://www.euroleague.net/main/results/by-date?seasoncode=E2013) 
2014-02-28 01:09:44+0200 [basketsp_test] INFO: Closing spider (finished) 
2014-02-28 01:09:44+0200 [basketsp_test] INFO: Dumping Scrapy stats: 
    {'downloader/request_bytes': 13663, 
    'downloader/request_count': 39, 
    'downloader/request_method_count/GET': 39, 
    'downloader/response_bytes': 527838, 
    'downloader/response_count': 39, 
    'downloader/response_status_count/200': 39, 
    'finish_reason': 'finished', 
    'finish_time': datetime.datetime(2014, 2, 27, 23, 9, 44, 569579), 
    'log_count/DEBUG': 46, 
    'log_count/INFO': 3, 
    'request_depth_max': 2, 
    'response_received_count': 39, 
    'scheduler/dequeued': 39, 
    'scheduler/dequeued/memory': 39, 
    'scheduler/enqueued': 39, 
    'scheduler/enqueued/memory': 39, 
    'start_time': datetime.datetime(2014, 2, 27, 23, 9, 21, 111255)} 
2014-02-28 01:09:44+0200 [basketsp_test] INFO: Spider closed (finished) 

Und hier ist ein Regelteil von dem Crawler:

class Basketspider(CrawlSpider): 
    name = "basketsp_test" 
    download_delay = 0.5 

    allowed_domains = ["www.euroleague.net"] 
    start_urls = ["http://www.euroleague.net/main/results/by-date"] 
    rules = (
     Rule(SgmlLinkExtractor(allow=('by-date\?seasoncode\=E\d+',)),follow=True), 
     Rule(SgmlLinkExtractor(allow=('seasoncode\=E\d+\&gamenumber\=\d+\&phasetypecode\=\w+',)),follow=True), 
     Rule(SgmlLinkExtractor(allow=('gamenumber\=\d+\&phasetypecode\=\w+\&gamecode\=\d+\&seasoncode\=E\d+',)),callback='parse_item'), 



) 
+0

Schlagen Sie vor, lesen Sie den Scrapy-Quellcode. – kev

Antwort

6

Ich würde einen BaseSpider Schaber stattdessen zu verwenden versucht sein, eines Crawlers. Wenn Sie einen Basspider verwenden, können Sie mehr von den geplanten Anforderungsrouten verwenden, anstatt ALLE hrefs auf der Seite zu finden und sie basierend auf globalen Regeln zu besuchen. Verwenden Sie yield Requests(), um das Durchlaufen der übergeordneten Sätze von Links und Callbacks fortzusetzen, um das Ausgabeobjekt vollständig an das Ende zu übergeben.

Aus Ihrer Beschreibung:

Ich denke, dass Crawler sollte in etwa so funktionieren: Das schließt Crawler so etwas wie eine Schleife ist. Wenn der erste Link gefunden wird, folgt der Crawler der Seite "Schritt 2", dann "Schritt 3" und danach werden die Daten extrahiert. Danach kehrt es zu "Schritt 1" zurück, um der zweiten Verbindung zu entsprechen und die Schleife erneut zu dem Punkt zu starten, an dem im ersten Schritt keine Verknüpfungen vorhanden sind.

Ein Request Callback-Stack wie dieser würde Ihnen sehr gut gefallen. Da Sie die Reihenfolge der Seiten kennen und welche Seiten Sie scrappen müssen. Dies hat auch den zusätzlichen Vorteil, dass Informationen über mehrere Seiten gesammelt werden können, bevor das zu verarbeitende Ausgabeobjekt zurückgegeben wird.

class Basketspider(BaseSpider, errorLog): 
    name = "basketsp_test" 
    download_delay = 0.5 

    def start_requests(self): 

     item = WhateverYourOutputItemIs() 
     yield Request("http://www.euroleague.net/main/results/by-date", callback=self.parseSeasonsLinks, meta={'item':item}) 

    def parseSeaseonsLinks(self, response): 

     item = response.meta['item'] 

     hxs = HtmlXPathSelector(response) 

     html = hxs.extract() 
     roundLinkList = list() 

     roundLinkPttern = re.compile(r'http://www\.euroleague\.net/main/results/by-date\?gamenumber=\d+&phasetypecode=RS') 

     for (roundLink) in re.findall(roundLinkPttern, html): 
      if roundLink not in roundLinkList: 
       roundLinkList.append(roundLink)   

     for i in range(len(roundLinkList)): 

      #if you wanna output this info in the final item 
      item['RoundLink'] = roundLinkList[i] 

      # Generate new request for round page 
      yield Request(stockpageUrl, callback=self.parseStockItem, meta={'item':item}) 


    def parseRoundPAge(self, response): 

     item = response.meta['item'] 
     #Do whatever you need to do in here call more requests if needed or return item here 

     item['Thing'] = 'infoOnPage' 
     #.... 
     #.... 
     #.... 

     return item 
13

Sie haben Recht, entsprechend der source code bevor jede Antwort auf die Callback-Funktion zurückkehrt, die Raupenkette über die Regeln Schleifen, ausgehend von der ersten. Sie sollten daran denken, wenn Sie die Regeln schreiben. Zum Beispiel die folgenden Regeln:

rules(
     Rule(SgmlLinkExtractor(allow=(r'/items',)), callback='parse_item',follow=True), 
     Rule(SgmlLinkExtractor(allow=(r'/items/electronics',)), callback='parse_electronic_item',follow=True), 
    ) 

Die zweite Regel wird nie alle angewendet werden, da die Verbindungen durch die erste Regel mit parse_item Rückruf extrahiert werden. Die Übereinstimmungen für die zweite Regel werden von der scrapy.dupefilter.RFPDupeFilter als Duplikate herausgefiltert.Sie sollten für eine korrekte Abstimmung von Links verwenden verweigern:

rules(
     Rule(SgmlLinkExtractor(allow=(r'/items',)), deny=(r'/items/electronics',), callback='parse_item',follow=True), 
     Rule(SgmlLinkExtractor(allow=(r'/items/electronics',)), callback='parse_electronic_item',follow=True), 
    ) 
3

Wenn Sie aus China sind, ich habe einen chinesischen Blog-Eintrag dazu:

别再滥用scrapy CrawlSpider中的follow=True


Lassen sie prüfen, wie die Regeln arbeiten unter der Haube:

def _requests_to_follow(self, response): 
    seen = set() 
    for n, rule in enumerate(self._rules): 
     links = [lnk for lnk in rule.link_extractor.extract_links(response) 
       if lnk not in seen] 
     for link in links: 
      seen.add(link) 
      r = Request(url=link.url, callback=self._response_downloaded) 
      yield r 

wie Sie sehen können, wenn wir einem Link folgen, der Die Verknüpfung in der Antwort wird von allen Regeln extrahiert, die eine for-Schleife verwenden, und dann zu einem set-Objekt hinzugefügt.

def _response_downloaded(self, response): 
    rule = self._rules[response.meta['rule']] 
    return self._parse_response(response, rule.callback, rule.cb_kwargs, rule.follow) 

def _parse_response(self, response, callback, cb_kwargs, follow=True): 

    if callback: 
     cb_res = callback(response, **cb_kwargs) or() 
     cb_res = self.process_results(response, cb_res) 
     for requests_or_item in iterate_spider_output(cb_res): 
      yield requests_or_item 

    # follow will go back to the rules again 
    if follow and self._follow_links: 
     for request_or_item in self._requests_to_follow(response): 
      yield request_or_item 

und es geht wieder und wieder auf die self._requests_to_follow(response):

und alle die Antwort wird durch self._response_downloaded behandelt werden.

Zusammenfassend: enter image description here

Verwandte Themen