? 第一步:引入爬蟲利器包
首先,我們需要引入requests和BeautifulSoup包來讓我們獲取到數(shù)據(jù),而在使用BeautifulSoup中底桂,一般會提示需要在函數(shù)()中添加features="html5lib"植袍,所以我們也引入html5lib。
灰色的部分即在整個(gè)代碼里沒有被使用到的籽懦,至于為什么html5lib呈灰色于个,小白我也不太明白。
第二步:我們先定義一個(gè)類
這個(gè)習(xí)慣要掌握好暮顺,這是讓我們有面向?qū)ο蟮乃季S厅篓,而不是直接面對過程。也便于以后一層一層嵌套的繼承捶码。不會丟在一起亂七八糟贷笛。然后我們在這個(gè)類的初始化函數(shù) def __init__中,我們可以定義一些類里面的全局變量宙项。我們這里面以縱橫中文網(wǎng)的一篇小說《大俠蕭金衍》為例。鏈接地址:http://book.zongheng.com/showchapter/779260.html
第三步:我們需要看看這個(gè)小說有多少章節(jié)株扛,并把每個(gè)章節(jié)的名字給爬取出來
在類里面尤筐,我們定義一個(gè)函數(shù)為Geturlandtitle,我們在這個(gè)函數(shù)里面實(shí)現(xiàn)獲取每一章節(jié)的名稱和跳轉(zhuǎn)的url洞就,以備下個(gè)函數(shù)獲取每一章節(jié)里面的文本盆繁。老套路,先用requests.get()獲取到代碼旬蟋,并使用 .text 輸出為str油昂,然后輸入給BeautifulSoup,根據(jù)標(biāo)簽來獲取內(nèi)容倾贰。由于一個(gè)網(wǎng)站往往是各種標(biāo)簽層層嵌套冕碟,所以最好多使用BeautifulSoup中的 find/find_all 來逐步精確定位到數(shù)據(jù)源的代碼塊。我們這里先精確到帶有 class = ‘col-4’ 的 <li> 標(biāo)簽匆浙,然后再精確到它下面包含的 <a> 標(biāo)簽安寺。在此需注意,BeautifulSoup返回回來的是一個(gè)bs4的玩意兒首尼,我們需要用find_all函數(shù)把想要的標(biāo)簽給找出來挑庶,然后再把結(jié)果用str()轉(zhuǎn)成BeautifulSoup可以認(rèn)識的,重復(fù)软能。
最好find_all函數(shù)返回的是一個(gè)<a>標(biāo)簽的list迎捺,那么此時(shí)我們需要for...in這個(gè)list,在這里需要提到查排,如上圖凳枝,我們是直接 for each in SecondA,那么每一次循環(huán)是雹嗦,each其實(shí)是被SeacondA[0]范舀,SecondA[1]這些給賦值合是,而不是從0到SecondA的最后一個(gè)索引數(shù)。因?yàn)楝F(xiàn)在Python是面對對象了锭环。還需要實(shí)現(xiàn)以前那種效果的話聪全,需要這樣寫:
繼續(xù)我們的爬蟲旅程,循環(huán)的用get去獲取每個(gè)<a>標(biāo)簽中的內(nèi)容辅辩,get()是要看<a>標(biāo)簽中有些什么难礼。獲取后再推入剛才初始化過的對應(yīng)空集合中。
第四步:我們通過上面獲取到的url來獲取每個(gè)章節(jié)中的內(nèi)容
我們假設(shè)上一個(gè)函數(shù)已經(jīng)把每個(gè)章節(jié)跳轉(zhuǎn)的url都推入了self.url這個(gè)list中玫锋,然后我們對這個(gè)list進(jìn)行for循環(huán)蛾茉,然后跟上面的操作類似,逐步的提取對應(yīng)章節(jié)中的文本文件撩鹿。然后print出來看看是否有些不需要的空格啊谦炬,沒用的文本信息之類的,使用函數(shù)移除掉节沦。然后同理把內(nèi)容塞入初始的空list中键思。
第五步:把爬出來的數(shù)據(jù)寫入對應(yīng)文件。這里我們以txt為例
首先我們定義一個(gè)writer函數(shù)甫贯,初始化函數(shù)的輸入變量為(name吼鳞,path,content)叫搁,name是小說章節(jié)名稱赔桌,path是小說爬出來的數(shù)據(jù)寫到本地文件的路徑,content是小說章節(jié)下的內(nèi)容渴逻。write_flag = True 這個(gè)不知道有啥用疾党,似乎刪除后也不會報(bào)錯,也能正常運(yùn)行并輸出結(jié)果txt裸卫,暫且不管仿贬。然后我們使用with open ... as...,這里有兩個(gè)知識點(diǎn):1:open和with open ... as的區(qū)別墓贿,2:文件打開模式的選擇茧泪。
1、open和with open ... as的區(qū)別
file = open("test.txt","r")
for line in file.readlines():
? ? print line
file.close()
? ? open需要在最后加一個(gè)close()語句聋袋,而且如果出現(xiàn)了異常队伟,就無法關(guān)閉對象。而with open的好處在于幽勒,如果出現(xiàn)了異常嗜侮,也會自動關(guān)閉,還不用寫close()語句。
2锈颗、文件打開模式
我們因?yàn)槭且崛∷械奈恼聝?nèi)容顷霹,所以我們需要用‘a(chǎn)+’的模式。我們的代碼如下:
最后一步:我們實(shí)例化這個(gè)類击吱,然后調(diào)用它的各個(gè)函數(shù)淋淀,最終使用writer函數(shù)寫入本地的txt中。
這里有幾個(gè)點(diǎn)需要注意:
1覆醇、if __name__=='__main__’:這個(gè)代表著整個(gè)代碼塊從這里開始執(zhí)行朵纷,而不是去執(zhí)行上面class中的內(nèi)容
2、dl = Downloader()永脓,是實(shí)例化了這個(gè)類
3袍辞、Python默認(rèn)是單線程的,所以我們看到 dl.Geturlandtitle() 以及 dl.GetContent()是不會出現(xiàn)異步的問題的常摧。
今天的筆記結(jié)束搅吁,放出小小成果: