2017-08-30 11 views
0

私はScrapyでニュースサイトを掻き集めて、スクラップしたアイテムをsqlalchemyでデータベースに保存します。 クロールジョブは定期的に実行され、最後のクロール以降に変更されなかったURLは無視します。ScreamサブクラスLinkExtractorはTypeErrorを発生させます:MyLinkExtractor()は予期しないキーワード引数 'allow'を持っています

私は、LinkExtractorをサブクラス化しようとしていて、response.urlが最近更新されたよりも最近クロールされた場合に空のリストを返します。

しかし、私は 'scrapyクロールspider_name' を実行したとき、私は取得しています:

TypeError: MyLinkExtractor() got an unexpected keyword argument 'allow'

コード:

def MyLinkExtractor(LinkExtractor): 
    '''This class should redefine the method extract_links to 
    filter out all links from pages which were not modified since 
    the last crawling''' 
    def __init__(self, *args, **kwargs): 
     """ 
     Initializes database connection and sessionmaker. 
     """ 
     engine = db_connect() 
     self.Session = sessionmaker(bind=engine) 
     super(MyLinkExtractor, self).__init__(*args, **kwargs) 

    def extract_links(self, response): 
     all_links = super(MyLinkExtractor, self).extract_links(response) 

     # Return empty list if current url was recently crawled 
     session = self.Session() 
     url_in_db = session.query(Page).filter(Page.url==response.url).all() 
     if url_in_db and url_in_db[0].last_crawled.replace(tzinfo=pytz.UTC) > item['header_last_modified']: 
      return [] 

     return all_links 

を...

class MySpider(CrawlSpider): 

    def __init__(self, *args, **kwargs): 
     """ 
     Initializes database connection and sessionmaker. 
     """ 
     engine = db_connect() 
     self.Session = sessionmaker(bind=engine) 
     super(MySpider, self).__init__(*args, **kwargs) 

    ... 

    # Define list of regex of links that should be followed 
    links_regex_to_follow = [ 
     r'some_url_pattern', 
     ] 

    rules = (Rule(MyLinkExtractor(allow=links_regex_to_follow), 
        callback='handle_news', 
        follow=True),  
      ) 

    def handle_news(self, response): 

     item = MyItem() 
     item['url'] = response.url 
     session = self.Session() 

     # ... Process the item and extract meaningful info 

     # Register when the item was crawled 
     item['last_crawled'] = datetime.datetime.utcnow().replace(tzinfo=pytz.UTC) 

     # Register when the page was last-modified 
     date_string = response.headers.get('Last-Modified', None).decode('utf-8') 
     item['header_last_modified'] = get_datetime_from_http_str(date_string) 

     yield item 

最も奇妙なことがあることです、交換する場合MyLinkExtractorLinkE xtractorルールの定義で実行されます。

しかし、私はルール定義でMyLinkExtractorを残し、にMyLinkExtractorを再定義する場合:

def MyLinkExtractor(LinkExtractor): 
    '''This class should redefine the method extract_links to 
    filter out all links from pages which were not modified since 
    the last crawling''' 
    pass 

私は同じエラーを取得します。

答えて

2

MyLinkExtractorclassの代わりにdefと宣言しているため、classではありませんが、機能しています。 Pythonは他の関数の中で関数を宣言することができ、実際には名前のどれも予約されていないので、見つけにくいです。

とにかく、スタックトレースは、正しくインスタンス化されていないクラスの場合には少し異なると思われます。最後にエラーが発生した関数の名前が表示されます(MyLinkExtractorの__init__)。

+0

...:|私はそれが単純なものだったことは分かっていました。さて、この質問がLinkExtractorのサブクラス化に役立つことを願っています。ありがとう@erhesto – pedrovgp

関連する問題