2016-04-13 12 views
0

Meine Spinne sieht aus wie dieseIst es möglich, Pipelines zu betreiben und gleichzeitig mehrere URLs in scrapy zu crawlen?

from scrapy.linkextractors import LinkExtractor 
from scrapy.spiders import CrawlSpider, Rule 
from scrapy.http import Request 
from ProjectName.items import ProjectName 

class SpidernameSpider(CrawlSpider): 
    name = 'spidername' 
    allowed_domains = ['webaddress'] 
    start_urls = ['webaddress/query1'] 

    rules = (
      Rule(LinkExtractor(restrict_css='horizontal css')), 
      Rule(LinkExtractor(restrict_css='vertical css'), 
        callback='parse_item') 
      ) 

    def parse_item(self, response): 
     item = ProjectName() 
     1_css = 'css1::text' 
     item['1'] = response.css(1_css).extract() 

     item = ProjectName() 
     2_css = 'css2::text' 
     item['2'] = response.css(2_css).extract() 
     return item 

und meine Pipeline wie folgt aus:

from scrapy.exceptions import DropItem 

class RemoveIncompletePipeline(object): 
    def reminc_item(self, item, spider): 
     if item['1']: 
      return item 
     else: 
      raise DropItem("Missing content in %s" % item) 

Alles funktioniert gut, wenn der Wert für das Feld 1 ist, dann fehlt, wird der coresponding Artikel aus der Ausgabe herausgenommen .

Aber, wenn ich start_urls ändern, um die Arbeit für mehrere Abfragen zu tun, wie folgt aus:

f = open("queries.txt") 
start_urls = [url.strip() for url in f.readlines()] 
f.close() 

oder so:

start_urls = [i.strip() for i in open('queries.txt').readlines()] 

Dann ist der Ausgang enthält die Elemente mit fehlenden Wert für Feld 1.

Was ist los? Und wie kann ich das vermeiden?

Für die Aufzeichnung queries.txt sieht wie folgt aus:

webaddress/query1
webaddress/query2

+0

@rook, thx für die Bearbeitung – crocefisso

+0

Aus Interesse, sind die URLs auf dem gleichen Server/Domain? Wenn dies der Fall ist, werden Sie sie nicht parallelisieren wollen, es sei denn, Sie sind sich sicher, dass die Trefferrate keine IP-Blockierung verursacht. – halfer

+0

Tatsächlich stammen sie aus derselben Domäne, da es sich um die Eingabe von Suchanfragen in einer Suchmaschine handelt, bei der es sich um Links innerhalb der Domäne handelt. Was würdest du empfehlen, um nicht blockiert zu werden? Ich wurde bisher nicht blockiert, da ich nicht mehr als 50 Testobjekte abrufen konnte. Ich möchte 500.000 Artikel erhalten, aufgeteilt in 15 bis 30 Suchanfragen. – crocefisso

Antwort

2

Nach dem docs Sie start_requests Methode überschreiben sollte.

Diese Methode muss ein Iterable mit den ersten Requests zum Crawlen für diese Spinne zurückgeben.

Dies ist die Methode, die von Scrapy aufgerufen wird, wenn die Spinne für Scraping geöffnet wird, wenn keine bestimmten URLs angegeben sind. Wenn bestimmte URLs angegeben sind, wird make_requests_from_url() stattdessen verwendet, um die Anfragen zu erstellen. Diese Methode wird auch nur einmal von Scrapy aufgerufen, also ist es sicher, es als Generator zu implementieren.

from scrapy.linkextractors import LinkExtractor 
from scrapy.spiders import CrawlSpider, Rule 
from scrapy.http import Request 
from ProjectName.items import ProjectName 

class SpidernameSpider(CrawlSpider): 
    name = 'spidername' 
    allowed_domains = ['webaddress'] 
    start_urls = ['webaddress/query1'] 

    rules = (
      Rule(LinkExtractor(restrict_css='horizontal css')), 
      Rule(LinkExtractor(restrict_css='vertical css'), 
        callback='parse_item') 
      ) 

    def start_requests(self): 
     return [scrapy.Request(i.strip(), callback=self.parse_item) for i in open('queries.txt').readlines()] 

    def parse_item(self, response): 
     item = ProjectName() 
     1_css = 'css1::text' 
     item['1'] = response.css(1_css).extract() 

     item = ProjectName() 
     2_css = 'css2::text' 
     item['2'] = response.css(2_css).extract() 
     return item 

UPD: einfach diesen Code setzen in Ihr Spinne Klasse

def start_requests(self): 
    return [scrapy.Request(i.strip(), callback=self.parse_item) for i in open('queries.txt').readlines()] 

UPD: Ihr haben eine falsche Logik in Ihrem parse_item Methode. Sie müssen es beheben.

def parse_item(self, response): 
    for job in response.css('div.card-top') 
     item = ProjectName() 
     # just quick example. 
     item['city'] = job.xpath('string(//span[@class="serp-location"])').extract()[0].replace(' ', '').replace('\n', '') 
     # TODO: you should fill other item fields 
     # ... 
     yeild item 
+0

Vielen Dank, ich werde es versuchen. Soll ich 'start_urls = ['webaddress/query1']'? – crocefisso

+0

Funktioniert nicht, hier ist der [log] (https://www.dropbox.com/s/l77o50rao9osqoj/scrapylog.txt?dl=0) – crocefisso

+0

Sie haben einige Fehler in Ihrer 'parse_item' Methode. Ich korrigierte den Anwser, überprüfe es noch einmal. Stellen Sie eine neue Frage, wenn Sie ein Problem mit Selektoren haben. Ihr Protokoll zeigt, was scrapy mehrere Start-URLs anruft, diese Frage ist gelöst –

Verwandte Themen