-
首先,需要下載安裝支持工具 wkhtmltopdf
安裝完成後將其下bin目錄的絕對路徑追加到環境變量中
-
之前
import requests import re import os import json import pdfkit HEADERS={ # 設置requests要用到的header 'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.100 Safari/537.36', } # 如果配置了環境變量無法立即生效(大概是需要重啓),可以通過這一行語句添加環境變量 os.environ["PATH"] += os.pathsep + r'C:\Program Files\wkhtmltopdf\bin'
-
獲取所有文章的url
簡單說一下原理,訪問要下載的專欄(我的測試專欄 強化學習前沿)主頁可以發現,主頁顯示的文章列表是動態加載的,每次即將滑動到最底部的時候會動態再加載一批列表出來,通過F12打開檢查模式,抓包到動態請求的鏈接
https://zhuanlan.zhihu.com/api/columns/{}/articles?include=data&limit=10&offset=40
這是開發中分頁顯示的操作,limit是一頁顯示的數量,offset是此頁的起始索引,那麼只要循環幾次就可以獲得所有頁的文章列表了測試發現這裏limit的上限爲100,即請求一次最多獲得100條文章表項
強化學習論文彙總的一種方式
通過檢查當前頁的表項數目,如果少於limit,則視爲最後一頁,不再繼續請求
def getUrls(zhuanlan): ''' :param zhuanlan: such as https://zhuanlan.zhihu.com/reinforcementlearning 傳入的是最後這個reinforcementlearning :return: 返回專欄下所有文章的url ''' urls = [] # p_titles = [] offset = 0 while True: url = 'https://zhuanlan.zhihu.com/api/columns/{}/articles?include=data&limit=100&offset={}'.format(zhuanlan, offset) html_string = requests.get(url,headers=HEADERS).text content = json.loads(html_string) # 獲取的content可以加載爲json格式 urls.extend([item['url'] for item in content['data']]) # 就可以用json的方式索引到所有的url # p_titles.extend([item['title'] for item in content['data']]) # 獲取標題 if len(content['data']) < 100: # 如果獲得的表項不足100,也就是最後一頁 break else: offset += 100 return urls
我自己用正則寫的獲取方式
在主頁中獲取文章總數,求得頁數上限
def getUrls2(zhuanlan): ''' :param zhuanlan: such as https://zhuanlan.zhihu.com/reinforcementlearning 傳入的是最後這個reinforcementlearning :return: 返回專欄下所有文章的url ''' urlindex = 'https://zhuanlan.zhihu.com/{}'.format(zhuanlan) resindex = requests.get(urlindex, headers=HEADERS) # print(resindex.text) matchac = re.search(r'"articlesCount":(\d+),', resindex.text) # 通過正則表達式獲取文章總數 articlesCount = int(matchac.group(1)) upper = articlesCount//100+1 # 下面設置了每頁顯示100條,這裏求總頁數 urls = [] for i in range(upper): urlpage = 'https://zhuanlan.zhihu.com/api/columns/{}/articles?include=data&limit={}&offset={}'.format(zhuanlan, 100, 100*i) # limit最大是100 respage = requests.get(urlpage, headers=HEADERS) respage.encoding = 'unicode_escape' matchurl = re.findall(r'"title":\s"[^"]+?",\s"url":\s"([^"]+?)",', respage.text) # 通過正則匹配url urls+=matchurl return urls
emmm,感覺還是人家寫的簡潔一些
-
mainJob——html to pdf
這裏可以通過兩種方式實現
- 直接通過os.system(wkhtmltopdf命令)執行wkhtmltopdf完成
- 通過集成功能包pdfkit完成,需要安裝pdfkit包
其中碰到的問題就是直接從url->pdf生成的pdf中沒有圖片,這是因爲網頁中的圖片地址採用的是相對地址,這樣直接訪問就無法獲取,講道理得拼接成完整地址,也就是說需要先獲得網頁內容(str),進行一步預處理,再轉成pdf,這裏採用了強化學習論文彙總中的方式進行了處理
def saveArticlesPdf(urls, target_path): os.makedirs(target_path, exist_ok=True) for i, url in enumerate(urls): print('[ {} / {} ] processing'.format(str(i+1).zfill(3), len(urls))) content = requests.get(url, headers=HEADERS).text title = re.search(r'<h1\sclass="Post-Title">(.+)</h1>', content).group(1) content = content.replace('<noscript>', '') # 解決無法下載圖片問題,其中圖片路徑爲相對路徑 content = content.replace('</noscript>', '') try: # 方式一,直接調用wkhtmltopdf的命令 # os.system('wkhtmltopdf {} {}'.format(content, target_path+'/{}.pdf'.format(title))) # 方式二,調用pdfkit包的方式 pdfkit.from_string(content, target_path+'/{}.pdf'.format(title)) except ValueError as e: # 如果出錯打印錯誤 print(title, e)
-
do it
if __name__ == '__main__': zhuanlan = 'reinforcementlearning' # urls = getUrls(zhuanlan) urls = getUrls2(zhuanlan) saveArticlesPdf(urls, 'data/{}'.format(zhuanlan))
運行效果
-
成功的一項
-
失敗的一項
可以從urls中按索引取出失敗的url重新操作,我這裏就不再實現了,注意我在print時爲了顯示效果將索引進行了+1操作
-
-
說明
全部代碼,按順序複製本文代碼亦可執行
-
參考文獻
爬蟲:Python下載html保存成pdf——以下載知乎下某個專欄下所有文章爲例
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.