Scrapy CrawlSpider 规则与多个回调
我正在尝试创建一个叫做ExampleSpider的爬虫,它是基于scrapy的CrawlSpider。我的ExampleSpider应该能够处理只包含艺术家信息的页面、只包含专辑信息的页面,以及一些同时包含专辑和艺术家信息的页面。
我已经能处理前两种情况了,但在第三种情况下出现了问题。我使用parse_artist(response)
方法来处理艺术家数据,使用parse_album(response)
方法来处理专辑数据。我的问题是,如果一个页面同时包含艺术家和专辑的数据,我应该如何定义我的规则呢?
- 我应该像下面这样做吗?(对同一个网址模式使用两个规则)
- 我应该使用多个回调吗?(scrapy支持多个回调吗?)
还有其他方法吗?(一种合适的方法)
class ExampleSpider(CrawlSpider): name = 'example' start_urls = ['http://www.example.com'] rules = [ Rule(SgmlLinkExtractor(allow=[r'same regex_rule']), callback='parse_artist', follow=True), Rule(SgmlLinkExtractor(allow=[r'same regex_rule']), callback='parse_album', follow=True), # more rules ..... ] def parse_artist(self, response): artist_item = ArtistItem() try: # do the scrape and assign to ArtistItem except Exception: # ignore for now pass return artist_item pass def parse_album(self, response): album_item = AlbumItem() try: # do the scrape and assign to AlbumItem except Exception: # ignore for now pass return album_item pass pass
1 个回答
9
CrawlSpider
会调用 _requests_to_follow()
这个方法来提取网址并生成请求以便继续跟进:
def _requests_to_follow(self, response):
if not isinstance(response, HtmlResponse):
return
seen = set()
for n, rule in enumerate(self._rules):
links = [l for l in rule.link_extractor.extract_links(response) if l not in seen]
if links and rule.process_links:
links = rule.process_links(links)
seen = seen.union(links)
for link in links:
r = Request(url=link.url, callback=self._response_downloaded)
r.meta.update(rule=n, link_text=link.text)
yield rule.process_request(r)
从上面可以看到:
- 变量
seen
用来记住已经处理过的urls
。 - 每个
url
最多只会被一个callback
处理。
你可以定义一个 parse_item()
方法来调用 parse_artist()
和 parse_album()
:
rules = [
Rule(SgmlLinkExtractor(allow=[r'same regex_rule']), callback='parse_item', follow=True),
# more rules .....
]
def parse_item(self, response):
yield self.parse_artist(response)
yield self.parse_album(response)