2015-10-03 21 views
5

Ich habe an einem Scrapy Web Scraper gearbeitet, der alle internen Links von einer Start-URL durchsucht und nur externe Links mit scrapy erfasst. Mein Hauptproblem ist jedoch die Klassifizierung der externen Links und internen Links. Zum Beispiel, wenn ich versuche, externe Links mit link.startswith("http") or link.startswith("ftp") or link.startswith("www") herauszufiltern, wenn die Website ihre eigene Website mit einem absoluten Pfad verbindet (www.my-domain.com/about statt /about) dann wird es es als den externen Link klassifizieren, auch wenn es nicht ist. Das Folgende ist mein Code:Scrapy: alle externen Links speichern und alle internen Links crawlen

import scrapy 
from lab_relationship.items import Links 

class WebSpider(scrapy.Spider): 
    name = "web" 
    allowed_domains = ["my-domain.com"] 
    start_urls = (
     'www.my-domain.com', 
    ) 

    def parse(self, response): 
     """ finds all external links""" 
     items = [] 
     for link in set(response.xpath('//a/@href').extract()): 
      item = Links() 
      if len(link) > 1: 
       if link.startswith("/") or link.startswith("."): 
        # internal link 
        url = response.urljoin(link) 
        item['internal'] = url 
        #yield scrapy.Request(url, self.parse) 
       elif link.startswith("http") or link.startswith("ftp") or link.startswith("www"): 
        # external link 
        item['external'] = link 
       else: 
        # misc. links: mailto, id (#) 
        item['misc'] = link 
       items.append(item) 
     return items 

Irgendwelche Vorschläge?

Antwort

7

Verwenden Sie die link extractor.

Bei der Instanziierung müssen Sie die erlaubte Domain passieren. Sie müssen sich nicht darum kümmern, die erforderlichen Tags anzugeben, da (laut Dokumentation) der Parameter tags standardmäßig ('a', 'area') ist.

Am Beispiel von Rust lang Webseite, der Code alle internen Links zu drucken aus ihrer Domain aussehen würde:

import scrapy 
from scrapy.linkextractors import LinkExtractor 


class RustSpider(scrapy.Spider): 
    name = "rust" 
    allowed_domains = ["www.rust-lang.org"] 
    start_urls = (
     'http://www.rust-lang.org/', 
    ) 

    def parse(self, response): 
     extractor = LinkExtractor(allow_domains='rust-lang.org') 
     links = extractor.extract_links(response) 
     for link in links: 
      print link.url 

und der Ausgang wäre eine Liste solcher Verbindungen: https://doc.rust-lang.org/nightly/reference.html (I can‘ t posten mehr), während alle Links wie jene zu StackOverflow ausgeschlossen werden.

Bitte überprüfen Sie die Dokumentationsseite, da der Link-Extraktor viele Parameter enthält, die Sie möglicherweise benötigen.

+0

Hm .. schlagen Sie vor, eine Reihe von internen Links mit LinkExtractor zu erstellen, und für alle Links zu überprüfen, ob sie den internen Links entsprechen, und wenn nein, sind sie externe Links? –

+0

Nicht genau, indem Sie 'deny_domains = 'Domäne' setzen, können Sie Links extrahieren, die sich nicht in einer bestimmten Domäne (extern) befinden. –

+0

Oh Mann. Das ist perfekt. Ich danke dir sehr. –

-2

Das if kann mehrere oder Anweisungen enthalten, nicht nur zwei.

+0

Aber mein Array wird auch interne Links enthalten. Ich will nur externe Links –

+0

Ja, nur das notiert. Wenn Sie Ihren Code betrachten, kann die Zeile "if link.startswith ("/") oder link.startswith (". "):" Zeile kann mehrere "oder" Anweisungen enthalten, andernfalls verwenden Sie möglicherweise [switch] (https: // pypi. python.org/pypi/switch) Anweisung – kcrk

+0

Ich verwende bereits mehrere 'or's in meinem Code, und ich sehe nicht, wie das absolute Links von relativen Links –

Verwandte Themen