Python写作第二天
完成了第一个作品:网页刷新器。定时读取指定的URL,并根据返回的内容抓取网页计数器读数(你可以稍作修改以适用于你希望的用途)。程序提供了GUI,为了避免界面失去响应,所以把工作封装到了线程中。
TO-DO LIST:
- Cookie;
- 由于目标URL不变,可以不使用Queue;
- 代理列表文件支持。
代码清单:
from Tkinter import *
from Queue import Queue
import tkFont
import threading
import time
import urllib
import re
import random
# Producer thread
class Producer(threading.Thread):
def __init__(self, threadname, queue):
threading.Thread.__init__(self, name = threadname)
self.sharedata = queue
def run(self):
global lock, increment, target
while (1):
# increment is a critical resource
lock.acquire()
for i in range(increment):
url = target.get()
self.sharedata.put(url)
increment = 0
lock.release()
# validate every 1 second
validateJobCount()
time.sleep(1)
# Consumer thread
class Consumer(threading.Thread):
def __init__(self, threadname, queue):
threading.Thread.__init__(self, name = threadname)
self.sharedata = queue
def run(self):
while (1):
url = self.sharedata.get()
self.__doRefresh(url)
time.sleep(random.randint(0, int(interval.get())))
def __doRefresh(self, url):
global err, proxy, interval, pattern
setErrorCount(err)
setCurrentJob(url)
setResponse('fetching...')
try:
sock = urllib.urlopen(url, proxies = proxy)
htmlSource = sock.read()
mo = pattern.search(htmlSource)
if mo:
setCounter(mo.group(5))
setResponse('\n'.join([mo.group(1),
mo.group(2),
mo.group(3),
'...',
mo.group(4)]))
else:
err += 1
setErrorCount(err)
setResponse('failed')
except IOError:
err += 1
setErrorCount(err)
setResponse('timeout')
##------------------------------------------------------------------------------
def validateJobCount():
global lblJobCount, queue
lblJobCount['text'] = 'job running: %d' % (queue.qsize(), )
def setErrorCount(i):
global lblErrorCount
lblErrorCount['text'] = 'error: %d' % (i, )
def setCurrentJob(str):
global lblCurrentJob
lblCurrentJob['text'] = 'last job: %s' % (str, )
def setCounter(str):
global lblCounter
lblCounter['text'] = 'counter: %s' % (str, )
def setResponse(str):
global txtResponse
txtResponse.delete('1.0', END)
txtResponse.insert(END, str)
def onClickProxy():
global flag, pstr, proxy, edtProxy
if flag.get() == 1:
proxy = {'http': pstr.get()}
edtProxy['state'] = 'readonly';
else:
proxy = {}
edtProxy['state'] = 'normal';
def onClick1000():
global increment, lock
lock.acquire()
increment += 1000
lock.release()
def onClick100():
global increment, lock
lock.acquire()
increment += 100
lock.release()
def onClick10():
global increment, lock
lock.acquire()
increment += 10
lock.release()
def onClick1():
global increment, lock
lock.acquire()
increment += 1
lock.release()
def onClickClear():
global queue
while queque.empty():
queue.get()
def onClickQuit():
global root
root.quit()
if __name__ == '__main__':
err = 0
increment = 0
queue = Queue()
lock = threading.RLock()
proxy = {}
pattern = re.compile(r"""
^([\w\W]*?)\n
([\w\W]*?)\n
([\w\W]*?)\n
[\w\W]*\n
([\w\W]*?clkcount1">(\d+)[\w\W]*?)\n
""", re.VERBOSE)
root = Tk()
root.title('xxx refresher 0.1')
root.geometry("640x480+192+144")
ft = tkFont.Font(family = 'Courier', size = 9)
##------------------------------------------------------------------------------
lfConf = LabelFrame(text = 'conf', font = ft)
frTarget = Frame(lfConf)
lbl1 = Label(frTarget,
text = 'target:',
justify=LEFT,
font = ft)
lbl1.pack(side=LEFT, expand=1, anchor=NW)
target = StringVar()
edtTarget = Entry(frTarget,
textvariable = target,
justify=LEFT,
width=60,
font = ft)
target.set('http://xxx')
edtTarget.pack(side=LEFT, anchor=NW)
frTarget.pack(expand=1, anchor=NW, padx=8, pady=2)
frProxy = Frame(lfConf)
flag = IntVar()
cb = Checkbutton(frProxy,
variable = flag,
text = 'use proxy:',
font = ft,
command = onClickProxy)
flag.set(0)
cb.pack(side=LEFT)
pstr = StringVar()
edtProxy = Entry(frProxy,
textvariable = pstr,
width=30,
font = ft)
pstr.set('http://127.0.0.1:8118')
edtProxy.pack(side=LEFT)
frProxy.pack(expand=1, anchor=NW, padx=8, pady=2)
frRefresh = Frame(lfConf)
lbl2 = Label(frRefresh,
text = 'max interval:',
justify=LEFT, font = ft)
lbl2.pack(side=LEFT, expand=1, anchor=NW)
interval = StringVar()
edtInterval = Entry(frRefresh,
textvariable = interval,
justify=RIGHT,
width=6,
font = ft)
interval.set('3')
edtInterval.pack(side=LEFT, anchor=NW)
lbl3 = Label(frRefresh,
text = 'second(s)',
justify=LEFT, font = ft)
lbl3.pack(side=LEFT, expand=1, anchor=NW)
frRefresh.pack(expand=1, anchor=NW, padx=8, pady=2)
lfConf.pack(anchor=NW, padx=8, pady=2, ipadx=8)
##------------------------------------------------------------------------------
lfLog = LabelFrame(text = 'log', font = ft)
lblJobCount = Label(lfLog, text = '', justify=LEFT, font = ft)
lblJobCount.pack(expand=0, anchor=NW, padx=8, pady=2)
lblErrorCount = Label(lfLog, text = '', justify=LEFT, font = ft)
lblErrorCount.pack(expand=0, anchor=NW, padx=8, pady=2)
lblCurrentJob = Label(lfLog, text = '', justify=LEFT, font = ft)
lblCurrentJob.pack(expand=0, anchor=NW, padx=8, pady=2)
lblCounter = Label(lfLog, text = '', justify=LEFT, font = ft)
lblCounter.pack(expand=1, anchor=NW, padx=8, pady=2)
frResponse = Frame(lfLog)
txtResponse = Text(frResponse, font = ft, width = 80, height = 12)
txtResponse.pack(side=LEFT, expand=1, fill=BOTH)
sbResponse = Scrollbar(frResponse)
sbResponse.pack(side=RIGHT, fill=Y)
txtResponse.config(yscrollcommand=sbResponse.set)
sbResponse.config(command=txtResponse.yview)
frResponse.pack(expand=1, anchor=NW, padx=8, pady=2)
lfLog.pack(expand=1, fill=BOTH, anchor=NW, padx=8, pady=2, ipadx=8)
##------------------------------------------------------------------------------
btn1000 = Button(root,
text = '+1000',
font = ft,
command = onClick1000)
btn1000.pack(side=LEFT, anchor=NW, padx=8, pady=2, ipadx=8)
btn100 = Button(root,
text = '+100',
font = ft,
command = onClick100)
btn100.pack(side=LEFT, anchor=NW, padx=8, pady=2, ipadx=8)
btn10 = Button(root,
text = '+10',
font = ft,
command = onClick10)
btn10.pack(side=LEFT, anchor=NW, padx=8, pady=2, ipadx=8)
btn1 = Button(root,
text = '+1',
font = ft,
command = onClick1)
btn1.pack(side=LEFT, anchor=NW, padx=8, pady=2, ipadx=8)
btnClear = Button(root,
text = 'clear',
font = ft,
command = onClickClear)
btnClear.pack(side=LEFT, anchor=NW, padx=8, pady=2, ipadx=8)
btnQuit = Button(root,
text = 'quit',
font = ft,
command = onClickQuit)
btnQuit.pack(side=LEFT, anchor=NW, padx=8, pady=2, ipadx=8)
producer = Producer('Producer', queue)
# Quit if main thread quited.
# This must be called before start() is called.
producer.setDaemon(True)
producer.start()
consumer = Consumer('Consumer', queue)
consumer.setDaemon(True)
consumer.start()
root.mainloop()
0 块板砖 :
发表评论