用Python自動下載網站所有文件
最近維基 jie mi 徹底公開瞭網站的全部文件,我就在想如何使用 Python 將其下載到本地永久保存,於是就有瞭這篇文章,寫爬蟲會遇到很多坑,借鑒他人經驗,考慮越全面,出錯的概率就越小。
假如一個網站,裡面有很多鏈接,有指向文件的,有指向新鏈接的,新的鏈接點擊進去後,仍然是有指向文件的,有指向新鏈接的,類似一個文件夾,裡面即有文件,又有目錄,目錄中又有文件和目錄。如何從這樣的網站上下載所有的文件,並按網站的目錄結構來保存這些文件呢?
關鍵詞:Python、下載、正則表達式、遞歸。
按照自頂向下來設計程序,我們整理自己的思路,然後使用 Python 語言來翻譯下即可。
思路:由於目錄的深度不固定,也不可能窮舉,且每一個目錄的處理方式和子目錄父目錄的處理流程都是一樣的,因此我們可以使用遞歸來下載所有文件。
遞歸代碼必須要有退出條件,退出條件要放在前面,本例中的遞歸退出條件就是:如果是文件就下載,下載完遞歸函數即完成任務。
總體思路:
1、給定一個 url,判斷是否是文件,如果是文件,下載即可,然後函數結束。
2、如果給定 url 不是文件,那麼訪問該 url,並獲取它下面的所有鏈接。
3、遍歷步驟 2 產生的所有鏈接,遞歸的執行步驟 1 和 2,直到程序運行結束。
以上思路,用代碼描述如下:
import urllib.request import requests import re, os def get_file(url): ''' 遞歸下載網站的文件 :param url: :return: ''' if isFile(url): print(url) try: download(url) except: pass else: urls = get_url(url) for u in urls: get_file(u)
前面導入的包在接下來函數中會用到,下面就是逐漸層向下,實現子功能。
判斷鏈接是否指向文件:
這裡總結 url 規律,很容易寫出。
def isFile(url): ''' 判斷一個鏈接是否是文件 :param url: :return: ''' if url.endswith('/'): return False else: return True
下載文件:
下載文件時要從 url 中獲取文件應該存儲的位置,並使用 os.makedirs 來創建多級目錄。然後使用 urllib.request.urlretrieve 來下載文件。
def download(url): ''' :param url:文件鏈接 :return: 下載文件,自動創建目錄 ''' full_name = url.split('//')[-1] filename = full_name.split('/')[-1] dirname = "/".join(full_name.split('/')[:-1]) if os.path.exists(dirname): pass else: os.makedirs(dirname, exist_ok=True) urllib.request.urlretrieve(url, full_name)
獲取 url 下的所有鏈接:
這裡要具體網站具體分析,看看如何使用正則表達式獲取網頁中的鏈接,這樣的正則表達式可以說是再簡單不過瞭。
def get_url(base_url): ''' :param base_url:給定一個網址 :return: 獲取給定網址中的所有鏈接 ''' text = '' try: text = requests.get(base_url).text except Exception as e: print("error - > ",base_url,e) pass reg = '<a href="(.*)" rel="external nofollow" >.*</a>' urls = [base_url + url for url in re.findall(reg, text) if url != '../'] return urls
這裡有個小坑,就是網站有個鏈接是返回上級頁面的,url 的後輟是 ‘../’ 這樣的鏈接要去掉,否則遞歸函數就限入瞭死循環。
接下來就是寫主函數,執行任務瞭,慢慢等它下載完吧。
if __name__ == '__main__': get_file('https://file.wikileaks.org/file/')
其實,還會存兩個問題:
1、假如網站某頁有個鏈接它指向瞭首頁,那麼遞歸程序仍然會限入一個死循環,解決方法就是將訪問過的 url 保存在一個列表裡(或者其他數據結構),如果接下來要訪問的 url 不在此列表中,那麼就訪問,否則就忽略。
2、如果下載的過程中程序突然報錯退出瞭,由於下載文件較慢,為瞭節約時間,那麼如何讓程序從報錯處繼續運行呢?這裡可采用分層遞歸,一開始時先獲取網站的所有一級 url 鏈接,順序遍歷這些一級 url 鏈接,執行上述的 get_file(url) ,每訪問一次一級 url 就將其索引位置加1(索引位置默認為0,存儲在文件中或數據庫中),程序中斷後再運行時先讀取索引,然後從索引處開始執行即可。另外,每下載成功一個文件,就把對應的 url 也保存在文件中或數據庫中,如果一級 url 下的鏈接已經下載過文件,那麼就不需要重新下載瞭。
以上就是用Python自動下載網站所有文件的詳細內容,更多關於python 自動下載網站文件的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- Python Django搭建文件下載服務器的實現
- 利用python爬取m3u8格式視頻的具體實現
- Python 批量下載陰陽師網站壁紙
- python urllib和urllib3知識點總結
- 如何用Python一次性下載抖音上音樂