I have a question about web.py.
The following is the example code from web.py tutorial. I added a print row into the code as print name. run python test.py, and then open http://0.0.0.0:8080/baby in the brower, you will see "hello baby" in the html page. However, in the terminal, you will see the print result is "favicon.ico".
I know favicon.ico, but I am pretty confused about why it doesn't print "baby".
Can someone explain this for me? Thanks to everybody~
import web
urls = (
'/(.*)', 'hello'
)
app = web.application(urls, globals())
class hello:
def GET(self, name):
print name
if not name:
name = 'World'
return 'Hello, ' + name + '!'
if __name__ == "__main__":
app.run()
Your web browser also requests favicon.ico automatically to show a small icon in your browser tab, ie:
http://0.0.0.0:8080/favicon.ico
in which case name is equal to "favicon.ico"
Related
This question already has an answer here:
Capture arbitrary path in Flask route
(1 answer)
Closed 1 year ago.
I am trying to pass a website as a parameter. It works if the website does not have a "/" in it. For example: http://192.168.1.156:2434/www.cookinglight.com scrapes cooking light for all the images on it's page; however, if I pass in http://192.168.1.156:2434/https://www.cookinglight.com/recipes/chicken-apple-butternut-squash-soup then an I get an invalid response. Here is my current code:
import json
from flask import Flask, render_template
from imagescraper import image_scraper
app = Flask(__name__)
#app.route("/", methods = ['GET'])
def home():
return render_template('index.html')
#app.route("/<site>", methods = ['GET'])
def get_image(site):
return json.dumps(image_scraper(site))
if __name__ == '__main__':
app.run(host='0.0.0.0', port=2434, debug=True)
import requests
from bs4 import BeautifulSoup
def image_scraper(site):
"""scrapes user inputed url for all images on a website and
:param http url ex. https://www.cookinglight.com
:return dictionary key:alt text; value: source link"""
search = site.strip()
search = search.replace(' ', '+')
website = 'https://' + search
response = requests.get(website)
soup = BeautifulSoup(response.text, 'html.parser')
img_tags = soup.find_all('img')
# create dictionary to add image alt tag and source link
images = {}
for img in img_tags:
try:
name = img['alt']
link = img['src']
images[name] = link
except:
pass
return images
I tried urrllib but did not have any success. Any help would be greatly appreciated! I am a student so still learning!!
UPDATE:
I believe this is the issue as described in the stackoverflow post
Need to allow encoded slashes on Apache
Flask uses / as separate between arguments in url - so you can create route("/<arg1>/<arg2>/<arg3>") (or popular in blogs route("/<year>/<month>/<day>")) and you can get values in variables arg1, arg2, arg3 - and when you try to use your url with / then it also treat it as "/<arg1>/<arg2>/<arg3>" and it tries to find route like route("/<arg1>/<arg2>/<arg3>") and it can't find it and it gives error 404.
route("/<site>") can match only string without /. site is only variable name - it doesn't mean that it will treat it as url with /
If you want to use / as part of single argument, not as separator between arguments, then you need <path:site>.
from flask import Flask
app = Flask(__name__)
#app.route("/")
def home():
return "Hello World"
#app.route("/<path:site>")
def get_image(site):
return f"OK: {site}"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=2434)#, debug=True)
See also Variable Rules
EDIT:
It has nothing to do with issue. Flask was specially created to use / as special char to separate values.
I found this question which seems to be what I'm looking for.
It says to use web.ctx['ip']
But I cant get it to work right, all I want is the IP of the visitor in a variable. So far I've been trying this:
import web
urls = (
'/', 'index'
)
class index:
def GET(self):
return "Hello, world!"
return web.ctx['ip'] #Trying to get it to just *show* so
#I can put it into a variable
print web.ctx['ip'] #Nothing happens here either
if __name__ == "__main__":
app = web.application(urls, globals())
app.run()
Thanks in advance, I think I'm close, I just need a little help. Maybe I need to import something else?
You are returning before even getting the IP address, Just re-order your code to the following way and remove return "Hello, world!" :
class index:
def GET(self):
print web.ctx['ip']
return web.ctx['ip']
I initially gave URLs like #app.route('/volume/') and #app.route('/cvolume/') where c denoted another section. But now I think section/page would be better than c prefix to the page i.e. #app.route('/c/volume/'). Can I simply make the change or will this break my app?
P.S. - I am using <a href="{{url_for("volume")}}> in templates instead of the plain <a href="/volume">
No, because url_for takes the name of the function, not the url. So if your function is:
# ...Code, imports...
#app.route('/cvolume/')
def volume():
return 'Hello world!'
#app.route('/volume/')
def volume_2():
return 'Hello You!'
#app.route('/test/')
def test():
return redirect(url_for('volume'))
The redirection would be for /cvolume/ not /volume/.
Does anyone know how I would be able to take the the URL as an argument in Python as page?
Just to readline in the script, user inputs into the shell and pass it through as an argument just to make the script more portable?
import sys, re
import webpage_get
def print_links(page):
''' find all hyperlinks on a webpage passed in as input and
print '''
print '\n[*] print_links()'
links = re.findall(r'(\http://\w+\.\w+[-_]*\.*\w+\.*?\w+\.*?\w+\.*[//]*\.*?\w+ [//]*?\w+[//]*?\w+)', page)
# sort and print the links
links.sort()
print '[+]', str(len(links)), 'HyperLinks Found:'
for link in links:
print link
def main():
# temp testing url argument
sys.argv.append('http://www.4chan.org')
# Check args
if len(sys.argv) != 2:
print '[-] Usage: webpage_getlinks URL'
return
# Get the web page
page = webpage_get.wget(sys.argv[1])
# Get the links
print_links(page)
if __name__ == '__main__':
main()
It looks like you kind of got started with command line arguments but just to give you an example for this specific situation you could do something like this:
def main(url):
page = webpage_get.wget(url)
print_links(page)
if __name__ == '__main__':
url = ""
if len(sys.argv >= 1):
url = sys.argv[0]
main(url)
Then run it from shell like this
python test.py http://www.4chan.org
Here is a tutorial on command line arguments which may help your understanding more than this snippet http://www.tutorialspoint.com/python/python_command_line_arguments.htm
Can you let me know if I miss understood your question? I didn't feel to confident in the meaning after I read it.
I am not really familiar with Python and am trying to transform one of my php webapps to python. Currently I am running the app on localhost using the appengine launcher and this is what I am trying to do.
I am trying to get a list of all the parameters posted to the url and then submit them to a page and get its content.
So basically:
1: get the params
2: get contents of a url by submitting those params (the PHP equivalent of curl of file_get_contents)
This is my code so far
from google.appengine.ext import webapp
class MyHandler(webapp.RequestHandler):
def get(self):
name1 = self.request.get_all("q")
name2 = self.request.get_all("input")
return name1,name2
x = MyHandler()
print x.get()
and the url
http://localhost:8080/?q=test1&input=test2
and this is the error I get
AttributeError: 'MyHandler' object has no attribute 'request'
Now I cant get it to print anything and I am not sure how I can get the contents of another url by submitting name1 and name2
I have tried looking at the documentation but I cant make sense of it since all they have is just 2 lines of code to get the use of function started.
x = MyHandler()
print x.get()
This is not a typical part of an AppEngine app. You don't use print to return output to the browser.
When you create a new app in AppEngineLauncher it gives you a skeleton project that looks like this:
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
class MainHandler(webapp.RequestHandler):
def get(self):
self.response.out.write('Hello world!')
def main():
application = webapp.WSGIApplication([('/', MainHandler)],
debug=True)
util.run_wsgi_app(application)
if __name__ == '__main__':
main()
Your app has to be run similarly. You need a main() method that creates a wsgi_app which is in charge of calling your handler. That main() function is called by dev_appserver, assuming your app.yaml file is set up correctly.
def get(self):
name1 = self.request.get_all("q")
name2 = self.request.get_all("input")
self.response.out.write(name1 + ',' + name2)
Should work if you've set up your app correctly.
You will need a few more lines of code to make this work if you are going to use the WebApp framework. Stick the following lines at the end of your code (and get rid of the last two lines where you instantiate your class and call the get method)
application = webapp.WSGIApplication([('/', MyHandler)])
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()