-
首先,需要下载安装支持工具 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——以下载知乎下某个专栏下所有文章为例
最新推荐文章于 2024-08-06 04:17:42 发布