寫在前面:最近有一個下載整理某網頁上所有文件的任務,打開網頁粗略估算了一下大概有上千個PDF文件需要下載並分類到不同的文件夾,如果用鼠標重復地機械勞動可能要花上一整天...於是乎,我決定嘗試把這個任務交給Python來干!這里就寫一篇Blog來記錄一下~
在不同網站上,下載PDF文檔的鏈接類型有多種,其中最常見的為直接以pdf為后綴的鏈接,比如https://arxiv.org/pdf/2107.09939.pdf。而還有一種情況 (ps. 剛才為了找例子發現這種情況好像不是很多),鏈接沒有pdf作為結尾,如果直接復制該鏈接到下載器中默認解析出來下載的不是PDF文檔而是html頁面,如在瀏覽器中復制該鏈接,Chrome瀏覽器默認打開該PDF的預覽界面,需要再點擊下載才可以進行手動下載。
由於第一種類型的PDF文檔直接使用迅雷、FDM (巨好用,這里安利一下!!)等工具就可以很方便地下載,本人這次也是遇到了第二種類型的情況,本篇Blog就主要關注第二種類型PDF文檔的批量下載。
1 使用Chrome瀏覽器插件Link Grabber抓取頁面上的下載鏈接
在批量下載文檔之前,需要先將文檔的下載鏈接批量獲取,Chrome的Link Grabber插件可以幫上大忙。以MIT的公開課網頁為例,一個課程的網頁上會有很多課程Slides等PDF資料的鏈接。

點擊Link Grabber插件,可以獲取該頁面上的所有下載鏈接,這個頁面上的PDF文檔下載鏈接就是以pdf作為后綴的鏈接。

由於這次任務涉及的網頁不方便公開,這里就沒有第二類鏈接的例子啦~
使用上面的插件獲取下載鏈接之后,復制到一個txt文本中保存,便於后面讀取進行批量訪問。
2 用Python實現自動打開Chrome瀏覽器下載PDF文檔
在搜索如何批量下載第二類PDF文檔的結果時,發現Chrome瀏覽器可以設置瀏覽器訪問該種下載鏈接時直接下載文檔,而不是打開PDF預覽界面。具體設置方法如下:


這么一來,就可以嘗試用Python自動打開Chrome瀏覽器,訪問需要下載的PDF文檔的下載鏈接,就自動直接下載了文件!網上有很多相關博客,例如這一篇。在搜索一系列資料之后,大概摸索出來了如下的實現方案。
2.1 pip安裝selenium
在cmd (mac中的終端)中敲入pip安裝selenium模塊
pip install selenium
2.2 安裝Chrome瀏覽器驅動chromedriver
在這里下載安裝對應Chrome版本的chromedriver,注意之后將下載解壓的文件放在python所在的文件夾下,否則會出現這篇文章中介紹的報錯。

2.3 Python控制Chrome自動網頁登錄
由於很多網頁的下載鏈接需要首先進行用戶登陸才可以進行后續訪問,在Chrome自動訪問下載鏈接之前,需要先寫幾行代碼控制Chrome自動登錄,這里參考了這篇博客(非常詳細 建議收藏!!)實現。注意具體的網頁需要具體分析~ 本人感覺xpath的解析方式比較好用。
2.4 設置Chrome打開鏈接即下載文件及下載到指定文件夾
如本節開頭所說,這個實現方案是通過Chrome設置打開鏈接即下載文件來實現的,所以需要進行相應的設置,同時參考這個頁面進行了下載到指定文件夾的設置。實現的過程中發現文件夾放在桌面上可以自動下載,如果指定某個內部文件夾會彈出下載彈窗。
3 主要代碼塊
主要的代碼總結如下,根據個人下載和整理文件的需求可以進行相應的擴展,比如將不同類的下載鏈接保存到不同的URL.txt中,利用for循環多次下載,通過拼接文件名自動將文檔下載到對應的新文件夾中。
from os import name
from selenium import webdriver
import time
# 設置谷歌瀏覽器打開pdf鏈接時自動下載到指定文件夾
options = webdriver.chrome.options.Options()
download_dir = "/Users/whale/Desktop/Download_PDF" # 這里是自定義的下載文件夾地址
options.add_experimental_option('prefs', {
"download.default_directory": download_dir,
"download.prompt_for_download": False,
"download.directory_upgrade": True,
"plugins.always_open_pdf_externally": True
}
)
path = "/Users/whale/opt/anaconda3/chromedriver"
driver = webdriver.Chrome(path,options=options)
# 登陸網頁,注意代碼因頁面而異
driver.get('https://MainPage/login.com') # 設置登錄頁面的網址
driver.find_element_by_name("username").send_keys('Whale')
driver.find_elements_by_id('password')[0].send_keys('Whale\'s password')
driver.find_element_by_xpath('//*[@id="form1"]/table/tbody/tr/td/table/tbody/tr[4]/td/input[1]').click() # 模擬點擊登陸按鈕
# 讀取URL文件並保存到url_list中
url_list = []
f = open("URL.txt","r")
lines = f.readlines()
for line in lines:
url_list.append(line)
# 逐個訪問下載鏈接,開始自動下載,最后關閉瀏覽器
for url in url_list:
driver.get(url)
time.sleep(5)
time.sleep(100) #注意設置瀏覽器停留時間,一些較大的PDF下載時間較長,需增大等待時間
driver.close()
寫在最后:總的來說雖然上面這個實現方案沒有實現完全的自動化(需要手動復制+保存下載鏈接),但已經極大程度地提高了我的工作效率!上述方案還不能很好地解決文件命名的問題,這里就留一個坑,有機會再想一下如何解決~
參考資料
- 使用selenium模塊訪問谷歌瀏覽器指定頁面: https://www.cnblogs.com/liugx/p/9739639.html
- webdriver打開谷歌瀏覽器報錯: https://blog.csdn.net/cckavin/article/details/79514790
- 使用python + selenium實現瀏覽器自動登錄: https://www.jianshu.com/p/d7a966ec1189
- python逐行讀取文件內容的三種方法: https://blog.csdn.net/fevershen/article/details/81296404
- 設置python調用谷歌瀏覽器下載到指定文件夾 https://www.5axxw.com/questions/content/ptip33