唔.....這個(gè)程序是這么多天來(lái)寫(xiě)的最麻煩,最費(fèi)時(shí)間精力的一個(gè)程序岭参,大概花了兩天時(shí)間
下面講講心酸歷程。憨琳。物咳。
-
看看運(yùn)行結(jié)果:
image.png
初始界面是這樣锣险,,而且我還只實(shí)現(xiàn)了小說(shuō)部分览闰,圖片部分甚至視頻部分都沒(méi)得精力搞下去了芯肤,,焕济,就光實(shí)現(xiàn)這個(gè)小說(shuō)部分纷妆,總共代碼長(zhǎng)度就800多行了,image.png
點(diǎn)進(jìn)去之后的一部分是這樣的:image.png
最上面是它們網(wǎng)站所有小說(shuō)的分類 晴弃,然后中間是用戶可以進(jìn)行的操作掩幢。
功能還是挺不錯(cuò)的,細(xì)節(jié)方面都調(diào)試過(guò)n遍了上鞠,現(xiàn)在bug應(yīng)該沒(méi)有际邻,,吧芍阎。世曾。
路徑下如果已經(jīng)存在就不會(huì)重復(fù)下載。
-
看起來(lái)簡(jiǎn)單的一個(gè)程序谴咸,要實(shí)現(xiàn)出它完整的功能還是挺麻煩的轮听。具體我才用了oop思想,也就是面向?qū)ο缶幊塘爰眩巡煌δ艿膶?shí)現(xiàn)代碼分開(kāi)編寫(xiě)血巍,可能會(huì)清楚些,封裝好后大概是這樣:image.png
很清晰明了珊随,My_thread是線程述寡,用來(lái)并行處理gui和爬蟲(chóng)的任務(wù);
Gui就是我們的tkinter主界面叶洞;Spider就是我們的爬蟲(chóng)部分鲫凶。最下面調(diào)用下。
大體步驟:
(一):實(shí)現(xiàn)Spider類的部分功能:
大概一共就這么多個(gè)函數(shù)衩辟,注釋已經(jīng)給的很詳細(xì)了螟炫。
注意內(nèi)容:
① number是類屬性,目的是判斷當(dāng)前是第幾只爬蟲(chóng)(比如小說(shuō)惭婿,圖片不恭,甚至視頻需要不同的爬蟲(chóng)來(lái)爬叶雹,這里記錄總共有幾只。)
這里面很多都是我在后期調(diào)試换吧,然后實(shí)現(xiàn)新功能的時(shí)候慢慢加的折晦,都是很有必要的。
③ 在實(shí)現(xiàn)get_etree的時(shí)候我也嘗試了很多次沾瓦,剛開(kāi)始一直修改timeout满着,因?yàn)橛袝r(shí)候網(wǎng)絡(luò)訪問(wèn)會(huì)很慢(表現(xiàn)出卡死的樣子),所以我設(shè)置只要timeout后就退出贯莺;后來(lái)我發(fā)現(xiàn)很多時(shí)候根本爬不到數(shù)據(jù)风喇。然后我給timeout設(shè)置很短,直接啥也沒(méi)有缕探,設(shè)置很大魂莫,它爬半天也沒(méi)結(jié)果。
注意一些類屬性的判斷啥的都是后期加上去的鞋邑,為了讓程序更完善。
它返回一個(gè)解析后所有數(shù)據(jù)的列表枚碗。
⑤ 下載文件的函數(shù)我為了和gui結(jié)合起來(lái)還是搞的挺復(fù)雜的:但是主體思想如果不用gui的話還是很簡(jiǎn)單,沒(méi)什么變化铸本,給的待下載列表里面就是一個(gè)個(gè)的字典视译,每個(gè)字典都是一本小說(shuō),字典有兩個(gè)鍵归敬,一個(gè)是小說(shuō)名字,還一個(gè)是小說(shuō)url鄙早。
⑥ deal_novel大概就是專門處理與gui交互的準(zhǔn)備過(guò)程汪茧,將一些必要的參數(shù)爬取下來(lái),比如給⑤的參數(shù)列表限番,就在這里面實(shí)現(xiàn)舱污,這里我也把所有頁(yè)的所有小說(shuō)都爬下來(lái)了(當(dāng)然用戶可以在gui界面手動(dòng)停止。)大概這樣:很多東西我都注釋了的弥虐,還挺容易看懂的扩灯。
⑦ start方法大概就是統(tǒng)籌下媚赖,做預(yù)處理工作等等:大概內(nèi)容就這么多,很多東西不是一開(kāi)始就能構(gòu)思完的珠插,函數(shù)框架可以在剛開(kāi)始構(gòu)建出來(lái)惧磺,但是內(nèi)容確實(shí)要根據(jù)程序的需要不斷變化。
(二):實(shí)現(xiàn)Gui類的部分功能:
這個(gè)gui是整個(gè)程序最復(fù)雜的一部分了(大概占了4捻撑,500行代碼)磨隘,gui是用python 標(biāo)準(zhǔn)庫(kù)tkinter開(kāi)發(fā)的, 如果沒(méi)有tkinter基礎(chǔ)可能難看懂 顾患。gui實(shí)現(xiàn)過(guò)程大概有以下幾步:1. 創(chuàng)建主窗口番捂,同時(shí)在主窗口的里面創(chuàng)建很多需要的組件。
- 給不同的組件綁定不同的事件江解。
- 當(dāng)觸發(fā)gui的事件后就設(shè)計(jì)函數(shù)去處理事件设预。
- gui的mainloop, 也就是一個(gè)永真循環(huán)犁河。但是可以被阻塞鳖枕,也可以在里面創(chuàng)建子進(jìn)程。
一個(gè)個(gè)大致講下:
其中frames是所有的框架組件,buttons是所有的按鈕組件彭谁,labels是所有的標(biāo)簽組件吸奴,它們都是列表,為什么要用列表呢缠局?原因是方便管理则奥,當(dāng)我處理同一類的組件時(shí)它們放在一起會(huì)很好處理,所以這是個(gè)好習(xí)慣狭园,把所有同類型的組件放在同一個(gè)列表里读处。
③ 放置主窗體所有組件:像這樣,有的用gird唱矛,有的用pack罚舱,看實(shí)際需求。
④ 處理主窗體的所有事件:這里注意個(gè)細(xì)節(jié):我把按鍵響應(yīng)與按鈕綁定在一起绎谦,而不是單獨(dú)處理管闷,這樣會(huì)很方便,f1和f2就是把按鍵響應(yīng)和按鈕綁定在一起的:
我把用戶點(diǎn)擊右上角的退出事件和離開(kāi)事件也綁定在一起了窃肠,可以方便處理包个。 ⑤ 設(shè)置字體沒(méi)啥說(shuō)的,用tkinter.font庫(kù)生成一個(gè)字體列表冤留,用的時(shí)候從里面取就好了:
⑦ 當(dāng)用戶點(diǎn)擊“小說(shuō)”后會(huì)觸發(fā)一個(gè)很重要的事件(主要代碼也在里面),結(jié)果是會(huì)生成一個(gè)子窗體糯而,然后各種操作也是在子窗體里面去完成天通,這樣做的好處,就是可以靈活的處理不同類型的主事件歧蒋,比如圖片啊土砂,視頻啊,小說(shuō)啊什么谜洽,點(diǎn)擊后會(huì)有更多的靈活處理的空間萝映。
放置這些組件也是在響應(yīng)函數(shù)里完成的。同時(shí)還需要在里面完成處理子窗體的組件綁定的各種事件:
這里重要的點(diǎn)也是:將按鍵事件與按鈕綁定在一起阐虚,方便一起處理序臂。
⑧ 各種響應(yīng)事件的實(shí)現(xiàn):我都放在類里面,作為類的成員函數(shù)实束,這樣一是方便奥秆,二是方便與spider爬蟲(chóng)類交互。比如這個(gè)關(guān)閉子窗口的事件:需要把用戶點(diǎn)擊右上角退出和esc離開(kāi)事件都綁定成了它咸灿。
构订。。避矢。大概就說(shuō)這么多悼瘾,有tkinter基礎(chǔ)的好搞些,慢慢搞總是能搞出來(lái)的审胸。
這里我再著重說(shuō)下幾個(gè)我之前不太會(huì)的:
- 創(chuàng)建frame框架時(shí)要手動(dòng)設(shè)置它的長(zhǎng)和寬亥宿, 創(chuàng)建各種組件時(shí)如果你需要按照你的規(guī)則拜訪好,最好也給他們?cè)O(shè)置長(zhǎng)和寬砂沛, 但是這個(gè)長(zhǎng)和寬和主窗體設(shè)置時(shí)候的長(zhǎng)和寬是不同的烫扼, 差不多組件的長(zhǎng)和寬代表它在”一面“一個(gè)可視范圍內(nèi)能占多數(shù)條(例如 listbox組件)
- 將組件與拉條綁定, 需要將拉條的command綁定成組件的yview函數(shù)碍庵, 將組件的yscrollcommand綁定成拉條的set函數(shù)映企。
- grid的sticky 將組件放好后邊緣對(duì)齊很重要。 pack的fill將組件沿著x或者y或者兩者填充滿静浴, side表示將組件放在窗體的哪個(gè)邊上卑吭。
(三):實(shí)現(xiàn)Thread類的功能:
我實(shí)現(xiàn)的thread類繼承threading.Thread類,這樣我只要重寫(xiě)它的run方法马绝,那么run方法里面的內(nèi)容就是在子線程中會(huì)執(zhí)行的方法。這里為什么要用thread開(kāi)線程挣菲? 因?yàn)間ui界面是一個(gè)死循環(huán)富稻, 你要在死循環(huán)里面暫停后去處理別的事件(這里比如爬蟲(chóng)事件)掷邦, 那么主窗體會(huì)卡死, 未響應(yīng)椭赋, 所以你必須要開(kāi)線程去處理那些處理完需要很長(zhǎng)時(shí)間的代碼抚岗。
我加了個(gè)code哪怔, 這個(gè)用來(lái)實(shí)現(xiàn)不同的處理宣蔚, target_list則是傳遞過(guò)來(lái)的待下載的目標(biāo)列表, 然后用線程去下載认境。
run方法就是線程的主題胚委,線程會(huì)做這里面的事情:
我像這樣用不同的code來(lái)識(shí)別處理不同的事件,這樣很方便叉信,不用寫(xiě)額外的線程代碼啥的亩冬。
(四):慢慢一步一步debug,統(tǒng)領(lǐng)協(xié)調(diào)整個(gè)程序硼身,處理類之間的交互:
然后最后這步才是最重要的硅急,我們需要把自己想象成用戶,去嘗試運(yùn)行自己的程序佳遂,然后處理程序的bug营袜,或者哪些需要改進(jìn)的也要自己去改進(jìn),反正都到了這步了丑罪,慢慢來(lái)就好了荚板,我也是花了很長(zhǎng)時(shí)間在這步,有時(shí)候運(yùn)行的時(shí)候想到了怎么改進(jìn)巍糯,但是正在處理別的啸驯,就用記事本把事情記下來(lái)之后再處理,一步步完善祟峦,直到最后把程序做好罚斗,總之,用戶的體驗(yàn)才是最重要的宅楞,你程序?qū)懙脑俸脹](méi)有用戶喜歡也是白搭针姿,所以跟著用戶的喜好走很重要的。
其中我在這步里面就加了n個(gè)類的成員屬性去完成不同的事情厌衙,處理各種bug距淫。。
總之很煎熬婶希,但只要你堅(jiān)持下來(lái)了榕暇,你就能勝利。
大概。彤枢。狰晚。就寫(xiě)這么多吧,缴啡,壁晒,這個(gè)做完自己還是有很大的成長(zhǎng), 但是也看到了很多自己的不足业栅, 要學(xué)習(xí)的東西還是太多了秒咐, ,希望大家好好學(xué)習(xí)碘裕,携取, 知識(shí)是最棒的。娘汞。 ?
(如果想要源碼或者exe文件或者有想要討論的地方可以私信我歹茶。∧阆遥看到必回惊豺。謝謝)