2015-10-03 145 views
5

我一直在研究scrapy網絡抓取工具,它從一個起始網址抓取所有內部鏈接,僅收集與scrapy的外部鏈接。但是,我的主要問題是分類外部鏈接和內部鏈接。例如,當我嘗試用link.startswith("http") or link.startswith("ftp") or link.startswith("www")過濾掉外部鏈接時,如果網站使用絕對路徑(www.my-domain.com/about而不是​​)鏈接其自己的網站,那麼即使它不是外部鏈接,它也會將其歸類爲外部鏈接。以下是我的代碼:Scrapy:存儲所有外部鏈接並抓取所有內部鏈接

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 

有什麼建議嗎?

回答

7

使用link extractor

當實例化你必須通過允許的域。您不必擔心指定所需的標籤,因爲(根據文檔)參數tags默認爲('a', 'area')

生鏽郎網站爲例,代碼打印所有的內部鏈接從他們的域名看起來像:

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 

,輸出會是這樣鏈接的列表:https://doc.rust-lang.org/nightly/reference.html(我可以」 t post more),同時排除像StackOverflow那樣的所有鏈接。

請務必查看文檔頁面,因爲鏈接提取器有許多您可能需要的參數。

+0

嗯..你是否建議製作一套LinkExtractor的內部鏈接,並且對於所有鏈接,檢查它們是否匹配內部鏈接,如果不匹配,那麼它們是外部鏈接? –

+0

不完全是,通過設置'deny_domains ='domain'',您可以提取不在給定域(外部)中的鏈接。 –

+0

哦,夥計。那很完美。非常感謝。 –

-2

如果可以採取多個或語句,而不只是兩個。

+0

但我的數組也會包含內部鏈接。我只想要外部鏈接 –

+0

是的,只是指出。看看你的代碼,「如果link.startswith(」/「)或link.startswith(」。「):」行可以有多個「或」語句,否則可能使用[開關](https:// pypi。 python.org/pypi/switch)聲明 – kcrk

+0

我已經在我的代碼中使用了多個'或',並且我沒有看到如何從相關鏈接中過濾掉絕對鏈接 –