2015-07-26 1 views
0

Je suis en train de créer un programme qui remplira un formulaire sur ce site: Insurance surveyPeut mécaniser le support ajax/remplir des formulaires via javascript?

J'utilise Python 2.7 et mécaniser après de nombreuses tentatives de 3,4 et la réalisation ne mécaniser fonctionne pas avec 3.4. Je suis novice mais j'ai beaucoup appris en essayant de le faire (python est génial).

import mechanize 
br = mechanize.Browser() 
urlofmypage = 'https://interactive.web.insurance.ca.gov/survey/' 
br.open(urlofmypage) 
print br.geturl() 
br.select_form(nr=0) 

br['location'] = ['ALAMEDA BERKELEY'] #SET FORM ENTRIES 
br['coverageType'] = ['HOMEOWNERS'] 
br['coverageAmount'] = ['$150,000'] 
br['homeAge'] = ['1-3 Years'] 

result = br.submit() 
print result 

Ceci est mon erreur: mechanize._form.ItemNotFoundError: articles insuffisants avec le nom « 150 000 $ »

Le problème est, seulement après que je remplir les champs du formulaire emplacement et coverageType puis effectuez les options pour coverageAmount montrez-vous: (.) ​​J'ai été déconner avec cela et regarder de nombreuses vidéos en ligne et toutes mes recherches m'ont conduit à conclure que la mécanisation ne fera pas cela.J'ai aussi lu que c'est un appel ajax

, et mécaniser ne fonctionnera pas pour cela.Les choses semblent pointer vers webdriver sélénium ... Quelqu'un at-il une entrée?

+0

Mechanize ne supporte pas JavaScript, et ne supporte donc pas ajax. – mhawke

Répondre

3

Les appels AJAX sont effectués par javascript et mécanize n'a aucun moyen d'exécuter javascript. Mechanize ne regarde que les champs de formulaire sur une page HTML statique et vous permet de remplir les champs &. C'est pourquoi votre recherche vous pointe vers des choses comme Selenium ou Ghost, qui courent sur un vrai navigateur qui peut exécuter javascript.

Il existe une façon plus simple de faire cela! Si vous utilisez les outils de développement sur votre navigateur (par exemple, l'onglet Réseau dans Firefox ou Chrome) et remplissez le formulaire que vous pouvez voir la demande de votre navigateur fait dans les coulisses, même avec AJAX:

Network tab in Firefox

cela vous dit:

  • Le navigateur fait une demande POST
  • a cette URL: https://interactive.web.insurance.ca.gov/survey/survey?type=homeownerSurvey&event=HOMEOWNERS
  • Avec le formulaire suivant params:
    • emplacement = ALAMEDA + ALAMEDA
    • coverageType = PROPRIÉTAIRES
    • coverageAmount = 150000
    • Homeage = New

Vous pouvez utiliser ces informations pour faire la même requête POST en Python :

import urllib.parse, urllib.request 

url = "https://interactive.web.insurance.ca.gov/survey/survey?type=homeownerSurvey&event=HOMEOWNERS" 
data = urllib.parse.urlencode(dict(
    location="ALAMEDA ALAMEDA", 
    coverageType="HOMEOWNERS", 
    coverageAmount="150000", 
    homeAge="New", 
)) 
res = urllib.request.urlopen(URL, data.encode("utf8")) 

print(res.read()) 

Ceci est python3. La bibliothèque requests fournit une API encore plus agréable pour faire des requêtes HTTP.


Modifier: En réponse à vos trois questions:

is it possible for the dictionary that you've created to have more than 1 location and cycle through them using a for loop?

Oui, il suffit d'ajouter une boucle autour du code et passer une valeur différente pour location chaque fois. Je mets ce code dans une fonction pour rendre le code plus propre, comme ceci:

https://gist.github.com/lost-theory/08786e3a27c8d8ce3839

the results are in a lot of jibberish, so I'd have to find a way to sift through it huh. Like pick out which is which

Oui, le charabia est HTML que vous devrez analyser pour recueillir les données que vous cherchez . Regardez HTMLParser dans la bibliothèque standard de python, ou installez une bibliothèque comme lxml ou BeautifulSoup, qui ont une API un peu plus agréable. Vous pouvez également essayer d'analyser le texte à la main en utilisant str.split.

Si vous voulez convertir les lignes en python list s de la table, vous aurez besoin de trouver toutes les lignes qui ressemblent à ceci:

<tr Valign="top"> 
    <td align="left">Bankers Standard <a href='http://interactive.web.insurance.ca.gov/companyprofile/companyprofile?event=companyProfile&doFunction=getCompanyProfile&eid=5906'><small>(Info)</small></a></td> 
    <td align="left"><div align="right">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;N/A</td> 
    <td align="left"><div align="right">250</div></td> 
    <td align="left">&nbsp;</td> 
    <td align="left">Bankers Standard <a href='http://interactive.web.insurance.ca.gov/companyprofile/companyprofile?event=companyProfile&doFunction=getCompanyProfile&eid=5906'><small>(Info)</small></a></td> 
    <td align="left"><div align="right">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1255</td> 
    <td align="left"><div align="right">500</div></td> 
    </tr> 

Vous voulez faire une boucle sur tous les éléments <tr> (ligne) , en saisissant tous les éléments <td> (colonne) à l'intérieur de chaque ligne, puis nettoyez le texte dans chaque colonne (en supprimant ces espaces &nbsp;, etc.).

Il y a beaucoup de questions sur StackOverflow et des tutoriels sur internet sur comment analyser ou gratter du HTML en python, comme this ou this.

could you explain why we had to do the data.encode line

Sûr! Dans le documentation for urlopen, il est dit:

data must be a bytes object specifying additional data to be sent to the server, or None if no such data is needed.

La fonction urlencode retourne une chaîne unicode, et si nous essayons de passer cela en urlopen, nous obtenons cette erreur:

TypeError: POST data should be bytes or an iterable of bytes. It cannot be of type str. 

Nous utilisons donc data.encode('utf8') pour convertir la chaîne unicode en octets. Vous devez généralement utiliser des octets pour l'entrée & comme lire ou écrire des fichiers sur le disque, envoyer ou recevoir des données sur le réseau comme des requêtes HTTP, etc. This presentation a une bonne explication des octets par rapport aux chaînes Unicode en python et pourquoi vous avez besoin décoder/encoder en faisant des E/S.

+0

Il n'y a pas d'appels ajax sur cette page - c'est la soumission de formulaire standard. Néanmoins, l'information sur la publication avec les demandes est utile. – mhawke

+0

@mhawke: Bon point. –

+0

Vous m'avez aidé à faire en peu de temps ce que j'essayais de faire depuis quelques semaines ... toutes mes ressources d'apprentissage en ligne m'ont amené à mécaniser et beautifulsoup, mais vous l'avez fait en utilisant urllib.parse et urllib .demande. Props bro !! Pardonnez-moi si je suis noob, mais est-il possible que le dictionnaire que vous avez créé ait plus d'un emplacement et que vous le parcouriez à l'aide d'une boucle for? En outre, les résultats sont dans beaucoup de charabia, donc je devrais trouver un moyen de passer au cri par le biais hein. Comme choisir lequel est qui? Enfin, pourriez-vous expliquer pourquoi nous devions utiliser la ligne data.encode? –

0

Aucun appel AJAX n'est effectué par cette page. C'est un simple code Javascript qui est exécuté à partir d'un événement onchange pour la case de sélection "Type de couverture:".

Si vous regardez la source de la page, vous verrez que toutes les valeurs sont stockées dans la fonction Javascript coverageTypeOnChange(). De cela, vous pouvez déterminer ce qu'il faut publier pour tous les cas. Pourvu que ces valeurs ne changent pas, vous serez en mesure d'automatiser le raclage du site sans exécuter de code Javascript. Si, toutefois, les valeurs changent au fil du temps (par exemple, comme le font habituellement les primes), alors vous feriez mieux de regarder Selenium ou d'autres navigateurs sans tête.

+0

En travaillant sur tous les postes, voulez-vous dire ce dont parle Steven K. ci-dessous? ou voulez-vous dire changer la valeur du formulaire d'entrée (désolé im novice) –

0

Ce problème m'a donné un gros mal de tête une fois.En ce qui concerne la ligne suivante:

br['location'] = ['ALAMEDA BERKELEY'] #SET FORM ENTRIES 

Cela implique que vous sélectionnez « ALAMEDA BERKELEY » dans une liste. Si oui, essayez d'ajouter une virgule après l'article:

br['location'] = ['ALAMEDA BERKELEY',] 

Sinon, utilisez:

br['location'] = 'ALAMEDA BERKELEY' 

J'essaie souvent des solutions de contournement élaborées pour mécaniser les problèmes, pour revenir à mon code d'origine et faire une légère modification ... très puissant, très impitoyable