最近閑的無聊,想爬點書看看纹笼。 于是我選擇了這個網(wǎng)站雨楓軒。
STEP1.分析網(wǎng)站
一開始我想通過一篇文章引用的鏈接苟跪,將書爬完廷痘,后來發(fā)現(xiàn)并不需要這樣做蔓涧。比如我們可以打開人生哲學(xué)這個欄目。
如圖1所示笋额,會把頁面數(shù)全列出來元暴。
并且這個url
http://txt.rain8.com/txtzx/list_93_1.html
也非常的有規(guī)律。
可以看出是由
'http://txt.rain8.com/txt'+'欄目名稱'+'list_欄目編號_頁數(shù).html'
組成的鳞陨。
知道了這點后昨寞,我們就能輕松的把網(wǎng)站爬完了。
STEP2.初始化
首先我們來理清思路厦滤。
這是我們需要的庫
import requests
import re
import os
其實這個項目用urllib2也能完成援岩。
我們首先來初始化,在self.urls里,我們定義一些需要fetch的欄目掏导。(比如言情享怀,恐怖仙俠之類的書就可以跳過)。然后寫一些正則表達式趟咆,供其他的method使用添瓷。
class fetchBook:
def __init__(self):
self.header = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0'}
self.urls = [
'http://txt.rain8.com/txtgw/',
'http://txt.rain8.com/txtzj/',
'http://txt.rain8.com/txtzx/',
'http://txt.rain8.com/txtsh/'
]
self.rePageIndex = re.compile('list_\d+_\d+.html')#得到欄目編號
self.rePageCount = re.compile('<strong>\d+</strong>')#得到頁面數(shù)目
self.reDownloadGet1 = re.compile('href=.http://txt.rain8.com/plus/xiazai_yfx.php?[^>]+')#得到下載鏈接
self.reGetTitle = re.compile('<title>.+</title>')#得到標(biāo)題
self.reGetAuthor = re.compile("</small><span>[^>]+")#得到作者名稱
self.reBookGetNew = re.compile('')#得到書籍鏈接
self.reBookGetOld = re.compile('')
self.cnt = 0
STEP3.獲取所有的頁面
我們可以查看人生哲學(xué)源代碼≈瞪矗可以找到總共的頁數(shù)鳞贷。
然后我們就能得到每一頁的數(shù)據(jù)。
代碼如下
def viewAllPage(self,url):
"""
函數(shù)功能為把該欄目下所有頁面全過一遍虐唠。
"""
req = requests.get(url,headers = self.header)
pageIndex = self.rePageIndex.findall(req.text)[0][5:7]
pageCount = int(self.rePageCount.findall(req.text)[0][8:-9])
urlToFetch = [url,'list_',pageIndex,'_','1','.html']
foldname = self.reGetTitle.findall(req.text)[0][7:]
foldname = foldname.encode('unicode_escape').decode('string_escape')
foldname = foldname.split('|')[0]
self.createDir(foldname)
for page in range(1,pageCount+1):
urlToFetch[4] = str(page)
url_to_get = ''.join(urlToFetch)#得到所有頁面的url
STEP4.得到下載鏈接
然后我們用上面寫好的正則表達式搀愧,來匹配她的下載鏈接。
def fetchDownloadUrl(self,bookurl):
req = requests.get(bookurl,headers = self.header)
result = self.reDownloadGet1.findall(req.text)
result = result[0][6:-17]
authorname = self.reGetAuthor.findall(req.text)[0][14:-6].encode('unicode_escape').decode('string_escape')
req = requests.get(result,headers = self.header)
bookname = self.reGetTitle.findall(req.text)[0][7:-24]
downloadurl = self.reDownloadGet1.findall(req.text)[0][6:-17]
return downloadurl,bookname,authorname
STEP5.下載
下載的時候疆偿,由于該網(wǎng)站下載的書都是rar格式的咱筛。所以我們只要用二進制的方式寫就可以了。
我們調(diào)用
self.req = requests.get(downloadUrl,headers = self.header)
然后
f = open(posi+'/'+bookname+'.rar','wb')
就可以寫進去了杆故。
STEP6.編碼問題
之前一直被python的編碼問題搞的頭大迅箩,這次又遇見了。于是找了點資料看了看处铛。
因為python工作使用的編碼是unicode饲趋,如果要在編碼間進行轉(zhuǎn)化,推薦要先decode成unicode撤蟆,然后再encode成別的編碼奕塑。
然后我在爬內(nèi)容的過程中碰到了這個問題:
s = u'\xb9\xc5\xca\xab\xb4\xca\xc3\xfb\xd6\xf8'
\xb9這樣的很明顯應(yīng)該是gbk編碼。而python卻在字符串前加了個u枫疆。然后我對這串字符encode還是decode都會報錯爵川。或者打印出來亂碼息楔。
經(jīng)過查閱資料寝贡,我找到了一種解決辦法
s.encode('unicode_escape').decode('string_escape')
經(jīng)過這樣處理后
>>> print repr(s)
>>> '\xb9\xc5\xca\xab\xb4\xca\xc3\xfb\xd6\xf8'
很明顯就恢復(fù)了正常扒披。這時我們只要decode('gb2312')就能轉(zhuǎn)換成unicode編碼了。
STEP7.結(jié)果展示
github地址
喜歡的可以點一下喜歡圃泡。