String formatting может сделать вещи намного аккуратнее, и меньше ошибок -prone.
Простой пример, %s
заменяется a title
:
my_html = "<html><body><h1>%s</h1></body></html>" % ("a title")
Или несколько раз (название то же самое, и теперь "мое содержание" отображается, когда второй %s
является:
my_html = "<html><body><h1>%s</h1>%s</body></html>" % ("a title", "my content")
Вы также можете использовать именованные ключи при выполнении %s
, например %(thekey)s
, что означает, что вам не нужно отслеживать, в каком порядке находятся %s
. Вместо list, вы используете dictionary, который отображает ключ к значению:
my_html = "<html><body><h1>%(title)s</h1>%(content)s</body></html>" % {
"title": "a title",
"content":"my content"
}
Самая большая проблема с вашим скриптом, вы используете глобальную переменную (data
). гораздо лучше всего было бы:
- search_results вызовов, с аргументом «SwineFlu»
- search_results возвращает список результатов, сохранить результат в переменной
- вызова WebOutput, с поиском приводит переменную в качестве аргумента
- WebOutput возвращает строку, содержащую ваш HTML
- написать возвращаемый HTML в файл
WebOutput вернет HTML (как строку) и напишет его в файл. Что-то вроде:
results = SearchResults("swineflu", 25)
html = WebOutput(results)
f = open("outw.html", "w")
f.write(html)
f.close()
Наконец, модуль twitterd требуется только при доступе к данным, которая требует входа в систему. Публичная шкала времени, ну, общедоступна и может быть доступна без аутентификации, поэтому вы можете удалить импорт twitterd и строку api =
.Если же хотите использовать twitterd, вы должны сделать что-то с переменной api
, например:
api = twitterd.Api(username='username', password='password')
statuses = api.GetPublicTimeline()
Итак, как я мог бы написать сценарий является:
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) в какой момент будет подходящим для приложения подходящим для приложения? Overkill?
Я бы сказал, всегда использовать веб-рамку (с некоторыми исключениями)
Теперь, это может показаться странным, учитывая все время я только потратил объяснение исправления в свой сценарий .. но с вышеназванным модификации вашего скрипта, это невероятно легко сделать, так как все было хорошо функционально!
Используя CherryPy, который представляет собой простую структуру HTTP для Python, вы можете легко отправлять данные в браузер, а не постоянно писать файл.
Предполагается, что приведенный выше сценарий сохраняется как twitter_searcher.py
.
Примечание. Я никогда раньше не использовал CherryPy, это просто пример HelloWorld на домашней странице CherryPy, с несколькими строками, скопированными из функции main() этого выше скрипта!
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())
Сохранить и запустить этот сценарий, затем перейдите к http://0.0.0.0:8080/
и он будет показывать свою страницу!
Проблема с этим, при каждой загрузке страницы он будет запрашивать API Twitter. Это не будет проблемой, если вы просто используете его, но с сотнями (или даже десятками) людей, которые смотрят на страницу, он начнет замедляться (и вы могли бы получить ограничение по скорости/заблокировать API-интерфейс Twitter, в конечном итоге)
Решение в основном возвращается к началу. Вы должны написать (кэш) результат поиска на диск, переименовать твиттер, если данные более чем на 60 секунд. Вы также можете заглянуть в CherryPy's caching options .. но этот ответ становится довольно абсурдно долго.
Thx all (llimllib, THC4k, dbr, Buddy)! Я определенно вижу ценность использования фреймворка даже для небольшого проекта. Я рассмотрю различные варианты и посмотрю, какой из них мне больше всего нравится. llimllib: Благодарю вас за очень ясный пример. это было очень полезно! dbr: большой thx !! чем ожидалось. (1) извините за ссылку api, это был просто старый код, который я забыл удалить. (2) любить переписывать/исправлять - гораздо лучше и будет использовать этот подход во всем моем коде в будущем. (3) запуская некоторые проблемы с Unicode с вашим кодом - не уверен, почему, но будет делать некоторые исследования. – timepilot