String formatting peut rendre les choses beaucoup plus nettes et moins d'erreurs -enclin.
Exemple simple, %s
est remplacé par a title
:
my_html = "<html><body><h1>%s</h1></body></html>" % ("a title")
Ou plusieurs fois (titre est le même, et maintenant "mon contenu" est affiché lorsque la deuxième %s
est:
my_html = "<html><body><h1>%s</h1>%s</body></html>" % ("a title", "my content")
Vous pouvez également utiliser des clés nommées lorsque vous faites %s
, comme %(thekey)s
, ce qui signifie que vous n'avez pas besoin de garder trace de l'ordre dans lequel se trouvent les %s
. Au lieu d'un list, vous utilisez un dictionary, qui mappe la clé d'une valeur:
my_html = "<html><body><h1>%(title)s</h1>%(content)s</body></html>" % {
"title": "a title",
"content":"my content"
}
Le plus gros problème avec votre script, vous utilisez une variable globale (data
). Un beaucoup mieux serait:
- search_results d'appel, avec un argument de « swineflu »
- search_results retourne une liste de résultats, stocker le résultat dans une variable
- appel WebOutput, la recherche des résultats variables comme argument
- WebOutput retourne une chaîne contenant votre code HTML
- écrire le code HTML retourné à votre fichier
WebOutput renvoie le code HTML (en tant que chaîne) et l'écrit dans un fichier. Quelque chose comme:
results = SearchResults("swineflu", 25)
html = WebOutput(results)
f = open("outw.html", "w")
f.write(html)
f.close()
Enfin, le module twitterd n'est requis que si vous accédez à des données nécessitant une connexion. Le calendrier public est, bien, public, et peut être consulté sans aucune authentification, de sorte que vous pouvez supprimer l'importation twitterd, et la ligne api =
.Si vous ne voulez utiliser twitterd, vous devez faire quelque chose avec la variable api
, par exemple:
api = twitterd.Api(username='username', password='password')
statuses = api.GetPublicTimeline()
Ainsi, la façon dont je pourrais avoir écrit le script est:
import time
import urllib
import simplejson
def search_results(query, rpp = 25): # 25 is default value for rpp
url = "http://search.twitter.com/search.json?q=%s&%s" % (query, rpp)
jsonResults = simplejson.load(urllib.urlopen(url))
data = [] # setup empty list, within function scope
for tweet in jsonResults["results"]:
# Unicode!
# And tweet is a dict, so we can use the string-formmating key thing
data.append(u"%(from_user)s | %(text)s" % tweet)
return data # instead of modifying the global data!
def web_output(data, query):
results_html = ""
# loop over each index of data, storing the item in "result"
for result in data:
# append to string
results_html += " <p style='font-size:90%%'>%s</p>\n" % (result)
html = """<html>
<head>
<meta http-equiv='refresh' content='60'>
<title>python newb's twitter search</title>
</head>
<body>
<h1 style='font-size:150%%'>Python Newb's Twitter Search</h1>
<h2 style='font-size:125%%'>Searching Twitter for: %(query)s</h2>
<h2 style='font-size:125%%'> %(ctime)s (updates every 60 seconds)</h2>
%(results_html)s
</body>
</html>
""" % {
'query': query,
'ctime': time.ctime(),
'results_html': results_html
}
return html
def main():
query_string = "swineflu"
results = search_results(query_string) # second value defaults to 25
html = web_output(results, query_string)
# Moved the file writing stuff to main, so WebOutput is reusable
f = open("outw.html", "w")
f.write(html)
f.close()
# Once the file is written, display the output to the terminal:
for formatted_tweet in results:
# the .encode() turns the unicode string into an ASCII one, ignoring
# characters it cannot display correctly
print formatted_tweet.encode('ascii', 'ignore')
if __name__ == '__main__':
main()
# Common Python idiom, only runs main if directly run (not imported).
# Then means you can do..
# import myscript
# myscript.search_results("#python")
# without your "main" function being run
(2) à quel moment un cadre serait-il approprié pour une application comme celle-ci? exagéré?
Je dirais toujours utiliser un framework web (avec quelques exceptions)
Maintenant, cela peut sembler étrange, étant donné tout le temps que je viens de passer à expliquer les correctifs à votre script .. mais, au-dessus modifications à votre script, c'est incroyablement facile à faire, puisque tout a été bien fonctionné! En utilisant CherryPy, qui est un framework HTTP très simple pour Python, vous pouvez facilement envoyer des données au navigateur, plutôt que d'écrire constamment un fichier.
Cela suppose que le script ci-dessus est enregistré sous la forme twitter_searcher.py
.
Remarque: Je n'ai jamais utilisé CherryPy auparavant, ce n'est que l'exemple HelloWorld sur la page d'accueil CherryPy, avec quelques lignes copiées de la fonction main() du script ci-dessus!
import cherrypy
# import the twitter_searcher.py script
import twitter_searcher
# you can now call the the functions in that script, for example:
# twitter_searcher.search_results("something")
class TwitterSearcher(object):
def index(self):
query_string = "swineflu"
results = twitter_searcher.search_results(query_string) # second value defaults to 25
html = twitter_searcher.web_output(results, query_string)
return html
index.exposed = True
cherrypy.quickstart(TwitterSearcher())
Enregistrez et exécutez ce script, puis accédez à http://0.0.0.0:8080/
et il va montrer votre page!
Le problème avec ceci, à chaque chargement de page il questionnera l'API de Twitter. Ce ne sera pas un problème si vous l'utilisez seulement, mais avec des centaines (voire des dizaines) de personnes qui regardent la page, ça commence à ralentir (et vous pourriez obtenir un tarif limité/bloqué par l'API twitter, éventuellement
La solution est fondamentalement de retour au début .. Vous écririez (cache) le résultat de la recherche sur le disque, en re-cherchant twitter si les données datent de plus de 60 secondes. Vous pouvez également regarder dans CherryPy's caching options .. mais cette réponse devient plutôt absurdement longue ..
Thx tous (llimllib, THC4k, dbr, Buddy)! Je vois vraiment l'intérêt d'utiliser un framework même pour un petit projet. Je vais jeter un coup d'oeil aux différentes options et voir lequel je préfère. llimllib: merci pour l'exemple très clair. C'était très utile! dbr: big thx !! bien au-delà de ce que j'attendais. (1) désolé pour la référence api, c'était juste l'ancien code que j'ai oublié de supprimer. (2) aime la réécriture/corrections - beaucoup mieux et utilisera cette approche dans tout mon code aller de l'avant. (3) rencontrer des problèmes d'unicode avec votre code - ne sais pas pourquoi mais fera quelques recherches. – timepilot