2012-10-24 18 views
5

Napisałem pająka za pomocą scrapy, który tworzy całą masę żądań HtmlXPathSelector na osobne witryny. Tworzy wiersz danych w pliku .csv po spełnieniu każdego żądania (asynchronicznie). Niemożliwe jest sprawdzenie, która prośba jest spełniona jako ostatnia, ponieważ żądanie jest powtarzane, jeśli nie wyodrębniono jeszcze danych (czasami kilka razy pomija dane). Mimo że zaczynam od uporządkowanej listy, wynik jest pomieszany, ponieważ wiersze są zapisywane natychmiast po wyodrębnieniu danych.Funkcja Python Scrapy do wywołania tuż przed wysłaniem sygnału spider_closed?

Teraz chciałbym posortować tę listę na podstawie jednej kolumny, ale po każdym żądaniu jest wykonywana. Czy sygnał "spider_closed" może być użyty do aktywacji prawdziwej funkcji? Jak poniżej, próbowałem połączyć sygnał z dyspozytorem, ale ta funkcja wydaje się drukowała tylko rzeczy, zamiast pracować ze zmiennymi, a nawet wywoływać inne funkcje.

def start_requests(self) 
    ... dispatcher.connect(self.spider_closed, signal=signals.engine_stopped) .... 


def spider_closed(spider): 
    print 'this gets printed alright' # <-only if the next line is omitted... 
    out = self.AnotherFunction(in)  # <-This doesn't seem to run 
+0

Myślę, że można dołączyć więcej niż 1 funkcję do sygnału. Czy to rozwiązałoby twój problem? –

+0

Możesz w rzeczywistości połączyć funkcję z sygnałem ... Wierzę, że moim rzeczywistym problemem była struktura "scrapy" - zostało to rozwiązane przez utworzenie pliku .py, który najpierw przechodzi przez pająk, a następnie sortuje plik wyjściowy później. Pomogło to niezmiernie: http://snipplr.com/view/67012/selfcontained-script-to-crawl-a-site-updated-scrapy-130dev/ – corg

+1

Nie powinien dispatcher.connect (...) być w __init __ () zamiast start_requests()? – imwilsonxu

Odpowiedz

0

Zhackowałem razem rurociąg, aby rozwiązać ten problem.

file: Project.middleware_module.SortedCSVPipeline

import csv 
from scrapy import signals 


class SortedCSVPipeline(object): 

    def __init__(self): 
     self.items = [] 
     self.file_name = r'YOUR_FILE_PATH_HERE' 
     self.key = 'YOUR_KEY_HERE' 

    @classmethod 
    def from_crawler(cls, crawler): 
     pipeline = cls() 
     crawler.signals.connect(pipeline.spider_closed, signals.spider_closed) 
     return pipeline 

    def spider_closed(self, spider): 
     for item in sorted(self.items, key=lambda k: k[self.key]): 
      self.write_to_csv(item) 

    def process_item(self, item, spider): 
     self.items.append(item) 
     return item 

    def write_to_csv(self, item): 
     writer = csv.writer(open(self.file_name, 'a'), lineterminator='\n') 
     writer.writerow([item[key] for key in item.keys()]) 

file: settings.py

ITEM_PIPELINES = {"Project.middleware_module.SortedCSVPipeline.SortedCSVPipeline" : 1000} 

Po uruchomieniu tego nie trzeba będzie używać eksportera artykuł ponieważ już to zrobi rurociąg csv pisząc dla ciebie. Ponadto 1000 w wejściu potoku w twoim ustawieniu musi mieć wyższą wartość niż wszystkie inne potoki, które chcesz uruchomić przed tym. Przetestowałem to w moim projekcie i otrzymałem plik CSV posortowany według podanej kolumny! HTH

Pozdrowienia

+0

Cóż, nie zauważyłem, że to było z 2012 roku ... Mam nadzieję, że pomaga komuś lol – rocktheartsm4l

+0

Dziękuję za wskrzeszenie tego jednego haha ​​- nie masz już projektu, ale ufam, że to by zadziałało – corg