1625-5 王子昂 总结《2017年3月13日》 【连续第163天总结】
A.Python 爬虫
B.昨天做好了CUI的愿望单爬虫,但是由于命令行的编码默认是GB2312的,与python的utf-8不匹配,所以萌生了制作GUI的想法
很简单,因为以前用过Tk的控制,在这个显示程序中完全不需要交互,而只是显示即可
刚开始是爬取完成以后进入mainloop()显示,测试了一下觉得有些迟滞,如果网络环境不好的话显示想必会更加慢
那先显示界面,再进行爬取,然后输出到文本框中不就行了吗。
尝试了一下,直接在mainloop()后添加text.insert()方法,发现没有反应
百思不得其解,明明之前做五子棋的时候也是开始mainloop()以后再更新文本的。检查了代码半天发现,之前的五子棋中的所有insert()方法都是绑定在某个函数,由事件驱动的;而这次是直接一条命令,因此无法执行。
遂查询使用after()(延时器)方法,仍然不行。思考了一下,这次绑定after方法是在mainloop开始之后的,所以绑定失败。于是把after()方法放在mainloop()之前,终于成功。
光秃秃的界面有些丑,再加上如果出现了不熟悉的游戏名字,没有图片来配合会认不出来。于是尝试爬取游戏图标地址并显示在界面中。查了一通,应该先用urllib2模块把图片以二进制下载下来,然后转换成gif格式用label控件显示在界面上
但是第一步,爬取图片链接就出现了问题:在线正则测试的网站对于python似乎有什么看法,在截取的一小段文本中php的正则只需要几百步,python却要几万步。把整个网页的源码放入以后,Python显示timeout,php则是catastrophic backtracking。
查询得知,正则回溯陷阱---由于正则表达式的写法,使得系统需要花费过多的时间和步数去查询。
举一个栗子:
考虑这样一个正则
/(a*)*b/
,用它来匹配”aaaaaaaaaa”(10个a组成的字符串)
花费了6143步才完成!如果再加上一个a呢,变成11个a组成的字符串会怎么样?
变成12287步了,翻了一倍。事实就是这样,当出现以上这种量词嵌套时,如果遭遇最坏情况(最后一个字符才能确实匹配不成功),那么这时正则引擎陷入灾难性回溯,时间复杂度为指数级)。 如果你试着再嵌套一层,9个a组成的字符串就能突破100万步了……
这才是正则表达式的难点和精髓:优化算法。
\d表示数字,\w表示字母,明明用.就可以全部通配,为什么要加以限制呢?---为了节省时间和资源
回溯算法非常方便,但也非常可怕。一旦落入回溯陷阱将会花费大量的时间。
于是图片的地址就爬不下来了,因为它的标识不易提取
其实我觉得使用尾部匹配应该可以快捷一点的,不过不知道为什么在线正则测试的网站似乎出了问题,python完全处理不了整页的源码。
附上代码:
#encoding:utf-8 import urllib2 import re import Tkinter top=Tkinter.Tk() text=Tkinter.Text(width=100) text.pack() def spider(): url='http://steamcommunity.com/id/whklhh/wishlist' request=urllib2.Request(url) response=urllib2.urlopen(request) data=response.read() # reg=r'<div class="gameListRowLogo">(?:.+?\n.+?){2}src="(.+?)">(?:.*?\n.+?){5}'+\ reg=r'<div class="discount_block discount_block_inline">.+?\n.+?>(-\d+%)(?:.+?\n.+?){2}¥ (\d+).+?\n.+?¥ (\d+)'+\ r'(?:.+?\n.+?){4}href="(.+?)"(?:.+?\n.+?){6}>(.+?)<' imgre=re.compile(reg) imglist=re.findall(imgre,data) for pro in imglist: text.insert('end',("%s\n\t现价:%s,原价:%s,折扣:%s,商品页面:%s\n")%(pro[4],pro[2],pro[1],pro[0],pro[3])) text.after(1,spider) Tkinter.mainloop()C. 明日计划
Java 日志