Use mechanize to select correct submit button - python

I'm using mechanize in my Python script to access web page sources. One of the pages I want to access uses two buttons to ask if I am 21 or not. I'm very new to python, and after searching all day, I can't figure out how to select the correct button in the same form because they have the same name. Printing the forms yields:
<SubmitButtonControl(over21=no) (readonly)>
<SubmitButtonControl(over21=yes) (readonly)>>
The HTML for the buttons, which are in the same form:
<button class="c-btn c-btn-primary" type="submit" name="over21"value="no">no thank you</button>
<button class="c-btn c-btn-primary" type="submit" name="over21"value="yes">continue</button>
What I've tried:
thisone = br.select_form(name='over21=yes')
br.submit(thisone)
Which yields error:
File "build/bdist.linux-armv7l/egg/mechanize/_mechanize.py", line 524,in select_form
mechanize._mechanize.FormNotFoundError: no form matching name 'over21=yes'
I've also tried
br.submit(nr=1)
which was suggested by another post, but I believe that is selecting a whole different form for me.
Any advice welcome! And yes, I am over 21! Thanks,

Related

Html form open's file in text insted of showing output from python code

This form shuld show the output on current page
<div class="form">
<form action="QA.py" method="POST" onsubmit="return false; >
<label for="form-search"></label>
<input type="text" id="form-search" placeholder="Search code ">
<!-- BUTTONS -->
<input type="submit" value="code Search" id="code_search" onclick = "processQuery()">
</form>
<p>Answer: </p>
<p id = 'output'></p>
</div>
Insted it just opens this code given billow
def main():
print("Hello,")
IN = input("query ")
QT = f"Q: {IN} ? A:"
response = openai.Completion.create(
model="text-davinci-003",
prompt=QT,
temperature=0,
max_tokens=64,
top_p=1,
frequency_penalty=0,
presence_penalty=0,
stop=["\n\n"]
)
user will input query in form-search on Html page
after clicking submit query shuld go to QA.py Python code
in python code input quary shud be submited to "IN"
after python Proveieds "A:" output shuld seen in 'output
Insted it just opens QA.py
You are missing a quotation mark on the form OnSubmit. The resulting javascript error allows the form to submit to the specified action which is your python file.
The Python file will only execute if run on a webserver that is properly configured. It may be that your web server is not configured for Python, or that you are running the html as a local file (ie from disk, not via a web server), and thus your Python file gets served as a file rather than executed.
It would appear you are trying to run a submit through javascript on a button. In which case the form action isn't required. Instead your processQuery() function which you haven't shared needs to specify which file to exectue.

How do I get checkbox "on" using Python Flask without causing a 400 bad request error?

I've got a form which is submitting a post request to Flask. It all works perfectly except when a checkbox is not ticked which causes a 400 error unless I have a try: except: catch for each option.
The challenge is that I have a lot of checkboxes and it seems like there would be a better way than just having a dozen try: except: checks.
Is there a more Pythonic way of doing this please?
Currently the HTML looks like this:
<div class="control">
<label class="checkbox">
<input name="option_1" type="checkbox">
Option 1
</label>
</div>
My Python code looks like:
try:
print(request.form['option_1'])
except:
print("option_1 not selected")
When a key might not exist, use .get(...) instead of accessing it directly, for example:
print(request.form.get('option_1'))
Thanks to Janos for the explanation, whoop only prints if the box is ticked with no error if it's not there.
if request.form.get('option_1'):
print('whoop')

How to control my webapp with Alexa

I built an alexa skill using Python with Flask_ask, which goes to my DB and retrieves information that I need and spells it out.
I am now trying to create a web UI which would have an option of asking the required question by typing it in or speaking directly to alexa. The web UI works easily as it redirects to the page I want as below :
#app.route('/getdog')
def getdog():
return render_template('mypage.html')
Ideally I would configure an intent which would trigger the change in webpage e.g.
#ask.intent('myintent')
def changepage():
getdog()
Any ideas how to handle this?
You can use use a simple HTML form with a text input box:<form method="POST" action="/changepage/">
Enter Your Query: <input type="text" name="intent_string" />
<input type="submit" value="Ask Alexa"/>
</form>
Your changepage url should call a method which handles calling other intents based on whatever string has been passes in the POST request.
If you not able to exactly match the required intent to call you can add a full text search and match with that

Uploading file to Google App Engine using new dev_appserver

Google App Engine documentation makes it appear very simple to get the contents of an uploaded file (self.request.get('user_file')), but while I can do this with old_dev_appserver.py, I cannot get it with the current dev_appserver.py (v1.9.2).
Here's a simple example that generates the incoming data:
<form name="myform" action="http://localhost:8080/sync?cmd=tester" enctype="multipart/form-data" method="post">
Username: <input type="file" name="user_file" />
<input type="submit" value="Submit" />
</form>
In old_dev_appserver.py, one could get the file in GAE via self.request.get('user_file'), but not with the latest (1.9.2) dev_appserver.py
WebApp2 says "Uploaded files are available as cgi.FieldStorage (see the cgi module) instances directly in request.POST." But, request.POST is empty, and cgi.FieldStorage() does not contain 'user_file' either.
Strangely, if I print out self.request.params, I do see an element in the UnicodeMultiDict that is (u'user_file', FieldStorage(u'user_file', u'myfile.ico')). But when I try to get that element, either via named access or just iterating over params, I cannot get it. Even if I do a Len(self.request.params) I get one less than what I see, and the 'user_file' element is missing. If I do this with old_dev_appserver, the Len(self.request.params) is correct.
How do I get user_file?
Figured it out (finally!). I had been logging elements of the request (params, body, etc.) as I sorted through other issues. But you can only instantiate a cgi.FieldStorage element once, so by the time I got to the actual self.request.get('user_file'), it was already gone.
Classic case in which removing the debugging actually makes it work.

How do I display a website with html-forms locally using python and collect the user input?

I am a behavorial scientist and usually collect data by letting participants do some tasks on a computer and record their responses (I write the programs using the pyglet wrapper PsychoPy). That is, the program runs locally and the data is stored locally.
Now I would like to know if there is a way to use Python to display a (local) website with html-forms to the user and collect the input (locally). The reason for this idea is that currently whenever I want to display checkboxes, radiobuttons, or input fields I use wxPython. This works quite well, but programming and layouting in wxPython is kind of cumbersome and I would prefer html with forms.
A requirement would be that it would need to rum without any borders, adress field, menu bar, ... The reason is that I need it in kind of fullscreen mode (I currently open a non-fullscreen pygflet window in the size of the screen to hide the desktop) so that participants can do nothing but work on the forms.
So I am looking for a way to (a) display html websites including html form above a pyglet window with no menu bar or whatsoever, (b) collect the input when clicking on the Ok button (i.e., the form is send), (c) control what is presented prior and after viewing this website, and (d) everything of this should happen locally!
My idea would be that the data is collected when participants hit the "Send away" button in the following example pic and the next page is displayed.
Update: I use windows (XP or 7).
This is a solution using Qt Webkit for rendering HTML. The default navigation request handler is wrapped by a function that checks for submitted form requests. The form uses the "get" method, so the data is included in the url of the request and can be retrieved that way. The original request is declined and you can change the content of the displayed web page as you wish.
from PyQt4 import QtGui, QtWebKit
app = QtGui.QApplication([])
view = QtWebKit.QWebView()
# intercept form submits
class MyWebPage(QtWebKit.QWebPage):
def acceptNavigationRequest(self, frame, req, nav_type):
if nav_type == QtWebKit.QWebPage.NavigationTypeFormSubmitted:
text = "<br/>\n".join(["%s: %s" % pair for pair in req.url().queryItems()])
view.setHtml(text)
return False
else:
return super(MyWebPage, self).acceptNavigationRequest(frame, req, nav_type)
view.setPage(MyWebPage())
# setup the html form
html = """
<form action="" method="get">
Like it?
<input type="radio" name="like" value="yes"/> Yes
<input type="radio" name="like" value="no" /> No
<br/><input type="text" name="text" value="Hello" />
<input type="submit" name="submit" value="Send"/>
</form>
"""
view.setHtml(html)
# run the application
view.show()
app.exec_()
As AdamKG mentioned, using a webframework would be a good choice. Since Django and similar might be an overkill here, using a micro webframework like 'flask' or 'bottle' would be a great choice.
This link demonstrates via step by step instruction how to make a simple form via a To-DO application. It assumes zero previous knowledge.
You can run it only locally also.
your want a simple solution, so just write a http server and run your simple page.
using python.BaseHTTPServer, coding a 15 line web server:
import BaseHTTPServer
class WebRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
if self.path == '/foo':
self.send_response(200)
self.do_something()
else:
self.send_error(404)
def do_something(self):
print 'hello world'
server = BaseHTTPServer.HTTPServer(('',80), WebRequestHandler)
server.serve_forever()
easy enough,but i suggest using some web frameworks. They are easy too.
for example, web.py. here is what u want in 50 line codes:
install web.py
make a dir with 2 files:
./
|-- app.py
`-- templates
`-- index.html
index.html
$def with (form, ret)
<html>
<head>
<title> another site </title>
</head>
<body>
<h1> hello, this is a web.py page </h1>
<form action="" method="post">
$:form.render()
</form>
<h2>$:ret</h2>
</body>
</html>
app.py logic file:
import web
### Url mappings
urls = (
'/', 'Index', )
### Templates
render = web.template.render('templates')
class Index:
form = web.form.Form(
web.form.Textbox('fav_name', web.form.notnull, description="Favorite Name:"),
web.form.Textbox('cur_name', web.form.notnull, description="Current Name:"),
web.form.Button('Send Away'),
)
def GET(self):
""" Show page """
form = self.form()
return render.index(form, "")
def POST(self):
""" handle button clicked """
form = self.form()
if not form.validates():
return render.index(form, "INPUT ERROR")
# save data by ur method, or do some task
#pyglet.save_data(form.d.fav_name, form.d.cur_name)
#pyglet.draw(some_pic)
#os.system(some_cmd)
form = self.form()
return render.index(form, "YOUR DATA SAVED")
app = web.application(urls, globals())
if __name__ == '__main__':
app.run()
run this server in your windows:
python app.py 9999
open browser: http://127.0.0.1:9999/
by the way, if ur data is only strings, u can save them in web.by by sqlite.
My suggestion would be:
Use some python server as, for example SimpleHTTPServer. It is needed because the submit button on forms sends the information to a server. There you should manage the received info some way;
Have your browser configured with one of those Kiosk extensions, which disallow even the use of Alt+F4. An example would be Open Kiosk extension for Firefox
Optionally, if you have affinity with scripts in general, you could create a script which, when executed, would at the same time run the python server AND open your html file in the browser. That would ease a lot your setup work for every subject in your group.
EDIT: I've read you need the pyglet over the browser window. That could be included in the script of step 3, using "always on top" option and absolute positioning of the pyglet (I can tell this would probably be simpler on Linux, which could be run from persistent LiveUSB - just a thought!)
EDIT (regarding the posted comment):
I think the most reliable option for output would be to disk (file or database) instead or RAM (running python object), then you read the info from file afterwards. Then, in case of a surprise (system hang, power failure), the already-entered data would be there.
The only (and most important) part I don't know HOW to do is to handle the content of the form's "submit" on the server-side. Probably some server-side script file (php, python) shoud be created and left on the server root, so the server would receive an http request containing the info, and send the info to the script, which then handles the processing and file/database storage activities.
This might be of your interest:
"The POST request method is used when the client needs to send data to the server as part of the request, such as when uploading a file or submitting a completed form." (from wikipedia on "POST(HTTP)" ENTRY)
In another link, some thoughts on using SimpleHTTPServer itself for handling POST requests:
http://islascruz.org/html/index.php/blog/show/Python%3A-Simple-HTTP-Server-on-python..html
Hope this helps.
The reason for this idea is that currently whenever I want to display
checkboxes, radiobuttons, or input fields I use wxPython. This works
quite well, but programming and layouting in wxPython is kind of
cumbersome and I would prefer html with forms.
You can combine the ease of HTML and still create native Windows applications using Flex with a Python backend.
If you are averse to Flex, a bit more - involved - but still native windows application generator is Camelot
Edit
Instead of typing it out again - I would suggest the django + flex + pyamf article on Adobe that explains it all with screenshots as well. You can replace django with flask or bottle as they are more lightweight, however the PyAMF library provides native support for django which is why it was used in the example.
PyAMF provides Action Message Format (a binary protocol to exchange object with the flash runtime) support for Python.

Categories