2015-10-03 9 views
5

Pracuję nad skrobaczką, która przeszukuje wszystkie linki wewnętrzne z adresu startowego i zbiera tylko linki zewnętrzne z scrapy. Jednak moim głównym problemem jest klasyfikowanie zewnętrznych linków i wewnętrznych linków. Na przykład, gdy próbuję odfiltrować linki zewnętrzne za pomocą link.startswith("http") or link.startswith("ftp") or link.startswith("www"), jeśli witryna łączy swoją własną stronę internetową z bezwzględną ścieżką (www.my-domain.com/about zamiast /about), wówczas klasyfikuje ją jako łącze zewnętrzne, nawet jeśli nie jest. Oto mój kod:Złomowanie: przechowuj wszystkie linki zewnętrzne i przeszukuj wszystkie łącza międzymiastowe.

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 

Wszelkie sugestie?

Odpowiedz

7

Użyj link extractor.

Podczas tworzenia instancji musisz przekazać dozwoloną domenę. Nie musisz się martwić o określenie wymaganych znaczników, ponieważ (zgodnie z dokumentami) parametr tags przyjmuje domyślnie ('a', 'area').

Na przykładzie stronie Rust lang, kod, aby wydrukować wszystkie linki wewnętrzne z ich domeną będzie wyglądać następująco:

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 

a wyjście będzie lista tych linków: https://doc.rust-lang.org/nightly/reference.html (mogę” t post more), jednocześnie wyłączając wszystkie łącza, takie jak te do StackOverflow.

Należy sprawdzić stronę z dokumentacją, ponieważ ekstraktor łącza ma wiele parametrów, które mogą być potrzebne.

+0

Hm .. sugerujesz tworzenie zestawów wewnętrznych linków z LinkExtractor, a dla wszystkich linków sprawdź, czy pasują do linków wewnętrznych, a jeśli nie, to czy są to linki zewnętrzne? –

+0

Niezupełnie, ustawiając 'deny_domains = 'domain'' można wyodrębnić łącza, które nie są w danej domenie (zewnętrzne). –

+0

Och, człowieku. To idealne. Dziękuję bardzo. –

-2

Jeśli można wziąć wiele lub oświadczenia, nie tylko dwa.

+0

Ale moja tablica będzie zawierać również linki wewnętrzne. Chcę tylko linki zewnętrzne. –

+0

Tak, właśnie to odnotowałem. Patrząc na twój kod, "if link.startswith ("/") lub link.startswith (". "):" Linia może mieć wiele "lub" instrukcji, w przeciwnym razie może użyć [przełącznika] (https: // pypi. python.org/pypi/switch) oświadczenie – kcrk

+0

Już używam wielu 'lub' w moim kodzie, i nie widzę jak to będzie filtrować bezwzględne linki z względnych linków –

Powiązane problemy