2012-10-24 21 views
5

Siteleri ayırmak için bir grup HtmlXPathSelector Requests yapan scrapy kullanarak bir örümcek yazdım. Her istek (asenkronize) memnun olduktan sonra bir .csv dosyasında bir veri satırı oluşturur. En son hangi talebin yerine getirildiğini görmek imkansızdır, çünkü henüz veri alınmadığı takdirde talep tekrarlanır (bazen verileri birkaç kez kaçırır). Düzgün bir listeyle başlasa bile, çıktılar, veri ayıklandıktan hemen sonra satırlar yazıldığından karıştırılır.Python Scrapy işlevi spider_closed sinyali gönderilmeden hemen önce çağrılacak mı?

Şimdi bu listeyi bir sütuna göre sıralamak istiyorum, ancak her istek yapıldıktan sonra. 'spider_closed' sinyali gerçek bir işlevi tetiklemek için kullanılabilir mi? Aşağıda olduğu gibi, sinyali dağıtıcıyla birleştirmeyi denedim, ancak bu işlev değişkenlerle çalışmak yerine ve hatta başka işlevleri çağırmak yerine yalnızca işleri yazdırıyor gibi görünüyor.

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

Sana bir sinyale 1'den fazla işlev eklemeyi düşünüyorum. Bu sorununuzu çözer mi? –

+0

Aslında, bir sinyale bir işlevi bağlayabilirsiniz ... Asıl sorunumun 'scrapy' yapısıyla olduğuna inanıyorum - bu, örümcek ile ilk önce çalıştırmak için bir .py dosyası oluşturarak çözüldü ve sonra daha sonra çıktı dosyası. Bu çok yardımcı oldu: http://snipplr.com/view/67012/selfcontained-script-to-crawl-a-site-updated-scrapy-130dev/ – corg

+1

dispatcher.connect (...) __init __ olması gerekir () start_requests() yerine? – imwilsonxu

cevap

0

Sizin için bu sorunu çözmek için birlikte bir boru hattını çarptım.

dosyası: 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()]) 

dosyası: settings.py

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

bu çalıştırırken bu boru hattı yapacak çünkü artık bir öğe ihracatçısı kullanmaya gerek olmayacak csv sizin için yazıyor. Ayrıca, ayarınızdaki boru hattı girişindeki 1000 numara, bundan önce çalıştırmak istediğiniz diğer tüm boru hatlarından daha yüksek bir değere sahip olmalıdır. Bunu projemde test ettim ve belirtilen sütun tarafından sıralanmış bir csv dosyasıyla sonuçlandı! HTH

Alkış

+0

Peki, bunun 2012'den beri olduğunu fark etmedim ... Umarım birisine yardım eder – rocktheartsm4l

+0

Bu bir hah'ı diriltdiğiniz için teşekkürler - daha fazla projeye sahip olmayın, ama bu işe yarayacak – corg

İlgili konular