zsky 发表于 2020-2-18 00:41

文泉学堂PDF(带书签)下载原理详细讲解_python脚本实现1秒1页

本帖最后由 L15263458908 于 2020-2-18 01:30 编辑

前言
      前段时间,文泉课堂开放免费阅读,许多朋友想要下载自己喜欢的电子书,但是却遇到了很多麻烦,有的是下载的不清晰,有的是根本不会下载,只得论坛发悬赏求助,这里写出下载文泉学堂PDF的原理和实现,希望能解答某些朋友的疑惑,虽然文泉学堂现在已经关闭开放,但仍然有免费畅读模块可以免费阅读,这些图书可以供大家进行测试。
https://lib-nuanxin.wqxuetang.com/



整体思路
       随便打开一本书


       我们可以发现,每一页其实都是一张图片,因此我们可以把所有的图片保存下来,然后再用python脚本合成PDF,左边的目录对应书签,我们可以通过获取HTML进行解析获得,然后再通过python对PDF进行添加书签,然后一本带书签的PDF文件就下载完毕了。



所以,★我们的整体思路是:
   下载高清图片---->合成PDF---->下载书签---->给PDF添加书签
下面就开始具体的讲解每一步

详细过程
1、下载高清图片
我们右键点击第一页图片审查元素(右键,检查),发现此页图片和下一页图片是高清的,但是其他页图片是缩略图


我们打开第3页,发现第1页和第2页又变成了缩略图,而第4页又变为高清


又经过多次试验,我们发现,高清图片每次加载2张,并且仅有2张,其他页面的图片都是模糊的
而图片在这里采用的是base64加密,于是我们的突破口是左上角的输入页码的框


       我们可以在左上角的框中依次输入1,3,5,7。。。。每次输入完之后保存图片然后进行下一次输入,这里我采用的是python的selenium模块进行模拟,然后用webdriver.Chrome()对象的page_source来获取当前页面的html文档(关于selenium的学习大家自行百度,这里不再讲解),获取到html文档之后再用BeautifulSoup获取base64加密的图片数据,然后base64解密,获取图片的分辨率,如果>500(判断是不是缩略图)就保存图片(这里我采用的是io模块的BytesIO和PIL模块的Image)
def get_image_size(content) :
    """
    :param content: 图片的二进制数据,不用保存图片到硬盘
    :return: 图片的宽高
    """
    tmpIm = BytesIO(content)
    im = Image.open(tmpIm)
    w = im.size# 宽
    h = im.size# 高
    return w, h

就这样,依次往复,获取到所有的图片,当然这其中还有一些其他的问题,到文章最后的时候再解答

2、合成PDF
关于合成PDF,在网上也能找到python对应的库,大家可以参考这篇文章
https://blog.devzeng.com/blog/python-convert-images-to-pdf.html
打不开的朋友看这里(我把网页保存为PDF了)
链接:https://pan.baidu.com/s/196O1AP1m3PDzeZu5Iel3lw
提取码:ared

from reportlab.lib.pagesizes import A4, portrait, landscape, mm
from reportlab.pdfgen import canvas

def convert_images_to_pdf(img_path, pdf_path, size, pdf_count) :
    """
    将图片合成为PDF
    :param img_path:图片文件夹路径
    :param pdf_path:PDF文件路径(包含PDF文件名)
    :param size: PDF的尺寸
    :param pdf_count: PDF的总页数
    :return:
    """
    pages = 0
    (w, h) = size
    c = canvas.Canvas(pdf_path, pagesize=portrait((w, h)))
    l = os.listdir(img_path)
    l.sort(key=lambda x : int(x[:-5]))      # 因为后缀都是.jpeg,所以是-5,对图片进行排序
    for i in l :
      f = img_path + os.sep + str(i)
      c.drawImage(f, 0, 0, w, h)
      c.showPage()
      pages = pages + 1
      print("添加进度: %f%%   \r" % ((pages / pdf_count) * 100))
    c.save()

在保存PDF的时候,需要获取PDF书本的名字,这里我们要通过打开PDF的那个页面获取



我们打开F12,刷新页面,检测数据包,发现以下数据包可以获取到名字


所以,在获取PDF名字的时候,只需要知道知道书本的id然后拼成url,访问这个url就行了

def get_pdf_name() :
    """
    :return: 将要下载PDF书籍的名字
    """
    try :
      index = url.find("pdf")
      name_url = "https://lib-nuanxin.wqxuetang.com/v1/book/initbook?bid=" + url
      headers = {
            'Accept' : 'application/json, text/plain, */*',
            'Accept-Encoding' : 'gzip, deflate, br',
            'Accept-Language' : 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7',
            'BA' : 'bapkg/com.bookask.wqxuetang baver/0.0.1',
            'Cache-Control' : 'no-cache',
            'Connection' : 'keep-alive',
            'Cookie' : str_cookie,
            'Host' : 'lib-nuanxin.wqxuetang.com',
            'Pragma' : 'no-cache',
            'Referer' : 'https://lib-nuanxin.wqxuetang.com/',
            'Sec-Fetch-Dest' : 'empty',
            'Sec-Fetch-Mode' : 'cors',
            'Sec-Fetch-Site' : 'same-origin',
            'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.100 Safari/537.36'
      }

      res = requests.get(name_url, headers=headers)
      dict = res.json()
      return dict['data']['name']
    except :
      return "default"


3、下载书签
关于书签的下载,我们对左边目录进行审查元素


用BeautifulSoup进行筛选即可,不过这里要注意一个问题就是子书签必须得所有目录展开之后才能在html文档中出现


所以我们必须用python模拟,依次点击左边的小三角形使其展开,然后再保存html文档筛选书签即可,这里我是把书签保存为列表了
4、给PDF添加书签
给PDF添加书签,我使用的是python的PyPDF2模块

from PyPDF2 import PdfFileReader, PdfFileWriter
def add_shu_q(shu_q, pdf_path) :
    """
    书签的列表格式
    无子书签:
    有子书签: ,...... ]]
    根据shu_q列表来对PDF文件添加书签
    :param shu_q:
    :return:
    """
    # 读取PDF文件,创建PdfFileReader对象
    book = PdfFileReader(pdf_path)

    # 创建PdfFileWriter对象,并用拷贝reader对象进行初始化
    pdf = PdfFileWriter()
    pdf.cloneDocumentFromReader(book)

    # 添加书签
    # 注意:页数是从0开始的,中文要用unicode字符串,否则会出现乱码
    # 如果这里的页码超过文档的最大页数,会报IndexError异常

    for i in range(len(shu_q)) :
      parent = pdf.addBookmark(shu_q, int(shu_q) - 1)
      if shu_q != 0 :# 如果有子书签
            for j in range(len(shu_q)) :
                pdf.addBookmark(shu_q, int(shu_q) - 1, parent=parent)

    # 保存修改后的PDF文件内容到文件中
    # 注意:这里必须用二进制的'wb'模式来写文件,否则写到文件中的内容都为乱码
    with open(pdf_path, 'wb') as fout :
      pdf.write(fout)


注意事项
整个过程中,最最核心的就是下载高清图片了,其他的都是小事,那么,在下载图片的过程中,前面我提到过,会出现一些问题,这里我罗列一下
       1、下载速度过快,可能在下载的过程中,在页面中弹出滑动验证的框
       2、下载速度过快,可能会封IP,至于封IP,又会出现两种情况
            2.1 无论怎么刷新,图片都无法变为高清
            2.2 无法打开文泉学堂的页面,打开页面的时候会显示页面加载失败

解决方法(这里都是自己这几天的实验自己总结出来的)

[*]       1、在下载之前,一定要自己在浏览器中先打开那个页面,不断刷新
[*]       2、经常换IP,每下载上100页就换一次IP
[*]       3、换cookie,每下载一本书,换一下代码中的cookie值
经过这样处理,还是会出现封IP的情况,不过已经缓解很多了我感觉,整体上基本实现了1页1秒的速度,也就是10分钟基本1本书就下完了


全部代码
这里我所有的代码都整合到了一个py文件当中,需要修改的主要是下面的str_cookie值


而cookie值就是你刷新一下文泉学堂的页面,得到的下面那个值



这里不知道是什么原因,我想把代码全部粘贴到这里来着,但是排版总是乱的,所以我把它放到百度网盘里了
链接:https://pan.baidu.com/s/1mbmWK-ysfx_CjfecEqnmog
提取码:gvpl

成果图展示


不对,贴错了,是下面那个。。。


由于吾爱上传图片大小的限制,这里只截取了部分动图,下面是完整的效果视频
链接:https://pan.baidu.com/s/1u5rx9dvd275DboWBf_rJ4A
提取码:mpk5
下载这篇54页的PDF只用了44秒


最后但是很重要
       最后,请下载完之后不要传播或营利,还有疫情严重,大家尽量不要出门,在家里就是最安全的,今天我一个朋友因为出门聚餐,被人举报,被遣送回家了。。。。

最后的最后,希望大家可以点一下下面的评分,您的评分是对这篇文章的最大支持,感谢,祝你们身体健康,生活愉快

zsky 发表于 2020-2-19 17:27

shazhugon 发表于 2020-2-19 17:20
兄弟能再帮我提取一本书吗?我送你一些CB

行,不过书本必须是免费的,现在

lanhezero 发表于 2020-2-18 23:48

C:\ProgramData\Anaconda3\python.exe D:/360安全浏览器下载/main.py
Traceback (most recent call last):
File "D:/360安全浏览器下载/main.py", line 7, in <module>
    from reportlab.lib.pagesizes import A4, portrait, landscape, mm
ModuleNotFoundError: No module named 'reportlab'

Process finished with exit code 1

请教这个报错怎么回事?另外PYCHARM一直下不了reportlab库是什么原因?已经改豆瓣镜像站更新,谢谢指教{:1_893:}

gls5566 发表于 2020-2-18 00:55

感谢分享!

goblin0427 发表于 2020-2-18 01:14

感谢大佬分享

zsky 发表于 2020-2-18 01:16

本帖最后由 L15263458908 于 2020-2-18 01:34 编辑

goblin0427 发表于 2020-2-18 01:14
感谢大佬分享
。。。。一直在编辑。。怎么最后全部代码粘贴进去是乱的啊,,,,,,,:'(weeqw

yaerhuo 发表于 2020-2-18 01:37

感谢大佬分享

shazhugon 发表于 2020-2-18 01:43

小白不懂啊,有成品下载的软件就好了,其实楼主你下的这本书我想要

wsdhgd 发表于 2020-2-18 01:49

终于收到渔了

yxb020 发表于 2020-2-18 02:13

太感谢楼主了,最近正在学习python爬虫,非常好的例程

verner 发表于 2020-2-18 07:22

刚开始学Python,还看不明白,收藏当参考资料,谢谢分享。

不苦小和尚 发表于 2020-2-18 07:23

非常时期楼主尽量少外出,注意身体健康
页: [1] 2 3 4 5 6 7
查看完整版本: 文泉学堂PDF(带书签)下载原理详细讲解_python脚本实现1秒1页