2017-07-13 4 views
1

Ich möchte eine Webseite scrape, die zuerst eine AJAXFormPost senden, die eine Sitzung öffnen und als nächstes ein _SearchResultGridPopulate senden, um ein Steuerelement zu füllen, das ich scrape benötigen, ist die Antwort ein JSON . Wie spinne sequenziell zu Websites, die Sitzung in scrapy verwenden

dies ist ein Fragment von meinem Code:

def parse_AjaxFormPost(self, response): 
     self.logger.info("parse_AjaxFormPost") 
     page = response.meta['page'] 
     header = { 
       'Accept':'*/*', 
       'Accept-Encoding':'gzip, deflate, br', 
       'Accept-Language':'en-US,en;q=0.8', 
       'Connection':'keep-alive', 
       'Content-Length':'14', 
       'Content-Type':'application/x-www-form-urlencoded', 
       'Cookie':'ASP.NET_SessionId=gq4dgcsl500y32xb1n2ciexq', 
       . 
       . 
       . 
      } 
     url = '<url>/Search/AjaxFormPost' 
     cities = ['city1','city2',...] 
     for city in cities: 
      formData = { 
         'City':city 
      } 
      re = scrapy.FormRequest(
      url, 
      formdata=formData, 
      headers=header, 
      dont_filter=True, 
      callback=self.parse_GridPopulate 
      ) 
      yield re 

def parse_GridPopulate(self,response): 
     self.logger.info("parse_LookupPermitTypeDetails") 
     url = '<url>/Search//_SearchResultGridPopulate?Grid-page=2&Grid-size=10&Grid-CERT_KEYSIZE=128&Grid-CERT_SECRETKEYSIZE=2048&Grid-HTTPS_KEYSIZE=128&Grid-HTTPS_SECRETKEYSIZE=2048' 
     header = { 
       'Accept':'*/*', 
       'Accept-Encoding':'gzip, deflate, br', 
       'Accept-Language':'en-US,en;q=0.8', 
       'Connection':'keep-alive', 
       'Content-Length':'23', 
       'Content-Type':'application/x-www-form-urlencoded', 
       'Cookie':'ASP.NET_SessionId=gq4dgcsl500y32xb1n2ciexq', 
       . 
       . 
       . 
     } 
     formData = { 
        'page':'1', 
        'size':'10' 
      } 
     re = scrapy.FormRequest(
     url, 
     formdata=formData, 
     headers=header, 
     dont_filter=True, 
     callback=self.parse 
     ) 

     yield re   


    def parse(self, response): 
     self.logger.info("parse_permit") 
     data_json = json.loads(response.body) 
     for row in data_json["data"]: 
      self.logger.info(row) 
      item = RedmondPermitItem() 
      item["item1"] = row["item1"] 
      item["item2"] = row["item2"] 
      yield item 

Das Problem ist, dass scrapy gleichzeitige beantragt und wann, und die Anforderung in parse_AjaxFormPost eine Sitzung öffnen, damit, wenn der Ball zu parse_LookupPermitTypeDetails ich die Sitzung der letzten bekam Bitte machen Sie es in parse_AjaxFormPost. Wenn ich also 10 Städte am Ende habe, habe ich 10 Mal die Informationen der letzten Stadt bekommen.

In Einstellungen geändert ich die Konfiguration:

CONCURRENT_REQUESTS_PER_DOMAIN = 1 
CONCURRENT_REQUESTS_PER_IP = 1 

Und es funktioniert nicht. Auf der anderen Seite dachte ich für eine Stadt der Spinne nur wie jedes Mal etwas

from twisted.internet import reactor, defer 
from scrapy.crawler import CrawlerRunner 
from scrapy.utils.log import configure_logging 
class MySpider(scrapy.Spider): 
# Your first spider definition 
... 
... 
configure_logging() 
runner = CrawlerRunner() 
@defer.inlineCallbacks 
def crawl(): 
    cities = ['city1','city2',...] 
     for city in cities: 
      yield runner.crawl(MySpider1,city=city) 
reactor.stop() 
crawl() 
reactor.run() # the script will block here until the last crawl call is finished 
in liefen

Vielleicht kann dies die einzige Lösung sein, aber ich bin mir nicht sicher. Ich möchte ein Verfahren für jede Website mit diesem Merkmal erstellen.

Irgendein Vorschlag darüber, wie man das löst, ist es möglich, dies nur Konfigurationseinstellungen zu erreichen.

danke im voraus.

Update1 ich ändern Sie den Titel, weil wichtig ist, dass für Websites, die Sitzung zu verwenden ist

Antwort

1

Dies ist ein Problem, das Verständnis, wie Gleichzeitigkeit funktioniert, da dies wird Sie noch nicht sequentiell Parallelität arbeiten, aber zwischen Rückrufe. Ich würde so etwas wie dies vorschlägt:

def parse_AjaxFormPost(self, response): 
    ... 
    cities = ['city1','city2',...] 
    formData = { 
       'City':cities[0] 
    } 
    re = scrapy.FormRequest(
     url, 
     formdata=formData, 
     headers=header, 
     dont_filter=True, 
     callback=self.parse_remaining_cities, 
     meta={'remaining_cities': cities[1:]}, # check the meta argument 
    ) 
    yield re 

def parse_remaining_cities(self, response): 
    remaining_cities = response.meta['remaining_cities'] 
    current_city = remaining_cities[0] 
    ... 
    yield Request(
     ..., 
     meta={'remaining_cities': remaining_cities[1:]}, 
     callback=self.parse_remaining_cities) 

diese Weise können Sie eine Anfrage zu einer Zeit und in einer Reihe von Stadt zu Stadt tun.

+0

Ich überprüfe und teste deine Antwort, aber ich fahre mit Problemen mit der Sitzung fort, weil ich brauche, dass eine Stadt nicht verarbeitet wird, bis alle Anfrage in Bezug auf die aktuelle Stadt mit der nächsten Stadt fortfahren – Cyberguille

Verwandte Themen