Python html输出(第一次尝试),几个问题(包括代码)

tim*_*lot 2 javascript python

虽然我已经玩了几个月的python(只是一个业余爱好者),但我对网络编程知之甚少(一点点html,零javascript等).也就是说,我有一个当前的项目让我第一次看到网络编程.这让我想问:

在Web上获取Python脚本输出的最简单方法是什么?

谢谢答案,我取得了一些进展.现在,我只是使用python和html.我无法发布我的项目代码,因此我使用twitter搜索编写了一个小例子(请参阅下文).

我的问题是:

(1)我做了什么非常愚蠢的事情吗?我觉得WebOutput()很明显但效率低下.如果我使用javascript,我假设我可以编写一个html模板文件然后只更新数据.是?更好的方法吗?

(2)框架在什么时候适合这样的应用程序?矫枉过正?

对不起基本问题 - 但我不想花太多时间走错路.

import simplejson, urllib, time

#query, results per page 
query = "swineflu"
rpp = 25
jsonURL = "http://search.twitter.com/search.json?q=" + query + "&rpp=" + str(rpp)

#currently storing all search results, really only need most recent but want the data avail for other stuff
data = []

#iterate over search results
def SearchResults():
    jsonResults = simplejson.load(urllib.urlopen(jsonURL))
    for tweet in jsonResults["results"]:
        try:
            #terminal output
            feed = tweet["from_user"] + " | " + tweet["text"]
            print feed
            data.append(feed)
        except:
            print "exception??"

# writes latest tweets to file/web
def WebOutput():
    f = open("outw.html", "w")
    f.write("<html>\n")
    f.write("<title>python newb's twitter search</title>\n")
    f.write("<head><meta http-equiv='refresh' content='60'></head>\n")
    f.write("<body>\n")
    f.write("<h1 style='font-size:150%'>Python Newb's Twitter Search</h1>")
    f.write("<h2 style='font-size:125%'>Searching Twitter for: " + query + "</h2>\n")
    f.write("<h2 style='font-size:125%'>" + time.ctime() + " (updates every 60 seconds)</h2>\n")

    for i in range(1,rpp):
        try:
            f.write("<p style='font-size:90%'>" + data[-i] + "</p>\n")
        except:
            continue

    f.write("</body>\n")
    f.write("</html>\n")
    f.close()

while True:
    print ""
    print "\nSearching Twitter for: " + query + " | current date/time is: " + time.ctime()
    print ""
    SearchResults()
    WebOutput()
    time.sleep(60)
Run Code Online (Sandbox Code Playgroud)

lli*_*lib 8

使用这样的框架并不过分; python框架往往非常轻巧,易于使用,并且可以使您更轻松地为您的小网站添加功能.但它也不是必需的; 我假设您是出于学习目的而这样做,并谈论我将如何更改代码.

你在WebOutput函数中没有模板引擎进行模板操作; python有各种各样的模板语言,我最喜欢的是mako.如果该函数中的代码变得比当前更加繁琐,我会将其分解为模板; 我会告诉你片刻会是什么样子.但首先,我使用多行字符串来替换所有那些f.write,并使用字符串替换而不是添加字符串:

f.write("""<html>
<title>python newb's twitter search</title>
<head><meta http-equiv='refresh' content='60'></head>
<body>
<h1 style='font-size:150%'>Python Newb's Twitter Search</h1>
<h2 style='font-size:125%'>Searching Twitter for: %s</h2>
<h2 style='font-size:125%'>%s (updates every 60 seconds)</h2>""" % (query, time.ctime()))

for datum in reversed(data):
    f.write("<p style='font-size:90%'>%s</p>" % (datum))

f.write("</body></html>")
Run Code Online (Sandbox Code Playgroud)

另请注意,我简化了你的for循环; 我会进一步解释我所说的是没有意义的.

如果您要将WebOutput函数转换为Mako,则首先要在文件顶部导入mako:

import mako
Run Code Online (Sandbox Code Playgroud)

然后你将用以下内容替换整个WebOutput():

f = file("outw.html", "w")
data = reversed(data)
t = Template(filename='/path/to/mytmpl.txt').render({"query":query, "time":time.ctime(), "data":data})
f.write(t)
Run Code Online (Sandbox Code Playgroud)

最后,您将创建一个如下所示的文件/path/to/mytmpl.txt:

<html>
<title>python newb's twitter search</title>
<head><meta http-equiv='refresh' content='60'></head>
<body>
<h1 style='font-size:150%'>Python Newb's Twitter Search</h1>
<h2 style='font-size:125%'>Searching Twitter for: ${query}</h2>
<h2 style='font-size:125%'>${time} (updates every 60 seconds)</h2>

% for datum in data:
    <p style'font-size:90%'>${datum}</p>
% endfor

</body>
</html>
Run Code Online (Sandbox Code Playgroud)

您可以看到,您完成的好处是将输出(或Web术语中的"视图层")与抓取和格式化数据的代码("模型层"和"控制器层")分开.这将使您将来更容易更改脚本的输出.

(注意:我没有测试我在这里提供的代码;如果它不太正确,请道歉.它应该基本上可以工作)


dbr*_*dbr 5

字符串格式化可以使事情变得更整洁,并且更不容易出错.

简单的例子,%s被替换为a title:

my_html = "<html><body><h1>%s</h1></body></html>" % ("a title")
Run Code Online (Sandbox Code Playgroud)

或多次(标题相同,现在"我的内容"显示在第二个%s位置:

my_html = "<html><body><h1>%s</h1>%s</body></html>" % ("a title", "my content")
Run Code Online (Sandbox Code Playgroud)

这样做时,也可以使用名为键%s,如%(thekey)s,这意味着你不必跟踪了解其顺序%s是相反的一个,列表,你可以使用一个字典,它映射的关键价值:

my_html = "<html><body><h1>%(title)s</h1>%(content)s</body></html>" % {
    "title": "a title",
    "content":"my content"
}
Run Code Online (Sandbox Code Playgroud)

您的脚本最大的问题是,您正在使用全局变量(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()
Run Code Online (Sandbox Code Playgroud)

最后,只有在访问需要登录的数据时才需要twitterd模块.公共时间表是公开的,无需任何身份验证即可访问,因此您可以删除twitterd导入和api =行.如果您确实想使用twitterd,则必须对api变量执行某些操作,例如:

api = twitterd.Api(username='username', password='password')
statuses = api.GetPublicTimeline()
Run Code Online (Sandbox Code Playgroud)

所以,我编写脚本的方式是:

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
Run Code Online (Sandbox Code Playgroud)

(2)框架在什么时候适合这样的应用程序?矫枉过正?

我会说总是使用一个web框架(有一些例外)

现在,这可能看起来很奇怪,因为我只是花了一些时间来解释你的脚本修复...但是,通过对你的脚本的上述修改,它非常容易做到,因为一切都很好地运行了!

使用CherryPy,这是一个非常简单的Python HTTP框架,您可以轻松地将数据发送到浏览器,而不是经常编写文件.

这假定上面的脚本保存为twitter_searcher.py.

注意我之前从未使用过CherryPy,这只是CherryPy主页上的HelloWorld示例,从上面脚本的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())
Run Code Online (Sandbox Code Playgroud)

保存并运行该脚本,然后浏览http://0.0.0.0:8080/并显示您的页面!

这个问题,在每个页面加载它将查询Twitter API.如果只是你使用它,这不会是一个问题,但是有数百(甚至数十)人在看页面,它会开始变慢(你可能会被twitter API限制/阻止,最终)

解决方案基本上回到了开始..你会将搜索结果写入(缓存)到光盘,如果数据超过60秒,则重新搜索twitter.您还可以查看CherryPy的缓存选项 ..但这个答案变得相当荒谬了......