2015-12-22 3 views
0

У меня есть следующий url для начала: http://somedomain.mytestsite.com/?offset=0. Я хотел бы пропустить этот url, увеличивая параметр смещения, скажем, на 100 каждый раз. Каждый раз, когда я получаю ответ, мне нужно проверить какое-то условие, чтобы решить, следует ли мне запускать следующую итерацию. Например:итерация по шаблону url params в Scrapy

class SomeSpider(BaseSpider): 
name = 'somespider' 

offset = 0 
items = list() 

def start_requests(self): 
    return [scrapy.Request("http://somedomain.mytestsite.com/?offset="+str(self.offset), callback=self.request_iterator)] 

def request_iterator(self, response): 
    body = response.body 
    #let's say we get json as response data 
    data = json.loads(body) 
    #check if page still have data to process 
    if data["matches"]: 
     self.items.extend(data["matches"]) 
     self.offset += 100 
     return self.start_requests() 
    else: 
     #process collected data in items list 
     return self.do_something_with_items() 

Это работает, но я не могу не почувствовать что-то не так с этим кодом. Может быть, я должен использовать некоторые scrapy's rules?

ответ

1

следующие вещи можно было бы улучшить:

1) не держите элементы, как атрибут паука, вы будете потреблять очень большое количество памяти с большими входами, использовать питон генераторы вместо. Когда вы используете генераторы, вы можете без проблем получать предметы и запросы от одного обратного вызова паука.

2) start_requests используется при запуске паука, там, кажется, мало нужно переписать их в коде, если переименовать свой метод для анализа (метод по умолчанию имя выполняются как обратный вызов start_requests) код будет более читабельным

# we should process at least one item otherwise data["matches"] will be empty. 
start_urls = ["http://somedomain.mytestsite.com/?offset="+1] 

def parse(self, response): 
    body = response.body 
    #let's say we get json as response data 
    data = json.loads(body) 
    #check if page still have data to process 
    if data["matches"]: 
     for x in data["matches"]: 
      yield self.process_your_item(x) 
     self.offset += 100 
     yield self.next_request() 
    else: 
     #process collected data in items list 
     for x self.do_something_with_items(): 
      yield x 

def next_request(self): 
    return scrapy.Request("http://somedomain.mytestsite.com/?offset="+str(self.offset)) 

, возможно, даже лучше вариант обратного вызова будет:

def parse(self, response): 
    body = response.body 
    #let's say we get json as response data 
    data = json.loads(body) 
    #check if page still have data to process 
    if not data["matches"]: 
     self.logger.info("processing done") 
     return 
    for x in data["matches"]: 
     yield self.process_your_item(x) 
    self.offset += 100 
    yield self.next_request() 
+0

Спасибо! Я отредактировал свойство 'start_urls', чтобы обработать хотя бы 1 элемент +, нет необходимости в обратном вызове' next_request' из-за того, что мы все делаем в методе 'parse'. – Helvdan

Смежные вопросы