美文网首页
python爬虫爬取某学习网站并用tkinter将整个程序封装成

python爬虫爬取某学习网站并用tkinter将整个程序封装成

作者: _Mirage | 来源:发表于2020-03-29 06:07 被阅读0次

唔.....这个程序是这么多天来写的最麻烦,最费时间精力的一个程序,大概花了两天时间
下面讲讲心酸历程。。。

  1. 看看运行结果:


    image.png
    初始界面是这样,,而且我还只实现了小说部分,图片部分甚至视频部分都没得精力搞下去了,,,就光实现这个小说部分,总共代码长度就800多行了, image.png
    点进去之后的一部分是这样的: image.png

最上面是它们网站所有小说的分类 ,然后中间是用户可以进行的操作。
功能还是挺不错的,细节方面都调试过n遍了,现在bug应该没有,,吧。。

下载界面是这样的: image.png

路径下如果已经存在就不会重复下载。

  1. 看起来简单的一个程序,要实现出它完整的功能还是挺麻烦的。具体我才用了oop思想,也就是面向对象编程,把不同功能的实现代码分开编写,可能会清楚些,封装好后大概是这样: image.png

    很清晰明了,My_thread是线程,用来并行处理gui和爬虫的任务;
    Gui就是我们的tkinter主界面;Spider就是我们的爬虫部分。最下面调用下。

大体步骤:
(一):实现Spider类的部分功能:


image.png
image.png

大概一共就这么多个函数,注释已经给的很详细了。
注意内容:
① number是类属性,目的是判断当前是第几只爬虫(比如小说,图片,甚至视频需要不同的爬虫来爬,这里记录总共有几只。)

② 构造函数大概初始化了: image.png

这里面很多都是我在后期调试,然后实现新功能的时候慢慢加的,都是很有必要的。

③ 在实现get_etree的时候我也尝试了很多次,刚开始一直修改timeout,因为有时候网络访问会很慢(表现出卡死的样子),所以我设置只要timeout后就退出;后来我发现很多时候根本爬不到数据。然后我给timeout设置很短,直接啥也没有,设置很大,它爬半天也没结果。

我最后才想了个好办法:就是开循环,timeout尽可能设置小,如果超时了先不退出,循环个10几次总时间也不长,因为每次的时间timeout挺短的,这样几乎每次都可以短时间内爬取到数据:超时后的处理大概像这样,先捕捉异常然后再处理它: image.png ,

注意一些类属性的判断啥的都是后期加上去的,为了让程序更完善。

这里循环完了还没访问到数据的话就退出了,认定网络不好或者原网站出了问题: image.png ④ 解析函数大概就这么简单: image.png

它返回一个解析后所有数据的列表。

⑤ 下载文件的函数我为了和gui结合起来还是搞的挺复杂的: image.png

但是主体思想如果不用gui的话还是很简单,没什么变化,给的待下载列表里面就是一个个的字典,每个字典都是一本小说,字典有两个键,一个是小说名字,还一个是小说url。

⑥ deal_novel大概就是专门处理与gui交互的准备过程,将一些必要的参数爬取下来,比如给⑤的参数列表,就在这里面实现,这里我也把所有页的所有小说都爬下来了(当然用户可以在gui界面手动停止。)大概这样: image.png

很多东西我都注释了的,还挺容易看懂的。

⑦ start方法大概就是统筹下,做预处理工作等等: image.png

大概内容就这么多,很多东西不是一开始就能构思完的,函数框架可以在刚开始构建出来,但是内容确实要根据程序的需要不断变化。

(二):实现Gui类的部分功能:
这个gui是整个程序最复杂的一部分了(大概占了4,500行代码),gui是用python 标准库tkinter开发的, 如果没有tkinter基础可能难看懂 。gui实现过程大概有以下几步:1. 创建主窗口,同时在主窗口的里面创建很多需要的组件。

  1. 给不同的组件绑定不同的事件。
  2. 当触发gui的事件后就设计函数去处理事件。
  3. gui的mainloop, 也就是一个永真循环。但是可以被阻塞,也可以在里面创建子进程。
我设计了这些函数: image.png image.png image.png image.png image.png

一个个大致讲下:

① 构造函数:创建主窗体,设置标题啥的,设置很多个和spider类通信的实例属性: image.png ② 生成主窗体所有组件: image.png

其中frames是所有的框架组件,buttons是所有的按钮组件,labels是所有的标签组件,它们都是列表,为什么要用列表呢?原因是方便管理,当我处理同一类的组件时它们放在一起会很好处理,所以这是个好习惯,把所有同类型的组件放在同一个列表里。

③ 放置主窗体所有组件: image.png

像这样,有的用gird,有的用pack,看实际需求。

④ 处理主窗体的所有事件: image.png
这里注意个细节:我把按键响应与按钮绑定在一起,而不是单独处理,这样会很方便,f1和f2就是把按键响应和按钮绑定在一起的: image.png
我把用户点击右上角的退出事件和离开事件也绑定在一起了,可以方便处理。 ⑤ 设置字体没啥说的,用tkinter.font库生成一个字体列表,用的时候从里面取就好了: image.png ⑥ 主体和start就是做初始工作,程序从start开始,依次调用所有的函数:主体是一个永真循环: image.png

⑦ 当用户点击“小说”后会触发一个很重要的事件(主要代码也在里面),结果是会生成一个子窗体,然后各种操作也是在子窗体里面去完成,这样做的好处,就是可以灵活的处理不同类型的主事件,比如图片啊,视频啊,小说啊什么,点击后会有更多的灵活处理的空间。

这是子窗体的所有组件: image.png
放置这些组件也是在响应函数里完成的。同时还需要在里面完成处理子窗体的组件绑定的各种事件: image.png

这里重要的点也是:将按键事件与按钮绑定在一起,方便一起处理。

⑧ 各种响应事件的实现:我都放在类里面,作为类的成员函数,这样一是方便,二是方便与spider爬虫类交互。比如这个关闭子窗口的事件: image.png

需要把用户点击右上角退出和esc离开事件都绑定成了它。

。。。大概就说这么多,有tkinter基础的好搞些,慢慢搞总是能搞出来的。

这里我再着重说下几个我之前不太会的:

  1. 创建frame框架时要手动设置它的长和宽, 创建各种组件时如果你需要按照你的规则拜访好,最好也给他们设置长和宽, 但是这个长和宽和主窗体设置时候的长和宽是不同的, 差不多组件的长和宽代表它在”一面“一个可视范围内能占多数条(例如 listbox组件)
  2. 将组件与拉条绑定, 需要将拉条的command绑定成组件的yview函数, 将组件的yscrollcommand绑定成拉条的set函数。
  3. grid的sticky 将组件放好后边缘对齐很重要。 pack的fill将组件沿着x或者y或者两者填充满, side表示将组件放在窗体的哪个边上。

(三):实现Thread类的功能:
我实现的thread类继承threading.Thread类,这样我只要重写它的run方法,那么run方法里面的内容就是在子线程中会执行的方法。这里为什么要用thread开线程? 因为gui界面是一个死循环, 你要在死循环里面暂停后去处理别的事件(这里比如爬虫事件), 那么主窗体会卡死, 未响应, 所以你必须要开线程去处理那些处理完需要很长时间的代码。

thread继承自标准库 。 image.png
我加了个code, 这个用来实现不同的处理, target_list则是传递过来的待下载的目标列表, 然后用线程去下载。
run方法就是线程的主题,线程会做这里面的事情: image.png

我像这样用不同的code来识别处理不同的事件,这样很方便,不用写额外的线程代码啥的。

(四):慢慢一步一步debug,统领协调整个程序,处理类之间的交互:
然后最后这步才是最重要的,我们需要把自己想象成用户,去尝试运行自己的程序,然后处理程序的bug,或者哪些需要改进的也要自己去改进,反正都到了这步了,慢慢来就好了,我也是花了很长时间在这步,有时候运行的时候想到了怎么改进,但是正在处理别的,就用记事本把事情记下来之后再处理,一步步完善,直到最后把程序做好,总之,用户的体验才是最重要的,你程序写的再好没有用户喜欢也是白搭,所以跟着用户的喜好走很重要的。
其中我在这步里面就加了n个类的成员属性去完成不同的事情,处理各种bug。。
总之很煎熬,但只要你坚持下来了,你就能胜利。

大概。。。就写这么多吧,,,这个做完自己还是有很大的成长, 但是也看到了很多自己的不足, 要学习的东西还是太多了, ,希望大家好好学习,, 知识是最棒的。。 ✌

(如果想要源码或者exe文件或者有想要讨论的地方可以私信我。。看到必回。谢谢)

相关文章

网友评论

      本文标题:python爬虫爬取某学习网站并用tkinter将整个程序封装成

      本文链接:https://www.haomeiwen.com/subject/txfyuhtx.html