Je raccroche un site d'actualité avec Scrapy et enregistre des éléments récupérés dans une base de données avec sqlalchemy. Le travail d'analyse s'exécute périodiquement et je souhaite ignorer les URL qui n'ont pas changé depuis la dernière exploration.Scrapy subclassing LinkExtractor soulève TypeError: MyLinkExtractor() a un argument de mot clé inattendu 'allow'
J'essaie de sous-classer LinkExtractor et retourner une liste vide dans le cas où le fichier response.url a été analysé plus récemment que mis à jour.
Mais quand je lance 'scrapy crawl spider_name' Je reçois:
TypeError: MyLinkExtractor() got an unexpected keyword argument 'allow'
Le code:
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
La chose la plus étrange est que , si je remplace MyLinkExtractor pour LinkE xtractor dans la règle définition, il s'exécute.
Mais si je laisse MyLinkExtractor dans la définition Règle et redéfinissent 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
je reçois la même erreur.
...: | Je savais que c'était quelque chose de simple que je manquais simplement ... mais rien de si stupide. Eh bien, j'espère que cette question peut aider n'importe qui sous-classant LinkExtractor. Merci @erhesto – pedrovgp