Allow a list as argument

Asked

Viewed 228 times

0

I have a Python REST API that takes 2 arguments, a Url list and a word. I am a beginner in Python and would like to know if it is possible to split the string of the URL to accept more than one URL qdo to request the body of the URL. For example, I can currently make the request on http://127.0.0.1/? urls=globe.com&word=google

Only that I would like to include more than one url in the body as http://127.0.0.1/? urls=globe.com&urls=terra.com.br&urls=Uol.com.br&word=google

Follows the code:

from flask import Flask
from flask_restful import Resource, Api, reqparse, abort
import requests

app = Flask(__name__)
api = Api(app)

parser = reqparse.RequestParser()
parser.add_argument('urls', action='append')
parser.add_argument('word')
parser.add_argument('ignorecase')

# Função que faz um GET para a URL e retorna quantas vezes a palavra word aparece no conteudo


def count_words_in(url, word, ignore_case):
    try:
        r = requests.get(url)
        data = str(r.text)
        if (str(ignore_case).lower() == 'true'):
            return data.lower().count(word.lower())
        else:
            return data.count(word)
    except Exception as e:
        raise e

# Função que inclui 'http://' na url e retorna a URL valida


def validate_url(url):
    if not(url.startswith('http')):
        url = 'http://' + url
    return url


class UrlCrawlerAPI(Resource):
    def get(self):
        try:
            args = parser.parse_args()
            valid_urls = [validate_url(url)  for url in args['urls']]
            lista = []
            for valid_url in valid_urls:
                lista.append({valid_url: {args['word']: count_words_in(valid_url, args['word'], args['ignorecase'])}})
                # return {valid_url: {args['word']: count_words_in(valid_url, args['word'], args['ignorecase'])}}
            return lista    
        except AttributeError:
            return {'message': 'Please provide URL and WORD arguments'}
        except Exception as e:
            return {'message': 'Unhandled Exception: ' + str(e)}


api.add_resource(UrlCrawlerAPI, "/")

if __name__ == '__main__':
    app.run(debug=True) 
  • for valid_url in valid_urls: return .... Here you are just reading the first URL and leaving the function

  • yes, but if valid_urls is an array or is it not supposed to go through the whole array ? is almost right, by Postman the function is correct returning a json with the occurrence of found words, however it is only returning the first url.

  • The moment you give one return within a for, it exits the execution of the for. You would have to create a list with the result you want and, outside of the for, returns this list

  • Thank you very much friend, it worked!! you helped me too much, follow the edited code running 100% and showing all Urls.

  • Glad it worked! You can mark the answer as correct if it helped you. D

2 answers

1

If what is returned by parser.parse_args() is a dictionary, it is impossible. Otherwise, you can pass the urls all together...

For example: urls=globe.com,earth.com,Uol.com

And separate them using str.split()

urls = args.split(',')

or something like that

  • thanks friend, but in case the attribution would be after args ? because it is giving error in the syntax. Follow the full code edited.

  • You should use urls = args['urls']. split(',') instead of urls = args.split(',').

  • thanks friend but keeps giving syntax error. this assignment of urls I should insert in which function ? edited the code again.

1


According to the documentation of Flask Restful just configure the URL parameter correctly for the framework to append of the repeated parameters, instead of overwriting existing ones:

parser.add_argument('urls', action='append')

And then to take the amount:

args = parser.parse_args()
args['urls']    # seria uma lista com todas as urls passados por parâmetro.
# aplicando `validate_url` para todas as URLs recebidas
valid_urls = [validate_url(url) for url in args['url']]
# ou
valid_urls = map(validate_url, args['url'])
  • Thank you young man, but when I insert action='append' in the arguments it enters the last unexpected exception. In case I shouldn’t split the string of the urls ? I edited my current code.

  • but args['urls'] is a list and you’re called validate_urls right into it as if it were a string, it’s right to throw an exception even. I think you want to apply the function to all incoming urls, maybe using map(validate_urls, args['urls']) or a list comprehension resolvea.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.