Reputation: 3064
I'm crawling a list of pages, where each page has a list of urls that I need also to be parses. I'm looping over these first pages but I don't know a priori when should I stop the crawling. For example this one is still to be parsed:
http://www.cmjornal.pt/opiniao/colunistas/acacio-pereira/MoreContent?firstContent=183
but not this one not because is already empty:
http://www.cmjornal.pt/opiniao/colunistas/acacio-pereira/MoreContent?firstContent=200
So my question is: how can I stop the crawler with a condition found from a url parsing? I tried to use CloseSpider()
but it doesn't work, because it completely close the spider, before the other urls are parsed.
I show the code I'm using with the CloseSpider()
:
class CmSpider(scrapy.Spider):
name = "historical"
start_urls = ['http://www.cmjornal.pt/opiniao/colunistas/acacio-pereira/MoreContent?firstContent=']
hostname = 'http://www.cmjornal.pt'
def parse(self, response):
for i in range(180,200,3):
url = response.url + str(i)
yield scrapy.Request(url,callback=self.parse_page,priority = 1)
def parse_page(self,response):
if len(response.xpath('/html/body//*')) <= 2:
raise CloseSpider('bandwidth_exceeded')
else:
pass
articles_url = response.xpath('//*[@class="lead"]/../h3/a/@href').extract()
for url in articles_url:
url = self.hostname+url
item = CmItem()
item['hostname'] = self.hostname
request = scrapy.Request(url,callback=self.parse_article)
request.meta['item'] = item
yield request
def parse_article(self,response):
item = response.meta['item']
(...)
Note: for this particular case I know when the content will end, but I need to run this for many other cases that I don't know such limit.
Upvotes: 1
Views: 1069
Reputation: 1548
You should stop yielding more requests instead of closing the spider, something like this:
# -*- coding: utf-8 -*-
import scrapy
from w3lib.url import add_or_replace_parameter
from w3lib.url import url_query_parameter
class HistorialSpider(scrapy.Spider):
name = 'historial'
allowed_domains = ['cmjornal.pt']
def start_requests(self):
base_url = 'http://www.cmjornal.pt/opiniao/colunistas/acacio-pereira/MoreContent'
new_url = add_or_replace_parameter(base_url, 'firstContent', 180)
yield scrapy.Request(new_url, callback=self.parse_page)
def parse_page(self, response):
if len(response.xpath('/html/body//*')) <= 2:
return
next_page = int(url_query_parameter(response.url, 'firstContent')) + 1
yield scrapy.Request(add_or_replace_parameter(response.url, 'firstContent', next_page),
callback=self.parse_page)
articles_url = response.xpath('//*[@class="lead"]/../h3/a/@href').extract()
for url in articles_url:
yield response.follow(url, callback=self.parse_article)
def parse_article(self, response):
pass
Upvotes: 1