2012-01-24 2 views
0

Alors j'essaie de supprimer certaines informations sur Gasbuddy.com, mais j'ai quelques problèmes avec le code scrapy.Comment gérez-vous plusieurs formulaires déroulants grisés avec Scrapy FormRequest

voici ce que j'ai jusqu'à présent, laissez-moi savoir ce que je fais mal:

from scrapy.spider import BaseSpider 
from scrapy.selector import HtmlXPathSelector 
from scrapy.contrib.loader import XPathItemLoader 
from scrapy.http import Request 
from scrapy.http import FormRequest 

class gasBuddy(BaseSpider): 
name = "gasBuddy" 
allowed_domains = ["http://www.gasbuddy.com"] 
start_urls = [ 
    "http://www.gasbuddy.com/Trip_Calculator.aspx", 
] 

def parse(self, response): 
    hxs = HtmlXPathSelector(response) 
    #for years in hxs.select('//select[@id="ddlYear"]/option/text()'): 
     #print years 
    FormRequest(url="http://www.gasbuddy.com/Trip_Calculator.aspx", 
       formdata={'Year': '%s'%("2011")}, 
       callback=self.make('2011')) 


def make (years, self, response): 
    #this is where we loop through all of the car makes and send the response to modle 
    hxs = HtmlXPathSelector(response) 
    for makes in hxs.select('//select[@id="ddlMake"]/option/text()').extract() 
     FormRequest(url="http://www.gasbuddy.com/Trip_Calculator.aspx", 
       formdata={'Year': '%s', 'Make': '%s'%(years, makes)}, 
       callback=self.model(years, makes)) 


def model (years, makes, self, response): 
    #this is where we loop through all of the car modles and get all of the data assoceated with it. 
    hxs = HtmlXPathSelector(response) 
    for models in hxs.select('//select[@id="ddlModel"]/option/text()') 
     FormRequest(url="http://www.gasbuddy.com/Trip_Calculator.aspx", 
       formdata={'Year': '%s', 'Make': '%s', 'Model': '%s'%(years, makes, models)}, 
       callback=self.model(years, makes)) 

     print hxs.select('//td[@id="tdCityMpg"]/text()') 

mon idée de base de ce code a été de sélectionner un champ de formulaire, puis appeler un formRequest et un rappel à une autre fonction qui continue ensuite sur la boucle jusqu'à ce que j'arrive à la dernière puis je commence à lire les informations de chaque voiture. mais je continue à obtenir quelques erreurs ... un étant gasbuddy n'a aucun attribut 'encoding' (dont je n'ai aucune idée de quoi il s'agit). Je ne suis pas sûr si vous pouvez passer des périmètres à une fonction de rappel.

toute aide serait grandement appréciée.

Répondre

3

Cette réponse ne couvre que les moyens d'appeler des rappels avec des arguments supplémentaires et ne résout pas le problème avec les formulaires dynamiques pour votre site concret.

Pour passer des paramètres supplémentaires au rappel, vous pouvez utiliser functools.partial à partir de la bibliothèque Python standard.

Exemple simplifié sans Scrapy:

import functools 


def func(self, response): 
    print self, response 

def func_with_param(self, response, param): 
    print self, response, param  

def caller(callback): 
    callback('self', 'response') 

caller(func) 
caller(functools.partial(func_with_param, param='param')) 

Vous devez donc définir make et model fonctions comme celui-ci (self est toujours premier argument):

def make (self, response, years): 
    ... 

def model (self, response, years, makes): 
    ... 

et paramètre de rappel:

import functools 
... 

def parse(self, response): 
    ... 
    return FormRequest(url="http://www.gasbuddy.com/Trip_Calculator.aspx", 
         formdata={'Year': '%s'%("2011")}, 
         callback=functools.partial(self.make, years='2011')) 

Une autre option pour passer des arguments à rappel dans Scrapy est d'utiliser l'argument meta pour FormRequest

.: par exemple

def parse(self, response): 
    ... 
    return FormRequest(url="http://www.gasbuddy.com/Trip_Calculator.aspx", 
         formdata={'Year': '%s'%("2011")}, 
         meta={'years':'2011'}, 
         callback=self.make) 

def make (self, response): 
    years = response.meta['years'] 
    ... 

Et pour models similaire.

Un autre problème dans votre code, FormRequest sont seulement créés et non utilisés. Vous devez les retourner (comme dans mon parse exemple) ou les yield en boucle:

for something in hxs.select(...).extract(): 
    yield FormRequest(...) 
+0

Merci beaucoup pour une telle explication approfondie. C'est très utile. tu es mon héros. :) –

+0

@ AlexW.H.B. en essayant de faire quelque chose de similaire, pouvez-vous partager comment vous avez résolu ce problème? nouveau sur python, mais si vous partagez votre code, je pourrais comprendre, comme ayant un fond de php. –

Questions connexes