2010-03-07 40 views
12

我需要創建一個用戶可配置的網絡蜘蛛/爬行器,我正在考慮使用Scrapy。但是,我無法對域進行硬編碼並允許使用URL正則表達式:es - 這可以在GUI中進行配置。爲幾個網站使用一個Scrapy蜘蛛

我如何(儘可能簡單地)使用Scrapy創建一個蜘蛛或一組蜘蛛,其中域和允許的URL regex:es是動態可配置的?例如。我將配置寫入一個文件,並且蜘蛛以某種方式讀取它。

+2

@ChristianDavén:不是答案爲接受你的問題? – dangra 2010-03-31 20:31:19

回答

10

警告:此答案適用於Scrapy v0.7,蜘蛛管理器api自此發生了很大變化。

覆蓋默認SpiderManager類,從數據庫加載您的自定義規則或別的地方,實例化一個自定義的蜘蛛與自己的規則/正則表達式和DOMAIN_NAME

在mybot

/settings.py:

SPIDER_MANAGER_CLASS = 'mybot.spidermanager.MySpiderManager' 

在mybot/spidermanager.py:

from mybot.spider import MyParametrizedSpider 

class MySpiderManager(object): 
    loaded = True 

    def fromdomain(self, name): 
     start_urls, extra_domain_names, regexes = self._get_spider_info(name) 
     return MyParametrizedSpider(name, start_urls, extra_domain_names, regexes) 

    def close_spider(self, spider): 
     # Put here code you want to run before spiders is closed 
     pass 

    def _get_spider_info(self, name): 
     # query your backend (maybe a sqldb) using `name` as primary key, 
     # and return start_urls, extra_domains and regexes 
     ... 
     return (start_urls, extra_domains, regexes) 

,現在您的自定義蜘蛛類,在mybot/spider.py:

from scrapy.spider import BaseSpider 

class MyParametrizedSpider(BaseSpider): 

    def __init__(self, name, start_urls, extra_domain_names, regexes): 
     self.domain_name = name 
     self.start_urls = start_urls 
     self.extra_domain_names = extra_domain_names 
     self.regexes = regexes 

    def parse(self, response): 
     ... 

注:

  • 如果你想利用它的規則系統的優勢
  • 要運行一個蜘蛛使用可以延長也CrawlSpider:./scrapy-ctl.py crawl <name>,其中name傳遞給SpiderManager.fromdomain和是從後端系統中獲取更多蜘蛛信息的關鍵
  • 由於解決方案會覆蓋默認的SpiderManager,因此對傳統蜘蛛(每個SPIDER的python模塊)進行編碼不起作用,但是,我認爲這不是問題。在默認情況下蜘蛛經理更多信息TwistedPluginSpiderManager
+0

與Alex Martelli方法的不同之處在於,蜘蛛根據需求進行實例化,而不是僅僅使用一個實例。這種方法可以減少後端的負載和scrapy bot進程的內存佔用。 – dangra 2010-03-07 18:57:20

+0

我如何指定每個自定義蜘蛛(ITEM_PIPELINES,USER_AGENT等)的設置?你也提到'./scrapy-ctl.py抓取'。什麼是'scrapy-ctl.py'? – warvariuc 2011-04-18 12:40:21

3

無恥自我推銷domo!您需要爲您的項目實例化示例中給出的搜尋器。

此外,您還需要在運行時配置爬網程序,只需將配置傳遞給爬網程序,並在配置更改時覆蓋運行時的設置。

4

你需要的是動態創建蜘蛛類,由scrapy所提供繼承你最喜歡的一般的蜘蛛類(您rules添加XmlFeedSpiderCrawlSpider子類,或,或其他),並加入domain_namestart_urls,並可能extra_domain_names(和/或start_requests()等),當你從你的GUI(或配置文件,或其他)獲得或推斷出它們。

Python可以很容易地執行類對象的動態創建;一個很簡單的例子可能是:

from scrapy import spider 

def makespider(domain_name, start_urls, 
       basecls=spider.BaseSpider): 
    return type(domain_name + 'Spider', 
       (basecls,), 
       {'domain_name': domain_name, 
       'start_urls': start_urls}) 

allspiders = [] 
for domain, urls in listofdomainurlpairs: 
    allspiders.append(makespider(domain, urls)) 

這讓你非常裸骨蜘蛛類的列表 - 你可能會想你實例之前添加parse方法給他們。季節去品嚐...... ;-)。

+0

以及此代碼在哪裏存在?我試圖動態地將爬蟲類添加到我的蜘蛛模塊中,但scrapy並沒有把它們加入。 – 2011-05-24 13:04:59

0

現在是非常容易爲這些目的配置scrapy:

  1. 關於第一個網址的訪問,你可以把它作爲對蜘蛛的呼叫屬性與-a,並使用start_requests函數來設置如何啓動蜘蛛

  2. 您不需要爲蜘蛛設置allowed_domains變量。如果你不包含那個類變量,蜘蛛將能夠允許每個域。

應該落得這樣的:

class MySpider(Spider): 

    name = "myspider" 

    def start_requests(self): 
     yield Request(self.start_url, callback=self.parse) 


    def parse(self, response): 
     ... 

,你應該把它叫做:

scrapy crawl myspider -a start_url="http://example.com"