鱼C论坛

 找回密码
 立即注册
查看: 4498|回复: 8

Python的Tkinter编程太长时间控制权不交还操作系统,求解决方案

[复制链接]
发表于 2015-9-1 19:50:58 | 显示全部楼层 |阅读模式
100鱼币
代码如下,点击给我爬!!!程序就会卡死,本来想把输出结果放入到Text组件中,结果程序卡死,很尴尬,求解决方案

  1. from tkinter import *
  2. import urllib.request
  3. import urllib.error
  4. import os
  5. import http.client
  6. import time
  7. import re
  8. import random
  9. import math

  10. class App(Frame):
  11.     def __init__(self,mw):
  12.         self.headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36'}
  13.         self.enctype = 'utf-8'
  14.         self.proxies = []

  15.         Frame.__init__(self,mw)
  16.         #初始默认值字典
  17.         self.var = dict()
  18.         #抓取地址----------------------------------------------------------------------------
  19.         self.frmURL = Frame(mw)     #抓取地址框架
  20.         
  21.         self.lblURL = Label(self.frmURL,text="抓取地址:")  #抓取地址标签
  22.         self.lblURL.grid(row=0,column=0,padx=10)

  23.         var = StringVar()
  24.         var.set(r"http://image.baidu.com/search/flip?tn=baiduimage&word=mai%20kuraki&pn=")
  25.         self.var["url1"] = var
  26.         self.entURL1 = Entry(self.frmURL,width=80,textvariable=self.var["url1"])   #地址1输入框
  27.         self.entURL1.grid(row=0,column=1)

  28.         var = StringVar()
  29.         var.set("0")
  30.         self.var["url2"] = var
  31.         self.entURL2 = Entry(self.frmURL,width=6,textvariable=self.var["url2"])   #地址2输入框
  32.         self.entURL2.grid(row=0,column=2)

  33.         var = StringVar()
  34.         var.set("")
  35.         self.var["url3"] = var
  36.         self.entURL3 = Entry(self.frmURL,textvariable=self.var["url3"])  #地址3输入框
  37.         self.entURL3.grid(row=0,column=3)
  38.         
  39.         self.lblStep = Label(self.frmURL,text="递增的量:") #递增量标签
  40.         self.lblStep.grid(row=0,column=4,padx=10)

  41.         var = StringVar()
  42.         var.set("1")
  43.         self.var["step"] = var
  44.         self.entStep = Entry(self.frmURL,width=6,textvariable=self.var["step"])  #递增量输入框
  45.         self.entStep.grid(row=0,column=5)
  46.         
  47.         self.frmURL.grid(sticky=W+E,row=0,column=0,pady=5)
  48.         #-------------------------------------------------------------------------------------
  49.         
  50.         #代理地址--------------------------以及times-------------------------------------------
  51.         self.frmProxy = Frame(mw)   #代理框架

  52.         self.lblProxy = Label(self.frmProxy,text="代理地址:")   #代理标签
  53.         self.lblProxy.grid(row=0,column=0,padx=10)

  54.         var = StringVar()
  55.         var.set(r"http://www.xicidaili.com/")
  56.         self.var["proxyurl"] = var
  57.         self.entProxyURL = Entry(self.frmProxy,width=80,textvariable=self.var["proxyurl"])  #代理地址输入框
  58.         self.entProxyURL.grid(row=0,column=1)

  59.         var = IntVar()
  60.         var.set(1)
  61.         self.var["http"] = var
  62.         self.cbtHttp = Checkbutton(self.frmProxy,text="HTTP",variable = self.var["http"])    #HTTP开关
  63.         self.cbtHttp.grid(row=0,column=2,padx=10)

  64.         var = IntVar()
  65.         var.set(0)
  66.         self.var["https"] = var
  67.         self.cbtHttps = Checkbutton(self.frmProxy,text="HTTPS",variable = self.var["https"])     #HTTPS开关
  68.         self.cbtHttps.grid(row=0,column=3,padx=10)

  69.         self.lblTimes = Label(self.frmProxy,text="最大失败次数:")   #最大失败次数标签
  70.         self.lblTimes.grid(row=0,column=4,padx=10)

  71.         var = StringVar()
  72.         var.set("5")
  73.         self.var["times"] = var
  74.         self.entTimes = Entry(self.frmProxy,textvariable = self.var["times"],width=6)   #最大失败次数
  75.         self.entTimes.grid(row=0,column=5,padx=10)
  76.         
  77.         self.frmProxy.grid(sticky=W+E,row=1,column=0,pady=5)
  78.         #-------------------------------------------------------------------------------------

  79.         #正则表达式区域--------------------------------------------------------------------------
  80.         self.frmre = Frame(mw)  #正则表达式框架
  81.         
  82.         self.frmreURL = LabelFrame(self.frmre,text="网页正则表达式",padx=10)     #网页正则表达式
  83.         self.var["reurl"] = r'''"objURL":"(http://.+?\.(?:jpg|jpeg|gif))"'''
  84.         self.txtURL = Text(self.frmreURL,width=60,height=10)
  85.         self.txtURL.pack()
  86.         self.txtURL.insert(INSERT,self.var["reurl"])
  87.         self.frmreURL.grid(sticky=W,row=0,column=0,padx=10)

  88.         self.frmreProxy = LabelFrame(self.frmre,text="代理正则表达式",padx=10)     #代理正则表达式
  89.         self.var["reproxy"] = r'''<tr\sclass[^>]*?>\s*?
  90.     <td>.+</td>\s*?
  91.     <td>(.*)?</td>\s*?
  92.     <td>(.*)?</td>\s*?
  93.     <td>(.*)?</td>\s*?
  94.     <td>(.*)?</td>\s*?
  95.     <td>(.*)?</td>\s*?
  96.     <td>(.*)?</td>\s*?
  97. </tr>'''
  98.         self.txtProxy = Text(self.frmreProxy,width=60,height=10)
  99.         self.txtProxy.pack()
  100.         self.txtProxy.insert(INSERT,self.var["reproxy"])
  101.         self.frmreProxy.grid(sticky=E,row=0,column=1,padx=10)
  102.         
  103.         self.frmre.grid(sticky=W+E,row=2,column=0,pady=5)
  104.         #--------------------------------------------------------------------------------------

  105.         #文件路径区域-----------------------------------------------------------------------------
  106.         self.frmPath = Frame(mw)    #文件路径框架

  107.         self.lblPath = Label(self.frmPath,text="保存路径:")      #标签
  108.         self.lblPath.pack(side=LEFT,padx=10)

  109.         var = StringVar()
  110.         var.set(r"G:\图片\仓木麻衣")
  111.         self.var["path"] = var
  112.         self.entPath = Entry(self.frmPath,textvariable=self.var["path"],width=125)    #保存路径
  113.         self.entPath.pack(side=RIGHT,padx=10)
  114.         
  115.         self.frmPath.grid(sticky=W+E,row=3,column=0,pady=5)
  116.         #---------------------------------------------------------------------------------------

  117.         #按钮区域---------------------------------------------------------------------------------
  118.         self.frmButton = Frame(mw)  #按钮框架

  119.         self.btnSpide = Button(self.frmButton,text="给我爬!!!",command=self.spide) #开始爬
  120.         self.btnSpide.pack(side=LEFT,padx=10,ipadx=60,ipady=5)

  121.         self.btnExit = Button(self.frmButton,text="退出",command=quit)
  122.         self.btnExit.pack(side=RIGHT,padx=10,ipadx=60,ipady=5)

  123.         self.frmButton.grid(sticky=W+E,row=4,column=0,pady=5)
  124.         #----------------------------------------------------------------------------------------

  125.     def spide(self):
  126.         self.get_proxy() #取得代理
  127.         self.create_localhost()  #生成本地直接访问proxies
  128.         self.download()  #开始下载

  129.     def get_proxy(self):            #从代理页面提取代理IP及端口
  130.         proxy_url = self.var["proxyurl"].get()
  131.         req = urllib.request.Request(proxy_url,None,self.headers)
  132.         response = self.get_result(req)
  133.         html = response.read().decode('utf-8')
  134.         p = re.compile(self.var["reproxy"],re.VERBOSE)
  135.         proxy_list = p.findall(html)
  136.         for each_proxy in proxy_list[1:]:
  137.             if self.var["http"].get() == 1 and each_proxy[4] == 'HTTP' or self.var["https"].get() == 1 and each_proxy[4] == 'HTTPS':
  138.                 self.proxies.append(each_proxy[0]+':'+each_proxy[1])

  139.     def get_result(self,req_or_url,is_retrieve=False,filename = None):         #取得网页页面
  140.         max_error_times = int(self.var["times"].get())
  141.         error_time = 0
  142.         while True:
  143.             try:
  144.                 if error_time == max_error_times:
  145.                     print('失败次数达%d次......放弃操作' % max_error_times)
  146.                     return None
  147.                 error_time += 1
  148.                 if is_retrieve:
  149.                     return urllib.request.urlretrieve(req_or_url,filename)
  150.                 else:
  151.                     return urllib.request.urlopen(req_or_url)
  152.             except urllib.error.URLError as e:
  153.                 if hasattr(e,'code'):         
  154.                     print(e.code,e.reason)
  155.                     self.change_proxy()
  156.                     continue
  157.                 elif hasattr(e,'reason'):
  158.                     print(e)
  159.                     self.change_proxy()
  160.                     continue
  161.             except (ConnectionResetError,http.client.BadStatusLine) as e:
  162.                 print(e)
  163.                 self.change_proxy()
  164.                 continue
  165.             except TimeoutError as e:
  166.                 print(e)
  167.                 print('服务器长时间无响应,自动切换代理.....')
  168.                 self.change_proxy()
  169.                 continue

  170.     def change_proxy(self):     #切换代理
  171.         proxy = random.choice(self.proxies)
  172.         if proxy == None:
  173.             proxy_support = urllib.request.ProxyHandler({})
  174.         else:
  175.             proxy_support = urllib.request.ProxyHandler({'http':proxy})
  176.         opener = urllib.request.build_opener(proxy_support)
  177.         opener.addheaders = [('User-Agent',self.headers['User-Agent'])]
  178.         urllib.request.install_opener(opener)
  179.         print('智能切换代理:%s' % ('本机' if proxy==None else proxy))

  180.     def create_localhost(self):     #生成本地直接访问的proxies
  181.         number = int((math.sqrt(5)-1)/2 * len(self.proxies))
  182.         for x in range(number):
  183.             self.proxies.append(None)

  184.     def download(self):     #下载图片
  185.         save_path = self.var["path"].get()
  186.         for pic_url in self.get_pic():         
  187.             file_name = os.path.split(pic_url)[1]
  188.             if not os.path.isdir(save_path):    #目录不存在就创建
  189.                 os.makedirs(save_path)
  190.             #如果文件已存在则跳过
  191.             if os.path.exists(save_path+'\\'+file_name):
  192.                 print('文件%s已存在...' % file_name)
  193.                 continue
  194.             self.get_result(pic_url,True,save_path+'\\'+file_name)
  195.             print('本次成功下载编号%s! %s' % (self.var['url2'].get() , pic_url))
  196.             self.var['url2'].set(str(int(self.var['url2'].get())+int(self.var['step'].get())))

  197.     def get_pic(self):      #生成器,返回一个图片链接
  198.         url1 = self.var['url1'].get()
  199.         url2 = self.var['url2'].get()
  200.         url3 = self.var['url3'].get()
  201.         while True:
  202.             url = url1+url2+url3
  203.             req = urllib.request.Request(url,None,self.headers)
  204.             response = self.get_result(req)
  205.             if response == None:
  206.                 print('获取页面失败.....')
  207.                 quit
  208.             html = response.read().decode(self.enctype)
  209.             pic = re.compile(self.var['reurl'],re.VERBOSE)
  210.             for pic in pic.finditer(html):
  211.                 yield pic.group(1)
  212.             time.sleep(5)

  213. def main():
  214.     root = Tk()
  215.     root.title("爬虫4------Margular制作")
  216.     root.iconbitmap("spider.ico")
  217.     root.resizable(True,True)
  218.     app1 = App(mw=root)
  219.     app1.mainloop()
  220.                     
  221. if __name__ == '__main__':
  222.     main()
复制代码

最佳答案

查看完整内容

代码太长,也没看。你试试在程序爬完之前,把所有的返回值都写在变量里面,不要写到tk的组件里面。因为图形化的列表框什么的,超频繁的读取写入会卡死的。这样反而拖慢电脑速度。另外一个就是,卡死也可能跟电脑配置有关呢。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-9-1 19:50:59 | 显示全部楼层
代码太长,也没看。你试试在程序爬完之前,把所有的返回值都写在变量里面,不要写到tk的组件里面。因为图形化的列表框什么的,超频繁的读取写入会卡死的。这样反而拖慢电脑速度。另外一个就是,卡死也可能跟电脑配置有关呢。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-9-2 12:38:50 | 显示全部楼层
同意楼上。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-9-2 14:10:02 | 显示全部楼层
同意楼上的楼上!!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-9-2 20:11:12 | 显示全部楼层
流氓大叔 发表于 2015-9-2 11:36
代码太长,也没看。你试试在程序爬完之前,把所有的返回值都写在变量里面,不要写到tk的组件里面。因为图形 ...

考虑了下你说的,并不是你说的那个问题,我的返回值全都是在变量里的。要是由VB的DoEvents就好了,这个关键字就是循环的时候暂时交还操作系统权限,这样就不会卡,不知道Python有没有类似的,求大家帮忙查查问问,百度找不到答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-9-2 20:48:51 | 显示全部楼层
我已经解决了,涉及到Python的一个叫做_thread的模块,使用多线程编程
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-9-26 20:45:13 | 显示全部楼层
楼主,可不可以散点鱼币,刚刚学习python的菜鸟:sweat:
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-12-3 19:03:38 | 显示全部楼层
完全看不懂啦啦啦啦啦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

头像被屏蔽
发表于 2016-1-28 08:16:39 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-20 08:35

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表