從VOA慢速英語的網站上下載Mp3與PDF文字的Python指令碼
想通過聽寫練習來提高自己的英語聽力。VOA慢速英語語速很慢(約100-120字/分鐘),發音標準清晰,內容豐富(包括新聞、詞彙諺語、人物故事等),提供錄音及文字下載,是非常不錯的入門聽寫材料。
為什麼要寫指令碼來下載呢?首先,雖然VOA有對應的Podcast節目,更新方便,但下載連結在大陸是無法訪問的,只能看到節目有更新,就是無法下載。其次,每天手動到VOA網站上去下載,似乎太傻瓜,這種重複性地工作應該要自動化處理的。
從網頁中抓取內容是非常常見的應用,處理流程一般就是下載網頁,用正則或其他解析html的工具提取需要的連結,再下載連結內容。在寫這個指令碼的過程中,遇到並解決了以下幾個問題,記錄在此。
- 提取節目的下載連結
- 下載內容時顯示進度條
- 保證檔案能夠完全下載,避免重複下載
- 使用Socks代理來解決GFW的問題
提取節目的下載連結
需要獲取3個資料:節目標題、節目PDF連結、節目Mp3連結。
VOS慢速英語除了Podcast外,還提供了RSS訂閱,可以直接解析RSS內容來獲取Mp3的下載連結;但是RSS輸出中沒有PDF文字的連結,所以我選擇了直接拉取web頁面,用正則來提取內容。
VOA慢速英語目前有7個主題,在每個主題自己的頁面可以看到當月更新的節目(我沒有找到可以列出所有節目的頁面)。在每期節目自己的頁面中,可以找到PDF的下載連結;但是Mp3的連結還需要進入線上收聽頁面才能找到。
這是主題列表頁面部分截圖: 這是某個主題下面最新節目列表頁面部分截圖: 這是PDF下載連結與Mp3線上收聽頁面部分截圖:
下載內容時顯示進度條
知道當前的進度總是一件減少焦慮感的事情。找到需要的下載連結後,使用Python的urllib.urlretrieve()
這個方法來下載檔案。urllib.urlretrieve()
的語法如下:
urlretrieve(url, filename=None, reporthook=None, data=None)
其中,reporthook是接收一定資料後要呼叫的函式,可以利用此回撥函式來實現進度條的功能,reporthook函式的定義如下:
reporthook(blocknum, blocksize, totalsize)
其中,blocknum是接收到的資料包個數,blocksize是資料包的位元組數,totalsize是總的需要下載的位元組數。對傳入的引數進行簡單處理就可以得到當前的下載進度。如果直接用print語句輸出結果的話,每次呼叫此函式都會產生新的一行,這顯然不是進度條的行為,我們希望在同一行更新進度。首先使用sys.stdout.write()
代替print語句可以去掉print自動輸出的換行符。然後,在每次輸出內容時,先輸出回車符('\b')讓游標回到行首,這樣就可以在當前行輸出內容,實現進度條的行為。reporthook函式的程式碼如下:
# show download progress
# 此函式感謝 http://ljdam.iteye.com/blog/1415336 的分享
def reporthook(blocks_read,block_size,total_size):
if not blocks_read:
print ("Connection opened")
if total_size <0:
sys.stdout.write("\rRead %d blocks " % blocks_read)
sys.stdout.flush()
else:
sys.stdout.write("\rdownloading: %d KB, totalsize: %d KB " % (blocks_read*block_size/1024.0,total_size/1024.0))
sys.stdout.flush()
保證檔案能夠完全下載,避免重複下載
首先避免重複下載,當本地已存在待下載檔案時,先從伺服器上獲取待下載的位元組數,與本地檔案對比,如果大小相等,那麼認為已經正常下載,跳過此檔案。這裡存在一個問題,有的伺服器在hearder中不包含Content-Length
這個欄位,這時無法判斷是否已完全下載。考慮到這種情況很少,且重複下載代價較高,所以也不下載此檔案。
if os.path.isfile(file_path):
# check length
length_s = urllib.urlopen( url ).info().get('Content-Length', 0)
length_l = os.path.getsize( file_path )
if length_s == 0 or long(length_s) == length_l:
return True
然後避免出現未下載完成的檔案。在下載時,當關閉程式視窗、手動停止(Ctrl+C)、出現錯誤時,會在檔案系統中殘留未下載完成的檔案,考慮到這種檔案會影響收聽,所以應當避免出現未下載完成的檔案。處理的思路是,如果在下載過程中遇到任何異常,那麼首先刪除未完成的郵件,然後將異常冒泡進行後續處理。
try:
urllib.urlretrieve(url, file_path, reporthook)
except:
os.remove( file_path)
raise
else:
return True
使用Socks代理來解決GFW的問題
首先感謝這個部落格的分享。Python可以通過SocksiPy模組來使用Socks代理。SocksiPy的下載與安裝見官網。這部分的程式碼如下:
import socks
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, '127.0.0.1', 9050, rdns=False)
socket.socket = socks.socksocket
這裡首先設定了socks的代理資訊,socks.PROXY_TYPE_SOCKS5
表示型別為socks5,127.0.0.1
與9050
分別是代理的IP與埠。我這裡使用的是本機作為代理。然後用具有代理功能的套接字覆蓋系統預設的套接字,後續連線就全部走代理了,非常方便。
完整程式碼請訪問這個gist。最後是程式執行截圖:
相關文章
- 英語學習網站學習網站
- 英語學習的網站和Blog推薦-轉載整理網站
- 英語學習網站大全學習網站
- 10個免費下載PHP指令碼的網站PHP指令碼網站
- 不錯的IT書籍下載網站 - 指令碼之家網站指令碼
- 10個提供免費PHP指令碼下載的網站PHP指令碼網站
- 大耳朵英語 - 不錯的英文學習網站學習網站
- 推薦16個下載超酷指令碼的熱門網站指令碼網站
- 大資料網站英語學習大資料網站
- 基本英語的學習與掌握 - 英語學習者的福音
- Linux 如何從網上下載檔案Linux
- TP開發的原始碼下載站系統,素材下載站原始碼系統,線上下載原始碼系統原始碼
- 有求 bing 的四大英語翻譯網站網站
- 測試網站頁面網速的一個簡單Python指令碼網站Python指令碼
- 一個線上下載地圖XYZ瓦片的網站實現地圖網站
- 如何用Python從PDF檔案中提取文字詞彙Python
- 網際網路大佬們的英語故事
- PDF英語文件怎麼翻譯成中文?
- 清華社互動英語視聽說答題指令碼的使用說明指令碼
- 英語資料下載
- 一個網站故障排查的、程式碼更新的簡便指令碼網站指令碼
- 網站指令碼語言有哪些優缺點?網路安全入門網站指令碼
- 如何從GitHub上下載來客原始碼並執行?Github原始碼
- Python需要懂英語嗎?英語基礎很重要嗎?Python
- Python 提取PDF文字和圖片Python
- jQuery 跨站指令碼漏洞影響大量網站jQuery指令碼網站
- PHP動態網頁設計與網站架設pdfPHP網頁網站
- 金山愛詞霸網站被掛馬上網學英語需注意網站
- 匯出 VuePress構建的網站為 PDFVue網站
- Python 英語單詞本Python
- jQuery 網站公告上下輪播jQuery網站
- 英語《聖經》的版本
- 網站怎麼又有書的原始碼下載?網站原始碼
- GitLab 中文版如何禁止從 UI 上下載程式碼?GitlabUI
- Python 查詢PDF中的指定文字並高亮顯示Python
- python監控mysql主從指令碼PythonMySql指令碼
- 編譯語言、解釋語言與指令碼語言之間的區別編譯指令碼
- 從英語小白到技術書籍譯者:讓英語成為你的職場加速器