注:源碼已更新,支持指定開始下載章節,默認步長為10,直至全部下載完成,保證為完整的mp3音頻文件。
有經驗的老鳥都(未婚的)會在公司附近租房,免受舟車勞頓之苦的同時節約了大把時間;也有些人出於某種原因需要每天披星戴月地游走於公司於家之間,很不幸俺就是這其中一員。由於家和公司離得比較遠,我平時在公交車上的時間占據了工作時間段的1/4,再加上杭州一向有中國的拉斯維加斯之稱(堵城),每每堵起來,哥都能想象自己成為變形金剛。這段漫長時間我想作為每個程序猿來說是無法忍受的,可是既然短時間無法改變生存的現狀,咱就好好利用這段時間吧。所以,我特地買了大屏幕的Note II 以便看pdf,另外耳朵也不能閑着,不過咱不是聽英語而是聽小說,我在讀書的時候就喜歡聽廣播,特別是說書、相聲等,所以我需要大量的有聲小說,現在網上這些資源多的很,但是下載頁記為麻煩,為了掙取更多的流量和廣告點擊,這些網站的下載鏈接都需要打開至少兩個以上的網頁才能找到真正的鏈接,甚是麻煩,為了節省整體下載時間,我寫了這個小程序,方便自己和大家下載有聲小說(當然,還有任何其他類型的資源)
先說明一下,我不是為了爬很多資料和數據,僅僅是為了娛樂和學習,所以這里不會漫無目的的取爬取一個網站的所有鏈接,而是給定一個小說,比方說我要下載小說《童年》,我會在我聽評書網上找到該小說的主頁然后用程序下載所有mp3音頻,具體做法見下面代碼,所有代碼都在模塊crawler5tps中:
1. 先設定一下start url 和保存文件的目錄
1 #-*-coding:GBK-*- 2 import urllib,urllib2 3 import re,threading,os 4 5 6 baseurl = 'http://www.5tps.com' #base url 7 down2path = 'E:/enovel/' #saving path 8 save2path = '' #saving file name (full path)
2. 從start url 解析下載頁面的url
1 def parseUrl(starturl): 2 ''' 3 parse out download page from start url. 4 eg. we can get 'http://www.5tps.com/down/8297_52_1_1.html' from 'http://www.5tps.com/html/8297.html' 5 ''' 6 global save2path 7 rDownloadUrl = re.compile(".*?<A href=\'(/down/\w+\.html)\'.*") #find the link of download page 8 #rTitle = re.compile("<TITILE>.{4}\s{1}(.*)\s{1}.*</TITLE>") 9 #<TITLE>有聲小說 悶騷1 播音:劉濤 全集</TITLE> 10 f = urllib2.urlopen(starturl) 11 totalLine = f.readlines() 12
''' create the name of saving file ''' 13 title = totalLine[3].split(" ")[1] 14 if os.path.exists(down2path+title) is not True: 15 os.mkdir(down2path+title) 16 save2path = down2path+title+"/" 17 18 downUrlLine = [ line for line in totalLine if rDownloadUrl.match(line)] 19 downLoadUrl = []; 20 for dl in downUrlLine: 21 while True: 22 m = rDownloadUrl.match(dl) 23 if not m: 24 break 25 downUrl = m.group(1) 26 downLoadUrl.append(downUrl.strip()) 27 dl = dl.replace(downUrl,'') 28 return downLoadUrl
3. 從下載頁面解析出真正的下載鏈接
1 def getDownlaodLink(starturl): 2 ''' 3 find out the real download link from download page. 4 eg. we can get the download link 'http://180j-d.ysts8.com:8000/人物紀實/童年/001.mp3?\ 5 1251746750178x1356330062x1251747362932-3492f04cf54428055a110a176297d95a' from \ 6 'http://www.5tps.com/down/8297_52_1_1.html' 7 ''' 8 downUrl = [] 9 gbk_ClickWord = '點此下載' 10 downloadUrl = parseUrl(starturl) 11 rDownUrl = re.compile('<a href=\"(.*)\"><font color=\"blue\">'+gbk_ClickWord+'.*</a>') #find the real download link 12 for url in downloadUrl: 13 realurl = baseurl+url 14 print realurl 15 for line in urllib2.urlopen(realurl).readlines(): 16 m = rDownUrl.match(line) 17 if m: 18 downUrl.append(m.group(1)) 19 20 return downUrl
4. 定義下載函數
1 def download(url,filename): 2 ''' download mp3 file ''' 3 print url 4 urllib.urlretrieve(url, filename)
5. 創建用於下載文件的線程類
1 class DownloadThread(threading.Thread): 2 ''' dowanload thread class ''' 3 def __init__(self,url,savePath): 4 threading.Thread.__init__(self) 5 self.url = url 6 self.savePath = savePath 7 8 def run(self): 9 download(self.url,self.savePath)
6. 開始下載
1 if __name__ == '__main__': 2 starturl = 'http://www.5tps.com/html/8297.html' 3 downUrl = getDownlaodLink(starturl) 4 aliveThreadDict = {} # alive thread 5 downloadingUrlDict = {} # downloading link 6 7 i = 0; 8 while i < len(downUrl): 9 ''' Note:我聽評說網 只允許同時有三個線程下載同一部小說,但是有時受網絡等影響,\ 10 為確保下載的是真實的mp3,這里將線程數設為2 ''' 11 while len(downloadingUrlDict)< 2 : 12 downloadingUrlDict[i]=i 13 i += 1 14 for urlIndex in downloadingUrlDict.values(): 15 #argsTuple = (downUrl[urlIndex],save2path+str(urlIndex+1)+'.mp3') 16 if urlIndex not in aliveThreadDict.values(): 17 t = DownloadThread(downUrl[urlIndex],save2path+str(urlIndex+1)+'.mp3') 18 t.start() 19 aliveThreadDict[t]=urlIndex 20 for (th,urlIndex) in aliveThreadDict.items(): 21 if th.isAlive() is not True: 22 del aliveThreadDict[th] # delete the thread slot 23 del downloadingUrlDict[urlIndex] # delete the url from url list needed to download 24 25 print 'Completed Download Work'
這樣就可以了,讓他盡情的下吧,咱還得碼其他的項目去,哎 >>>
等下了班copy到Note中就可以一邊聽小說一邊看資料啦,最后附上源碼。