2015-01-15 10 views
9

Ich möchte alle externen Links von einer bestimmten Website mit Scrapy erhalten. Mit dem folgenden Code crawlt der Spider auch externe Links:Scrapy, folgen Sie nur internen URLs, aber extrahieren Sie alle gefundenen Links

from scrapy.contrib.spiders import CrawlSpider, Rule 
from scrapy.contrib.linkextractors import LinkExtractor 
from myproject.items import someItem 

class someSpider(CrawlSpider): 
    name = 'crawltest' 
    allowed_domains = ['someurl.com'] 
    start_urls = ['http://www.someurl.com/'] 

    rules = (Rule (LinkExtractor(), callback="parse_obj", follow=True), 
) 

    def parse_obj(self,response): 
    item = someItem() 
    item['url'] = response.url 
    return item 

Was fehlt mir? Verhindert "allowed_domains" das Crawlen der externen Links? Wenn ich "allow_domains" für LinkExtractor einstelle, werden die externen Links nicht extrahiert. Nur um zu verdeutlichen: Ich möchte interne Links crawlen, aber externe Links extrahieren. Jede Hilfe geschätzt!

+0

Wenn ich die OffsiteMiddleware die Links ermöglichen nicht gecrawlt werden, sondern auch nicht extrahiert. Wenigstens dann kann ich sehen "Gefiltert Offsite-Anfrage zu 'www.externedomain'. Sicherlich vermisse ich hier etwas Triviales? – sboss

+0

nur zu verstehen: Möchten Sie die Liste aller externen Links für eine bestimmte Website haben? – aberna

+0

Ja, dass ist korrekt! – sboss

Antwort

9

Sie können hier SgmlLinkExtractor Dokumentation macht auch den Link-Extraktor verwenden, um alle Links zu ziehen, wenn Sie jede Seite parsen.

Der Link-Extraktor filtert die Links für Sie. In diesem Beispiel verweigert der Link-Extraktor Links in der erlaubten Domäne, sodass nur externe Links abgerufen werden.

from scrapy.contrib.spiders import CrawlSpider, Rule 
from scrapy.contrib.linkextractors import LxmlLinkExtractor 
from myproject.items import someItem 

class someSpider(CrawlSpider): 
    name = 'crawltest' 
    allowed_domains = ['someurl.com'] 
    start_urls = ['http://www.someurl.com/'] 

    rules = (Rule(LxmlLinkExtractor(allow=()), callback='parse_obj', follow=True),) 


    def parse_obj(self,response): 
    for link in LxmlLinkExtractor(allow=(),deny = self.allowed_domains).extract_links(response): 
     item = someItem() 
     item['url'] = link.url 
3

Eine Lösung wäre eine Nutzung process_link Funktion im http://doc.scrapy.org/en/latest/topics/link-extractors.html

class testSpider(CrawlSpider): 
    name = "test" 
    bot_name = 'test' 
    allowed_domains = ["news.google.com"] 
    start_urls = ["https://news.google.com/"] 
    rules = (
    Rule(SgmlLinkExtractor(allow_domains=()), callback='parse_items',process_links="filter_links",follow= True) , 
    ) 

def filter_links(self, links): 
    for link in links: 
     if self.allowed_domains[0] not in link.url: 
      print link.url 

    return links 

def parse_items(self, response): 
    ### ... 
+0

@sboss Ich bemerkte, dass Sie akzeptiert und nachher meine vorgeschlagene Lösung herabgestuft. Der Code funktioniert gut, haben Sie ein anderes Problem bemerkt? – aberna

+0

Hallo aberna, Entschuldigung für die Herabstufung.Ich fand 12Ryan12: s Antwort eleganter, wie es ermöglicht Ich benutze die eingebauten doppelten Filter usw. Ich schätze die Antwort aber! – sboss

3

Eine aktualisierte Code basiert auf 12Ryan12 Antwort,

from scrapy.spiders import CrawlSpider, Rule 
from scrapy.linkextractors.lxmlhtml import LxmlLinkExtractor 
from scrapy.item import Item, Field 

class MyItem(Item): 
    url= Field() 


class someSpider(CrawlSpider): 
    name = 'crawltest' 
    allowed_domains = ['someurl.com'] 
    start_urls = ['http://www.someurl.com/'] 
    rules = (Rule(LxmlLinkExtractor(allow=()), callback='parse_obj', follow=True),) 

    def parse_obj(self,response): 
     item = MyItem() 
     item['url'] = [] 
     for link in LxmlLinkExtractor(allow=(),deny = self.allowed_domains).extract_links(response): 
      item['url'].append(link.url) 
     return item 
-2

pip installieren -U Scrapy mein Problem gelöst)