2016-03-19 5 views
0

Ich habe einen Crawlspider für meine Bedürfnisse erstellt es funktioniert perfekt. Es gibt jedoch bestimmte XML-Sitemaps in einigen Kategorien (nicht in allen) auf der Website, die ich crawle. Also würde ich gerne die Funktion haben, XML-Sitemap in diesen Kategorien zu analysieren und Links zu erhalten, überlasse es dann dem crawlspider, tiefer zu diesen Links zu gehen.Crawlspider zum Parsen und Hinzufügen von Links von XML-Seiten auf dem Weg

Ich bin mir bewusst, dass es einen SitemapSpider und XMLFeedSpider gibt, aber ich brauche die Funktionalität von crawlspider mit XMLFeedSpider oder umgekehrt.

Jede Hilfe wäre willkommen.

Antwort

3

Um CrawlSpider Arbeit mit URLs in Sitemaps zu machen, können Sie einen benutzerdefinierten Link-Extraktor für XML-Antworten kochen, aber es sieht wie CrawlSpider does not process XML responses. Sie müssen also auch _requests_to_follow überschreiben, um sie zu akzeptieren.

Hier ist ein Beispiel Spinne ich mit einem sitemap.gz URL versucht, mit (enthaltend ein Sitemap)

from scrapy.spiders.crawl import CrawlSpider, Rule 
from scrapy.link import Link 
from scrapy.http import Request 


class XmlLinkExtractor(): 

    def __init__(self, xpath, namespaces): 
     self.xpath = xpath 
     self.namespaces = namespaces 

    def extract_links(self, response): 
     selector = response.selector 
     if self.namespaces: 
      for i, ns in self.namespaces.items(): 
       selector.register_namespace(i, ns) 
     for link in selector.xpath(self.xpath).extract(): 
      yield Link(link) 


class ExampleSitemapCrawlSpider(CrawlSpider): 
    name = "myspider" 
    start_urls = (
     # link to a sitemap index file 
     'http://www.example.com/sitemap.gz', 

     # link to a sitemap file 
     #'http://www.example.com/sitemaps/sitemap-general.xml', 
     ) 
    rules = (

     # this handles sitemap indexes, following links to other sitemaps 
     Rule(XmlLinkExtractor('/sm:sitemapindex/sm:sitemap/sm:loc/text()', 
       {"sm": "http://www.sitemaps.org/schemas/sitemap/0.9"}),), 

     # this is for "leaf" pages in sitemaps 
     Rule(XmlLinkExtractor('/sm:urlset/sm:url/sm:loc/text()', 
       {"sm": "http://www.sitemaps.org/schemas/sitemap/0.9"}), 
      # here, defining the callback without follow=True 
      # makes the crawler stop at these pages level, 
      # not following deeper links 
      # unset the callback if you want those pages 
      # to go through other rules once downloaded 
      callback='parse_loc'), 
     # ... other rules 
    ) 

    def _requests_to_follow(self, response): 
     # we need to override `_requests_to_follow` 
     # and comment these 2 lines, because they filter XML responses 
     #if not isinstance(response, HtmlResponse): 
     # return 
     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] 
      if links and rule.process_links: 
       links = rule.process_links(links) 
      for link in links: 
       seen.add(link) 
       r = Request(url=link.url, callback=self._response_downloaded) 
       r.meta.update(rule=n, link_text=link.text) 
       yield rule.process_request(r) 

    def parse_loc(self, response): 
     self.logger.debug("parsing %r" % response) 

Je nachdem, wie Sie von /urlset/url/loc Seiten analysieren beginnen soll, können Sie verschiedene URLs zu verschiedenen Rückrufe umleiten (Hinzufügen von unterschiedlichen Regeln und Anpassen XmlLinkExtractor Filterung zu ermöglichen (oder XPath zu verwenden, um Filter)

+0

Danke Paul, auch eine andere Sache, die ich bemerkt habe ist, dass Steven auch die richtige Antwort hat. Das Problem besteht, wenn ich mit xml pages starte (wenn ich start_urls als xml gesetzt habe) in crawlspider. Wenn ich mit einer HTML-Seite anfange, dann gehe ich zu einer XML-Seite, die Crawlspider scheint mit Steven's Antwort den Trick zu machen. Danke Ihnen allen, dass Sie mir geholfen haben. Entschuldigung für die späte Antwort. – Saitx

0

Sie können Ihrem aktuellen CrawlSpider einfach eine Regel hinzufügen und die XML selbst analysieren. Sie müssen nur eine Regel an der Spitze der rules hinzufügen und bearbeiten sitemap_xml_xpath im Rückruf:

import scrapy 
import scrapy.linkextractors 
import scrapy.spiders.crawl 


class SmartlipoSpider(scrapy.spiders.crawl.CrawlSpider): 
    name = "myspider" 
    start_urls = ('http://example.com/',) 
    rules = (
     scrapy.spiders.crawl.Rule(
      scrapy.linkextractors.LinkExtractor(
       allow=r'sitemap\.xml$', 
      ), 
      callback='parse_sitemap_xml', follow=True, 
     ), 
     # the other rules... 
    ) 

    def parse_sitemap_xml(self, response): 
     sitemap_xml_xpath = '/urlset/url' 

     for url in response.xpath(sitemap_xml_xpath): 
      yield scrapy.Request(url) 

    # your other callbacks... 
+0

ich dies versucht haben, bevor die Antwort, das ist zu parse_sitemap_xml kommen scheint null zu sein. Es ist nicht als HTML behandelt wie erwartet. – Saitx

+0

Crawlspider die Rückkehr tut XML-Ergebnisse. Antwort kommt aus irgendeinem Grund leer oder wenn ich eine XML-Seite starte_url der obige Code führt nicht die Parse_sitemap_xml. – Saitx

Verwandte Themen