Mechanize without a form, just textbox and button - python

I've been searching Google for almost every query I can think of related to this. The page I'm trying to submit is something similar to this. There is no form. The objects are not grouped in a form. Most other threads talk about the form not having a name, but in my case, the page doesn't have a form at all.
<div class="container">
<br/>
<img id="imageXYZ" />
<br/>
<input id="inputXYZ" />
<br/>
<button id="submitObject">Go</button>
<br/>
<script type="text/javascript">blah blah blah</script>
</div>
So when there is no form, simply just an input field and button, how do I select a form so I can fill in the text box and click the button?
Thank-you so much!

To do this, I had to do 2 things to get this to work with the code above. First, I had to use this line of code to select all the objects without a form.
Br.form = Br.global_form()
Secondly, the HTML code is formatted wrong, so I had to add a parameter to my initial browser call:
Br = mechanize.Browser(factory=mechanize.RobustFactory())

Related

HTML & Python - For loops and dynamic forms creation

I am new working with HTML and Python, and I am trying to develop some code for personal use.
The goal is to show the different leagues with a color code: red or green, and if I click on a league, it opens a different tab with more detailes information of that league, that is to say, it would be necessary to send the id of the league to the server to be able to use it for the next tab. I am trying to use a form, but it is not working.
The if-else condition is just to choose whether the color is red or green based on a league condition.
The problem I am having is that, creating the form with the for loop as I am doing, the league id that sends is always the same (1st league of the lopp), it is not dynamic, then I would like to know how to program it to be able to see the chosen league.
No matter on what league you click, you always access the same league information. I guess there is something wrong with the code because it is not dynamic, it does not display info based on my selection.
My idea was to have multiple forms created with the loop, one for each league, but it doesnt work.
I would really appreciate your help, thank you very much!
This is the HTML code:
competicionesAPIDict is a dict where the key is the country and the values the different leagues that exists in it.
competicionesAPI is the value obtained from the dict, that is iterated to get the info from each league.
<div style="width: 80%; height: 70%; background-color: azure; width: max-content">
{% for paisAPI, competicionesAPI in competicionesAPIDict.items() %}
<div class="div_pais">
<h4>{{paisAPI}} </h4>
<img src={{dict_banderas_pais[paisAPI]}} alt="No funciona" width="30px" height="30px"/>
{% for competicionAPI in competicionesAPI %}
{% if dict_hay_competicion[competicionAPI['id']] %}
<form name="siCompeticion"+{{competicionAPI['id']}} method="POST" action="/RAI/API/competicion">
<input type="hidden" name="id_competicion" value={{competicionAPI['id']}} />
<a href=/RAI/API/competicion style="font-size: 14px;margin-left: 17px;color: green;"
onclick="document.forms[0].submit();return false;">{{competicionAPI['name']}}</a>
</form>
{% else %}
<form name="noCompeticion"+{{competicionAPI['id']}} method="POST" action="/RAI/API/competicion">
<input type="hidden" name="id_competicion" value={{competicionAPI['id']}} />
<a href=/RAI/API/competicion style="font-size: 14px;margin-left: 17px;color: red;"
onclick="document.forms[0].submit();return false;">{{competicionAPI['name']}}</a>
</form>
{% endif %}
{% endfor %}
</div>
{% endfor %}
OK, I was wrong in a comment about hidden input field value being a problem.
I mean, it is still a problem, but it should work as is, except for JS code bug you made.
So first, what gave me wrong impression was that you would usually make one form per request, and then do as I said, set the forms values correctly to provide data of the request upon submit. You made a lot of forms, one per iteration, which is not wrong, but what you did is say in onclick event to activate always the first form on the site. I.e.
document.forms[0]
so, whatever you click, only first form will be submitted with the value of the first hidden input field in it.
As you have if-else clauses, I wouldn't rely on form indexes within the DOM, but use something to create unique IDs per each form, then use document.getElementById() to get that exact form and submit it. But you already gave your forms names, so you can use those with document.getElementsByName() or give the form an ID of same value.
Names does not need to be unique, IDs should.
Just a little sample:
<form id="siCompeticion"+{{competicionAPI['id']}} ...>
<input type="hidden" name="something" value={{competicionAPI['id']}}>
CLICK ME
</form>
In your place I would most probably write a little JS code to perform AJAX request, most likely using jquery. In any case, I would avoid making a lot of forms.

Capture HTML textbox value in python without CGI

I need to get the user input in a textbox and process it using my python script when user presses Submit button. Unfortunately I am using an external server that does not support CGI. Is there any other way I can do this? This is my sample HTML.
<body>
<form name="form1" method="post" action="script1.py">
<div id="heading"><big><big><big>My analysis</big></big></big></div>
<textarea cols="50" rows="1" name="Query_text" id="Query_text"></textarea>
<div id="Button"><input name="Submit" value="Submit" type="submit"></div>
</form>
</body>
You can do the form processing with Javascript but hopefully you don't want to save this input beyond the next page the person accesses. Another old school option is emailing yourself the contents of Query_text. But honestly this is a lot more work than you want to do and not worth the effort (for most people). What you need is a new web host.

Using button on a page with python

I am scraping a page for some data, however I need to insert text into a text box, submit the form and scrape the result page. I looked at the page source, but I'm not sure how to activate the button or pass down the argument for it.
Website is http://archive.org/web/web.php
Trying to look at some historicals, and no idea what to use for this. Open to any solution
First you should know that click on that button usually does a POST to some urls, passes the data in that form, here is:
<form id="wwmform" name="wwmform" method="get" action="http://web.archive.org/form-submit.jsp" onsubmit="document.location.href='http://web.archive.org/web/*/'+document.getElementById('wwmurl').value;return false;" style="display:inline;">
<input id="wwmurl" type="text" name="url" size="50" value="http://">
<button type="submit" name="type" value="urlquery" class="roundbox5">Take Me Back</button>
</form>
you see the action attribute? That's where the data goes to.
So in python, you may need urllib and urllib2 to encode the data and post it to the target url and then fetch the outcome.
ps: watch out the onsubmit

twitter bootstrap href button does not work

I am creating a html template for a django based app. I am using the twitter bootstrap API for buttons here, but one of them (the cancel button) doesn't seem to be working correctly. I link it to another page using an href, but when I click on the button, it redirects to the current page's post method. See below:
<h2>Add new Schedule:</h2>
<form class="form-horizontal" method='post'>
<table>
{% load bootstrap %}
{{ form|bootstrap }}
{% csrf_token %}
<tr>
<td></td>
<td>
<input class="btn btn-primary" type='submit' name='reset' value='Save' />
</td>
<td></td>
<td>Cancel</button></td>
</tr>
</table>
</form>
However, if I get rid of the button and use it as a simple href it seems to work:
<td><a href='{%url head.views.edit_instance_binding binding.id %}'>Cancel</a></td>
What's going on here?
You have a <button> inside an <a> element - get rid of the button, otherwise you'll be submitting your form.
If you want your anchor to be styled as a button, give it a btn class.
And Bootstrap is just a big set of CSS facilities with little js thrown in - no APIs at all :))
EDIT: nowadays HTML semantics and appearance are well separated [though someone may argue that Bootstrap has its hacks regarding this, see its <i>'s use for icons].
Keeping the eye on your case, you wanted to use a <button> to style a simple anchor like an embossed button. But a <button> tag is just a way to provide a richer <input type="submit">, in which you can insert images for example [see all the BS examples with icons beside buttons].
Well, <input type="submit"> and <button> inside a <form> trigger the latter's action, i.e. they post some data the user entered to such location.
If you just need to reach some URL without submitting anything, you need an anchor tag [<a>], which can be styled as you wish, e.g. with BS btn, btn-primary, btn-whateva classes.

Python mechanize - two buttons of type 'submit'

I have a mechanize script written in python that fills out a web form and is supposed to click on the 'create' button. But there's a problem, the form has two buttons. One for 'add attached file' and one for 'create'. Both are of type 'submit', and the attach button is the first one listed. So when I select the forum and do br.submit(), it clicks on the 'attach' button instead of 'create'. Extensive Googling has yielded nothing useful for selecting a specific button in a form. Does anyone know of any methods for skipping over the first 'submit' button and clicking the second?
I tried using the nr parameter, without any luck.
I was able to get it to work with a combination of the name and label parameters, where "label" seems to correspond to the "value" in the HTML:
Here are my two submit buttons:
<input type="submit" name="Preview" value="Preview" />
<input type="submit" name="Create" value="Create New Page" />
... and here's the code that clicks the first one, goes back, and then clicks the second:
from mechanize import Browser
self.br = Browser()
self.br.open('http://foo.com/path/to/page.html')
self.br.select_form(name='my_form')
self.br['somefieldname'] = 'Foo'
submit_response = self.br.submit(name='Preview', label='Preview')
self.br.back()
self.br.select_form(name='my_form')
self.br['somefieldname'] = 'Bar'
submit_response = self.br.submit(name='Create', label='Create New Page')
There's a variant that also worked for me, where the "name" of the submit button is the same, such as:
<input type="submit" name="action" value="Preview" />
<input type="submit" name="action" value="Save" />
<input type="submit" name="action" value="Cancel" />
and
self.br.select_form(name='my_form')
submit_response = self.br.submit(name='action', label='Preview')
self.br.back()
submit_response = self.br.submit(name='action', label='Save')
IMPORTANT NOTE - I was only able to get any of this multiple-submit-button code to work after cleaning up some HTML in the rest of the page.
Specifically, I could not have <br/> - instead I had to have <br /> ... and, making even less sense, I could not have anything between the two submit buttons.
It frustrated me to no end that the mechanize/ClientForm bug I hunted for over two hours boiled down to this:
<tr><td colspan="2"><br/><input type="submit" name="Preview" value="Preview" /> <input type="submit" name="Create" value="Create New Page" /></td></tr>
(all on one line) did not work, but
<tr><td colspan="2"><br />
<input type="submit" name="Preview" value="Preview" />
<input type="submit" name="Create" value="Create New Page" /></td></tr>
worked fine (on multiple lines, which also shouldn't have mattered).
I like mechanize because it was easy to install (just copy the files into my include directory) and because it's pretty simple to use, but unless I'm missing something major, I think that bugs like this are kind of awful - I can't think of a good reason at all why the first example there should fail and the second should work.
And, incidentally, I also found another mechanize bug where a <textarea> which is contained within a <p> is not recognized as a valid control, but once you take it out of the <p> container it's recognized just fine. And I checked, textarea is allowed to be included in other block-level elements like <p>.
I would suggest you to use Twill which uses mechanize (mostly monkeypatched).
So say you have form with some fields and two submit buttons with names "submit_to_preview" and "real_submit". Following code should work.
BTW remember this is not threadsafe so you might want to use locks in case if you want to use the code in a threaded env.
import twill.commands
b = twill.get_browser()
url = "http://site/myform"
twill.commands.go(url)
twill.commands.fv("2", "name", "Me")
twill.commands.fv("2", "age", "32")
twill.commands.fv("2", "comment", "useful article")
twill.commands.browser.submit("real_submit")
Hope that helps. Cheers.
Use the 'click' method. E.g.
mybrowser.select_form(nr=0)
req = mybrowser.click(type="submit", nr=1)
mybrowser.open(req)
Should work.
I can talk from experience using HTTP, rather than mechanize, but I think this is probably what you want.
When there are two submit buttons in a form, a server can determine which one was pressed, because the client should have added an argument for the submit button. So:
<form action="blah" method="get">
<p>
<input type="submit" name="button_1" value="One" />
<input type="submit" name="button_2" value="Two" />
</p>
</form>
Will take you either the URL:
blah?button_1=One
or:
blah?button_2=Two
Depending on which button was pressed.
If you're programatically determining what arguments are going to be sent, you need to add an argument with the name of the submit button that was pressed, and it's value.

Categories

Resources